1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-01 16:24:12 +01:00

[dxvk] Reimplement vertex buffer bindings

Reduces the number of Vulkan calls for vertex buffer bindings and
works around incorrect validation errors emitted when applications
do not use a consecutive range of vertex bindings. No performance
impact is expected in most games.
This commit is contained in:
Philip Rebohle 2018-05-09 13:01:52 +02:00
parent b6d33e6289
commit 47b9fd8b19
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99

View File

@ -1945,29 +1945,51 @@ namespace dxvk {
if (m_flags.test(DxvkContextFlag::GpDirtyVertexBuffers)) {
m_flags.clr(DxvkContextFlag::GpDirtyVertexBuffers);
uint32_t bindingMask = 0;
std::array<VkBuffer, MaxNumVertexBindings> buffers;
std::array<VkDeviceSize, MaxNumVertexBindings> offsets;
// Set buffer handles and offsets for active bindings
uint32_t bindingCount = 0;
uint32_t bindingMask = 0;
for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) {
const uint32_t binding = m_state.gp.state.ilBindings[i].binding;
bindingCount = std::max(bindingCount, binding + 1);
if (m_state.vi.vertexBuffers[binding].defined()) {
auto vbo = m_state.vi.vertexBuffers[binding].physicalSlice();
const VkBuffer handle = vbo.handle();
const VkDeviceSize offset = vbo.offset();
m_cmd->cmdBindVertexBuffers(binding, 1, &handle, &offset);
m_cmd->trackResource(vbo.resource());
buffers[binding] = vbo.handle();
offsets[binding] = vbo.offset();
bindingMask |= 1u << binding;
} else {
const VkBuffer handle = m_device->dummyBufferHandle();
const VkDeviceSize offset = 0;
m_cmd->cmdBindVertexBuffers(binding, 1, &handle, &offset);
m_cmd->trackResource(vbo.resource());
}
}
// Bind a dummy buffer to the remaining bindings
uint32_t bindingsUsed = (1u << bindingCount) - 1u;
uint32_t bindingsSet = bindingMask;
while (bindingsSet != bindingsUsed) {
uint32_t binding = 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) {
m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
m_state.vi.bindingMask = bindingMask;