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:
parent
078bc27b14
commit
fb70de8852
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user