diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 6d16d03e5f..86851ed67f 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1254,17 +1254,73 @@ void BufferCache

::BindHostTransformFeedbackBuffers() { if (maxwell3d->regs.transform_feedback_enabled == 0) { return; } - HostBindings host_bindings; - for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) { + const auto is_active = [&](u32 index) { const Binding& binding = channel_state->transform_feedback_buffers[index]; const auto& control = maxwell3d->regs.transform_feedback.controls[index]; const bool has_layout = control.varying_count != 0 || control.stride != 0; + return has_layout && binding.buffer_id != NULL_BUFFER_ID && binding.size != 0; + }; + + std::array window_indices{}; + std::array window_offsets{}; + u32 window_mask = 0; + if constexpr (USE_UNIFIED_DIRECT_BINDING) { + if (runtime.SupportsUnifiedTransformFeedbackBinding()) { + for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) { + if (!is_active(index)) { + continue; + } + const Binding& binding = channel_state->transform_feedback_buffers[index]; + if (binding.size > runtime.UnifiedMaxTransformFeedbackBufferSize()) { + continue; + } + if (ResolveUnifiedDirectBinding(binding.device_addr, binding.size, + UNIFIED_TRANSFORM_FEEDBACK_BINDING_ALIGNMENT, + window_indices[index], window_offsets[index])) { + window_mask |= 1u << index; + } + } + } + } + + if constexpr (USE_UNIFIED_DIRECT_BINDING) { + if (window_mask != 0) { + for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) { + const Binding& binding = channel_state->transform_feedback_buffers[index]; + if (((window_mask >> index) & 1) != 0) { + TouchBuffer(slot_buffers[binding.buffer_id], binding.buffer_id); + MarkWrittenBufferInPlace(binding.device_addr, binding.size); + runtime.BindTransformFeedbackBufferFromWindow( + index, window_indices[index], static_cast(window_offsets[index]), + binding.size); + continue; + } + if (!is_active(index)) { + runtime.BindNullTransformFeedbackBuffer(index); + continue; + } + Buffer& buffer = slot_buffers[binding.buffer_id]; + TouchBuffer(buffer, binding.buffer_id); + const u32 size = binding.size; + SynchronizeBuffer(buffer, binding.device_addr, size); + MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size); + const u32 offset = buffer.Offset(binding.device_addr); + buffer.MarkUsage(offset, size); + runtime.BindTransformFeedbackBuffer(index, buffer, offset, size); + } + return; + } + } + + HostBindings host_bindings; + for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) { + const Binding& binding = channel_state->transform_feedback_buffers[index]; Buffer* host_buffer = &slot_buffers[NULL_BUFFER_ID]; u32 offset = 0; u32 size = 0; - if (has_layout && binding.buffer_id != NULL_BUFFER_ID && binding.size != 0) { + if (is_active(index)) { Buffer& buffer = slot_buffers[binding.buffer_id]; TouchBuffer(buffer, binding.buffer_id); size = binding.size; diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index 97bcc65f92..8368986b9e 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -184,6 +184,7 @@ class BufferCache : public VideoCommon::ChannelSetupCaches GetMaxComputeWorkGroupCount() const { const auto& count = properties.properties.limits.maxComputeWorkGroupCount; return {count[0], count[1], count[2]};