From c7e33e636e4a7dcdd23ed2859d958629c4ef453c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Mon, 8 Jan 2018 20:23:21 +0100 Subject: [PATCH] [dxvk] Fixed vertex buffer binding issue If an application binds vertex buffers before changing the input layout, it might happen that the vertex buffers are not bound correctly to the Vulkan command buffer. This issue is now resolved. --- src/d3d11/d3d11_device.cpp | 27 +++++++++++--- src/dxvk/dxvk_context.cpp | 75 ++++++++++++++++++++++++++------------ 2 files changed, 74 insertions(+), 28 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index d135345a..ca33273d 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -659,7 +659,7 @@ namespace dxvk { pShaderBytecodeWithInputSignature), BytecodeLength); DxbcModule dxbcModule(dxbcReader); - Rc inputSignature = dxbcModule.isgn(); + const Rc inputSignature = dxbcModule.isgn(); std::vector attributes; std::vector bindings; @@ -707,7 +707,7 @@ namespace dxvk { // Create vertex input binding description. The // stride is dynamic state in D3D11 and will be - // set by STDMETHODCALLTYPE D3D11DeviceContext::IASetVertexBuffers. + // set by D3D11DeviceContext::IASetVertexBuffers. DxvkVertexBinding binding; binding.binding = pInputElementDescs[i].InputSlot; binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; @@ -716,8 +716,8 @@ namespace dxvk { binding.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; if (pInputElementDescs[i].InstanceDataStepRate != 1) { - Logger::err(str::format( - "D3D11Device::CreateInputLayout: Unsupported instance data step rate: ", + Logger::warn(str::format( + "D3D11Device: Unsupported instance data step rate: ", pInputElementDescs[i].InstanceDataStepRate)); } } @@ -732,7 +732,7 @@ namespace dxvk { if (binding.inputRate != existingBinding.inputRate) { Logger::err(str::format( - "D3D11Device::CreateInputLayout: Conflicting input rate for binding ", + "D3D11Device: Conflicting input rate for binding ", binding.binding)); return E_INVALIDARG; } @@ -743,6 +743,23 @@ namespace dxvk { bindings.push_back(binding); } + // Check if there are any semantics defined in the + // shader that are not included in the current input + // layout. + for (auto i = inputSignature->begin(); i != inputSignature->end(); i++) { + bool found = i->systemValue != DxbcSystemValue::None; + + for (uint32_t j = 0; j < attributes.size() && !found; j++) + found = attributes.at(j).location == i->registerId; + + if (!found) { + Logger::warn(str::format( + "D3D11Device: Vertex input '", + i->semanticName, i->semanticIndex, + "' not defined by input layout")); + } + } + // Create the actual input layout object // if the application requests it. if (ppInputLayout != nullptr) { diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index f89d685f..c644e961 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -805,7 +805,10 @@ namespace dxvk { const DxvkVertexAttribute* attributes, uint32_t bindingCount, const DxvkVertexBinding* bindings) { - m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + m_flags.set( + DxvkContextFlag::GpDirtyPipelineState, + DxvkContextFlag::GpDirtyIndexBuffer, + DxvkContextFlag::GpDirtyVertexBuffers); m_state.il.numAttributes = attributeCount; m_state.il.numBindings = bindingCount; @@ -1033,36 +1036,58 @@ namespace dxvk { switch (binding.type) { case VK_DESCRIPTOR_TYPE_SAMPLER: - m_descriptors[i].image.sampler = res.sampler->handle(); - m_descriptors[i].image.imageView = VK_NULL_HANDLE; - m_descriptors[i].image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - m_cmd->trackResource(res.sampler); - break; + if (res.sampler != nullptr) { + m_descriptors[i].image.sampler = res.sampler->handle(); + m_descriptors[i].image.imageView = VK_NULL_HANDLE; + m_descriptors[i].image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + m_cmd->trackResource(res.sampler); + } else { + Logger::err("DxvkContext: Unbound sampler descriptor"); + m_descriptors[i].image.sampler = VK_NULL_HANDLE; + m_descriptors[i].image.imageView = VK_NULL_HANDLE; + m_descriptors[i].image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } break; case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: - m_descriptors[i].image.sampler = VK_NULL_HANDLE; - m_descriptors[i].image.imageView = res.imageView->handle(); - m_descriptors[i].image.imageLayout = res.imageView->imageInfo().layout; - - m_cmd->trackResource(res.imageView); - m_cmd->trackResource(res.imageView->image()); - break; + if (res.imageView != nullptr) { + m_descriptors[i].image.sampler = VK_NULL_HANDLE; + m_descriptors[i].image.imageView = res.imageView->handle(); + m_descriptors[i].image.imageLayout = res.imageView->imageInfo().layout; + + m_cmd->trackResource(res.imageView); + m_cmd->trackResource(res.imageView->image()); + } else { + Logger::err("DxvkContext: Unbound image descriptor"); + m_descriptors[i].image.sampler = VK_NULL_HANDLE; + m_descriptors[i].image.imageView = VK_NULL_HANDLE; + m_descriptors[i].image.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; + } break; case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: - m_descriptors[i].texelBuffer = res.bufferView->handle(); - - m_cmd->trackResource(res.bufferView); - m_cmd->trackResource(res.bufferView->buffer()->resource()); - break; + if (res.bufferView != nullptr) { + m_descriptors[i].texelBuffer = res.bufferView->handle(); + + m_cmd->trackResource(res.bufferView); + m_cmd->trackResource(res.bufferView->buffer()->resource()); + } else { + Logger::err("DxvkContext: Unbound texel buffer"); + m_descriptors[i].texelBuffer = VK_NULL_HANDLE; + } break; case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: - m_descriptors[i].buffer = res.bufferSlice.descriptorInfo(); - m_cmd->trackResource(res.bufferSlice.resource()); - break; + if (res.bufferSlice.handle() != VK_NULL_HANDLE) { + m_descriptors[i].buffer = res.bufferSlice.descriptorInfo(); + m_cmd->trackResource(res.bufferSlice.resource()); + } else { + Logger::err("DxvkContext: Unbound buffer"); + m_descriptors[i].buffer.buffer = VK_NULL_HANDLE; + m_descriptors[i].buffer.offset = 0; + m_descriptors[i].buffer.range = 0; + } break; default: Logger::err(str::format("DxvkContext: Unhandled descriptor type: ", binding.type)); @@ -1135,8 +1160,12 @@ namespace dxvk { const VkDeviceSize offset = vbo.offset(); if (handle != VK_NULL_HANDLE) { - m_cmd->cmdBindVertexBuffers(i, 1, &handle, &offset); + m_cmd->cmdBindVertexBuffers( + m_state.il.bindings[i].binding, + 1, &handle, &offset); m_cmd->trackResource(vbo.resource()); + } else { + Logger::err(str::format("DxvkContext: Unbound vertex buffer: ", i)); } } }