|
|
|
@ -1254,17 +1254,73 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() { |
|
|
|
if (maxwell3d->regs.transform_feedback_enabled == 0) { |
|
|
|
return; |
|
|
|
} |
|
|
|
HostBindings<typename P::Buffer> 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<u64, NUM_TRANSFORM_FEEDBACK_BUFFERS> window_indices{}; |
|
|
|
std::array<u64, NUM_TRANSFORM_FEEDBACK_BUFFERS> 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<u32>(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<typename P::Buffer> 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; |
|
|
|
|