|
|
@ -805,47 +805,43 @@ void BufferCache<P>::UpdateVertexBufferSlot(u32 index, const Binding& binding) { |
|
|
|
|
|
|
|
|
template <class P> |
|
|
template <class P> |
|
|
void BufferCache<P>::BindHostVertexBuffers() { |
|
|
void BufferCache<P>::BindHostVertexBuffers() { |
|
|
|
|
|
HostBindings<typename P::Buffer> host_bindings; |
|
|
|
|
|
bool any_valid{false}; |
|
|
auto& flags = maxwell3d->dirty.flags; |
|
|
auto& flags = maxwell3d->dirty.flags; |
|
|
u32 enabled_mask = enabled_vertex_buffers_mask; |
|
|
|
|
|
HostBindings<Buffer> bindings{}; |
|
|
|
|
|
u32 last_index = std::numeric_limits<u32>::max(); |
|
|
|
|
|
const auto flush_bindings = [&]() { |
|
|
|
|
|
if (bindings.buffers.empty()) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
bindings.max_index = bindings.min_index + static_cast<u32>(bindings.buffers.size()); |
|
|
|
|
|
runtime.BindVertexBuffers(bindings); |
|
|
|
|
|
bindings = HostBindings<Buffer>{}; |
|
|
|
|
|
last_index = std::numeric_limits<u32>::max(); |
|
|
|
|
|
}; |
|
|
|
|
|
while (enabled_mask != 0) { |
|
|
|
|
|
const u32 index = std::countr_zero(enabled_mask); |
|
|
|
|
|
enabled_mask &= (enabled_mask - 1); |
|
|
|
|
|
const Binding& binding = VertexBufferSlot(index); |
|
|
|
|
|
|
|
|
for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) { |
|
|
|
|
|
const Binding& binding = channel_state->vertex_buffers[index]; |
|
|
Buffer& buffer = slot_buffers[binding.buffer_id]; |
|
|
Buffer& buffer = slot_buffers[binding.buffer_id]; |
|
|
TouchBuffer(buffer, binding.buffer_id); |
|
|
TouchBuffer(buffer, binding.buffer_id); |
|
|
SynchronizeBuffer(buffer, binding.device_addr, binding.size); |
|
|
SynchronizeBuffer(buffer, binding.device_addr, binding.size); |
|
|
if (!flags[Dirty::VertexBuffer0 + index]) { |
|
|
if (!flags[Dirty::VertexBuffer0 + index]) { |
|
|
flush_bindings(); |
|
|
|
|
|
continue; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
flags[Dirty::VertexBuffer0 + index] = false; |
|
|
flags[Dirty::VertexBuffer0 + index] = false; |
|
|
|
|
|
|
|
|
|
|
|
host_bindings.min_index = (std::min)(host_bindings.min_index, index); |
|
|
|
|
|
host_bindings.max_index = (std::max)(host_bindings.max_index, index); |
|
|
|
|
|
any_valid = true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (any_valid) { |
|
|
|
|
|
host_bindings.max_index++; |
|
|
|
|
|
for (u32 index = host_bindings.min_index; index < host_bindings.max_index; index++) { |
|
|
|
|
|
flags[Dirty::VertexBuffer0 + index] = false; |
|
|
|
|
|
|
|
|
|
|
|
const Binding& binding = channel_state->vertex_buffers[index]; |
|
|
|
|
|
Buffer& buffer = slot_buffers[binding.buffer_id]; |
|
|
|
|
|
|
|
|
const u32 stride = maxwell3d->regs.vertex_streams[index].stride; |
|
|
const u32 stride = maxwell3d->regs.vertex_streams[index].stride; |
|
|
const u32 offset = buffer.Offset(binding.device_addr); |
|
|
const u32 offset = buffer.Offset(binding.device_addr); |
|
|
buffer.MarkUsage(offset, binding.size); |
|
|
buffer.MarkUsage(offset, binding.size); |
|
|
if (!bindings.buffers.empty() && index != last_index + 1) { |
|
|
|
|
|
flush_bindings(); |
|
|
|
|
|
} |
|
|
|
|
|
if (bindings.buffers.empty()) { |
|
|
|
|
|
bindings.min_index = index; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
host_bindings.buffers.push_back(&buffer); |
|
|
|
|
|
host_bindings.offsets.push_back(offset); |
|
|
|
|
|
host_bindings.sizes.push_back(binding.size); |
|
|
|
|
|
host_bindings.strides.push_back(stride); |
|
|
} |
|
|
} |
|
|
bindings.buffers.push_back(&buffer); |
|
|
|
|
|
bindings.offsets.push_back(offset); |
|
|
|
|
|
bindings.sizes.push_back(binding.size); |
|
|
|
|
|
bindings.strides.push_back(stride); |
|
|
|
|
|
last_index = index; |
|
|
|
|
|
|
|
|
runtime.BindVertexBuffers(host_bindings); |
|
|
} |
|
|
} |
|
|
flush_bindings(); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
template <class P> |
|
|
template <class P> |
|
|
|