1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-11-30 13:24:10 +01:00

[dxvk] Optimize vertex buffer binding

If there are gaps in the binding numbers, we don't want to
create overhead by iterating over unused bindings.
This commit is contained in:
Philip Rebohle 2019-05-08 00:19:14 +02:00
parent 078bc27b14
commit fb70de8852
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99

View File

@ -3678,51 +3678,47 @@ namespace dxvk {
std::array<VkDeviceSize, MaxNumVertexBindings> offsets; std::array<VkDeviceSize, MaxNumVertexBindings> offsets;
// Set buffer handles and offsets for active bindings // Set buffer handles and offsets for active bindings
uint32_t bindingCount = 0; uint32_t bindingMask = 0;
uint32_t bindingMask = 0;
for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) { for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) {
const uint32_t binding = m_state.gp.state.ilBindings[i].binding; uint32_t binding = m_state.gp.state.ilBindings[i].binding;
bindingCount = std::max(bindingCount, binding + 1); bindingMask |= 1u << binding;
if (m_state.vi.vertexBuffers[binding].defined()) { if (likely(m_state.vi.vertexBuffers[binding].defined())) {
auto vbo = m_state.vi.vertexBuffers[binding].getDescriptor(); auto vbo = m_state.vi.vertexBuffers[binding].getDescriptor();
buffers[binding] = vbo.buffer.buffer; buffers[binding] = vbo.buffer.buffer;
offsets[binding] = vbo.buffer.offset; offsets[binding] = vbo.buffer.offset;
bindingMask |= 1u << binding;
m_cmd->trackResource(m_state.vi.vertexBuffers[binding].buffer()); m_cmd->trackResource(m_state.vi.vertexBuffers[binding].buffer());
} else {
buffers[binding] = m_device->dummyBufferHandle();
offsets[binding] = 0;
} }
} }
// Bind a dummy buffer to the remaining bindings // Adjust stride of inactive bindings if needed
uint32_t bindingsUsed = (1u << bindingCount) - 1u;
uint32_t bindingsSet = bindingMask;
while (bindingsSet != bindingsUsed) {
uint32_t binding = bit::tzcnt(~bindingsSet);
buffers[binding] = m_device->dummyBufferHandle();
offsets[binding] = 0;
bindingsSet |= 1u << binding;
}
// Bind all vertex buffers at once
if (bindingCount != 0) {
m_cmd->cmdBindVertexBuffers(0, bindingCount,
buffers.data(), offsets.data());
}
// If the set of active bindings has changed, we'll
// need to adjust the strides of the inactive ones
// and compile a new pipeline
if (m_state.vi.bindingMask != bindingMask) { if (m_state.vi.bindingMask != bindingMask) {
m_flags.set(DxvkContextFlag::GpDirtyPipelineState); m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
m_state.vi.bindingMask = bindingMask; m_state.vi.bindingMask = bindingMask;
} }
// Actually bind all the vertex buffers
uint32_t bindingIndex = 0;
while (bindingMask) {
uint32_t shift = bit::tzcnt(bindingMask);
uint32_t count = bit::tzcnt(~bindingMask >> shift);
uint32_t index = bindingIndex + shift;
m_cmd->cmdBindVertexBuffers(
index, count,
&buffers[index],
&offsets[index]);
bindingIndex += shift + count;
bindingMask >>= shift + count;
}
} }
} }