From 0610296248584b2ae42425953bd07cbb8b83452d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 8 Dec 2017 19:39:33 +0100 Subject: [PATCH] [d3d11] Implemented constant buffer binding --- src/d3d11/d3d11_context.cpp | 81 +++++++++++++++++++++++++---- src/d3d11/d3d11_context.h | 7 +++ src/d3d11/d3d11_context_state.h | 33 ++++++------ src/dxbc/gen/dxbc_gen_common.cpp | 7 +++ src/dxbc/gen/dxbc_gen_common.h | 3 +- src/dxbc/gen/dxbc_gen_pixel.cpp | 4 +- src/dxbc/gen/dxbc_gen_vertex.cpp | 6 ++- src/dxvk/dxvk_context.cpp | 37 +++++++------ src/spirv/spirv_module.cpp | 10 ++++ src/spirv/spirv_module.h | 4 ++ tests/d3d11/test_d3d11_triangle.cpp | 64 ++++++++++++----------- 11 files changed, 178 insertions(+), 78 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 7e942827..a331f4cc 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -113,7 +113,7 @@ namespace dxvk { // this->IASetIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0); this->VSSetShader(nullptr, nullptr, 0); -// this->VSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, nullptr); + this->VSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, nullptr); // this->VSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, nullptr); // this->VSSetSamplers (0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, nullptr); @@ -133,7 +133,7 @@ namespace dxvk { // this->GSSetSamplers (0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, nullptr); this->PSSetShader(nullptr, nullptr, 0); -// this->PSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, nullptr); + this->PSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, nullptr); // this->PSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, nullptr); // this->PSSetSamplers (0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, nullptr); @@ -360,7 +360,32 @@ namespace dxvk { const void* pSrcData, UINT SrcRowPitch, UINT SrcDepthPitch) { - Logger::err("D3D11DeviceContext::UpdateSubresource: Not implemented"); + // We need a different code path for buffers + D3D11_RESOURCE_DIMENSION resourceType; + pDstResource->GetType(&resourceType); + + if (resourceType == D3D11_RESOURCE_DIMENSION_BUFFER) { + Com bufferResource; + + pDstResource->QueryInterface( + __uuidof(IDXGIBufferResourcePrivate), + reinterpret_cast(&bufferResource)); + + VkDeviceSize offset = 0; + VkDeviceSize size = VK_WHOLE_SIZE; + + if (pDstBox != nullptr) { + offset = pDstBox->left; + size = pDstBox->right - pDstBox->left; + } + + m_context->updateBuffer( + bufferResource->GetDXVKBuffer(), + offset, size, pSrcData); + } else { + Logger::err("D3D11DeviceContext::UpdateSubresource: Images not yet supported"); + } + } @@ -613,16 +638,10 @@ namespace dxvk { switch (binding.format) { case DXGI_FORMAT_R16_UINT: indexType = VK_INDEX_TYPE_UINT16; break; case DXGI_FORMAT_R32_UINT: indexType = VK_INDEX_TYPE_UINT32; break; - - default: - Logger::err(str::format( - "D3D11DeviceContext::IASetIndexBuffer: Invalid index format: ", - binding.format)); } m_context->bindIndexBuffer( dxvkBinding, indexType); - } @@ -676,7 +695,11 @@ namespace dxvk { UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers) { - Logger::err("D3D11DeviceContext::VSSetConstantBuffers: Not implemented"); + this->BindConstantBuffers( + D3D11ShaderStage::VertexShader, + &m_state.vs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers); } @@ -942,7 +965,11 @@ namespace dxvk { UINT StartSlot, UINT NumBuffers, ID3D11Buffer* const* ppConstantBuffers) { - Logger::err("D3D11DeviceContext::PSSetConstantBuffers: Not implemented"); + this->BindConstantBuffers( + D3D11ShaderStage::PixelShader, + &m_state.vs.constantBuffers, + StartSlot, NumBuffers, + ppConstantBuffers); } @@ -1301,6 +1328,38 @@ namespace dxvk { } + void D3D11DeviceContext::BindConstantBuffers( + D3D11ShaderStage ShaderStage, + D3D11ConstantBufferBindings* pBindings, + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers) { + for (uint32_t i = 0; i < NumBuffers; i++) { + D3D11Buffer* buffer = nullptr; + + if (ppConstantBuffers != nullptr) + buffer = static_cast(ppConstantBuffers[i]); + + if (pBindings->at(StartSlot + i) != buffer) { + pBindings->at(StartSlot + i) = buffer; + + DxvkBufferBinding dxvkBinding; + + if (buffer != nullptr) { + dxvkBinding = DxvkBufferBinding( + buffer->GetDXVKBuffer(), + 0, VK_WHOLE_SIZE); + } + + // TODO compute actual slot index + m_context->bindResourceBuffer( + VK_PIPELINE_BIND_POINT_GRAPHICS, 0, + dxvkBinding); + } + } + } + + void D3D11DeviceContext::ApplyViewportState() { // We cannot set less than one viewport in Vulkan, and // rendering with no active viewport is illegal anyway. diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index a69d6148..b86dd7bc 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -554,6 +554,13 @@ namespace dxvk { D3D11ContextState m_state; + void BindConstantBuffers( + D3D11ShaderStage ShaderStage, + D3D11ConstantBufferBindings* pBindings, + UINT StartSlot, + UINT NumBuffers, + ID3D11Buffer* const* ppConstantBuffers); + void ApplyViewportState(); void SetupIAStateObjects(); diff --git a/src/d3d11/d3d11_context_state.h b/src/d3d11/d3d11_context_state.h index 41dcac51..31bc2896 100644 --- a/src/d3d11/d3d11_context_state.h +++ b/src/d3d11/d3d11_context_state.h @@ -10,54 +10,51 @@ namespace dxvk { - struct D3D11ComputePipelineBindings { - std::array, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT> constantBuffers; -// std::array, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> shaderResourceViews; -// std::array, D3D11_1_UAV_SLOT_COUNT> uniformAccessViews; -// std::array, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT> samplers; - }; - - - struct D3D11GraphicsPipelineBindings { - std::array, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT> constantBuffers; -// std::array, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT> shaderResourceViews; -// std::array, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT> samplers; + enum class D3D11ShaderStage { + VertexShader = 0, + HullShader = 1, + DomainShader = 2, + GeometryShader = 3, + PixelShader = 4, + ComputeShader = 5, }; + using D3D11ConstantBufferBindings = std::array< + Com, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT>; struct D3D11ContextStateVS { Com shader; - D3D11GraphicsPipelineBindings bindings; + D3D11ConstantBufferBindings constantBuffers; }; struct D3D11ContextStateHS { Com shader; - D3D11GraphicsPipelineBindings bindings; + D3D11ConstantBufferBindings constantBuffers; }; struct D3D11ContextStateDS { Com shader; - D3D11GraphicsPipelineBindings bindings; + D3D11ConstantBufferBindings constantBuffers; }; struct D3D11ContextStateGS { Com shader; - D3D11GraphicsPipelineBindings bindings; + D3D11ConstantBufferBindings constantBuffers; }; struct D3D11ContextStatePS { Com shader; - D3D11GraphicsPipelineBindings bindings; + D3D11ConstantBufferBindings constantBuffers; }; struct D3D11ContextStateCS { Com shader; - D3D11ComputePipelineBindings bindings; + D3D11ConstantBufferBindings constantBuffers; }; diff --git a/src/dxbc/gen/dxbc_gen_common.cpp b/src/dxbc/gen/dxbc_gen_common.cpp index 3629ba90..e4f26995 100644 --- a/src/dxbc/gen/dxbc_gen_common.cpp +++ b/src/dxbc/gen/dxbc_gen_common.cpp @@ -43,6 +43,7 @@ namespace dxvk { DxbcValueType(DxbcScalarType::Float32, 4, elementCount)); uint32_t structType = m_module.defStructType(1, &arrayType); + m_module.decorateArrayStride(arrayType, 16); m_module.memberDecorateOffset(structType, 0, 0); m_module.decorateBlock(structType); @@ -50,8 +51,14 @@ namespace dxvk { m_module.defPointerType(structType, spv::StorageClassUniform), spv::StorageClassUniform); + m_module.setDebugName(varIndex, str::format("cb", bufferId).c_str()); + m_module.decorateDescriptorSet(varIndex, 0); + m_module.decorateBinding(varIndex, 0); m_constantBuffers.at(bufferId).varId = varIndex; m_constantBuffers.at(bufferId).size = elementCount; + + // TODO compute resource slot index + m_resourceSlots.push_back({ 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER }); } diff --git a/src/dxbc/gen/dxbc_gen_common.h b/src/dxbc/gen/dxbc_gen_common.h index 77bb014e..4bf7c08a 100644 --- a/src/dxbc/gen/dxbc_gen_common.h +++ b/src/dxbc/gen/dxbc_gen_common.h @@ -156,7 +156,8 @@ namespace dxvk { std::vector m_rRegs; - std::array m_constantBuffers; + std::array m_constantBuffers; + std::vector m_resourceSlots; uint32_t defScalarType( DxbcScalarType type); diff --git a/src/dxbc/gen/dxbc_gen_pixel.cpp b/src/dxbc/gen/dxbc_gen_pixel.cpp index 6bf9afcd..86bcf355 100644 --- a/src/dxbc/gen/dxbc_gen_pixel.cpp +++ b/src/dxbc/gen/dxbc_gen_pixel.cpp @@ -60,6 +60,7 @@ namespace dxvk { m_module.decorateLocation(var.valueId, regId); m_module.setDebugName(var.valueId, str::format("v", regId).c_str()); + m_entryPointInterfaces.push_back(var.valueId); switch (im) { case DxbcInterpolationMode::Undefined: @@ -168,7 +169,8 @@ namespace dxvk { return new DxvkShader( VK_SHADER_STAGE_FRAGMENT_BIT, - 0, nullptr, + m_resourceSlots.size(), + m_resourceSlots.data(), m_module.compile()); } diff --git a/src/dxbc/gen/dxbc_gen_vertex.cpp b/src/dxbc/gen/dxbc_gen_vertex.cpp index 6894df71..1c8dfdcb 100644 --- a/src/dxbc/gen/dxbc_gen_vertex.cpp +++ b/src/dxbc/gen/dxbc_gen_vertex.cpp @@ -48,6 +48,7 @@ namespace dxvk { m_module.decorateLocation(m_vRegs.at(regId).valueId, regId); m_module.setDebugName(m_vRegs.at(regId).valueId, str::format("v", regId).c_str()); + m_entryPointInterfaces.push_back(m_vRegs.at(regId).valueId); } if (sv != DxbcSystemValue::None) { @@ -64,6 +65,7 @@ namespace dxvk { m_module.decorateLocation(m_oRegs.at(regId).valueId, regId); m_module.setDebugName(m_oRegs.at(regId).valueId, str::format("o", regId).c_str()); + m_entryPointInterfaces.push_back(m_oRegs.at(regId).valueId); } if (sv != DxbcSystemValue::None) { @@ -134,7 +136,8 @@ namespace dxvk { return new DxvkShader( VK_SHADER_STAGE_VERTEX_BIT, - 0, nullptr, + m_resourceSlots.size(), + m_resourceSlots.data(), m_module.compile()); } @@ -160,6 +163,7 @@ namespace dxvk { this->regStore(this->ptrBuiltInPosition(), srcValue, DxbcComponentMask(true, true, true, true)); } break; + default: ; } } } diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index f8b176ac..7d33e358 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -340,26 +340,29 @@ namespace dxvk { VkDeviceSize offset, VkDeviceSize size, const void* data) { + this->renderPassEnd(); - if (size == 0) - return; + if (size == VK_WHOLE_SIZE) + size = buffer->info().size; - if (size <= 65536) { - m_cmd->cmdUpdateBuffer( - buffer->handle(), - offset, size, data); - } else { - // TODO implement - Logger::err("DxvkContext::updateBuffer: Large updates not yet supported"); + if (size != 0) { + if (size <= 65536) { + m_cmd->cmdUpdateBuffer( + buffer->handle(), + offset, size, data); + } else { + // TODO implement + Logger::err("DxvkContext::updateBuffer: Large updates not yet supported"); + } + + m_barriers.accessBuffer( + buffer, offset, size, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + buffer->info().stages, + buffer->info().access); + m_barriers.recordCommands(m_cmd); } - - m_barriers.accessBuffer( - buffer, offset, size, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT, - buffer->info().stages, - buffer->info().access); - m_barriers.recordCommands(m_cmd); } diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index db02a9d9..0a1bf642 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -238,6 +238,16 @@ namespace dxvk { } + void SpirvModule::decorateArrayStride( + uint32_t object, + uint32_t stride) { + m_annotations.putIns (spv::OpDecorate, 4); + m_annotations.putWord (object); + m_annotations.putWord (spv::DecorationArrayStride); + m_annotations.putInt32(stride); + } + + void SpirvModule::decorateBinding( uint32_t object, uint32_t binding) { diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 1a02cd17..f06a76d1 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -88,6 +88,10 @@ namespace dxvk { uint32_t object, spv::Decoration decoration); + void decorateArrayStride( + uint32_t object, + uint32_t stride); + void decorateBinding( uint32_t object, uint32_t binding); diff --git a/tests/d3d11/test_d3d11_triangle.cpp b/tests/d3d11/test_d3d11_triangle.cpp index 11c10941..c60d9992 100644 --- a/tests/d3d11/test_d3d11_triangle.cpp +++ b/tests/d3d11/test_d3d11_triangle.cpp @@ -14,32 +14,17 @@ struct Extent2D { struct Vertex { float x, y, z, w; - float r, g, b, a; }; const std::string g_vertexShaderCode = - "struct VsInput {\n" - " float4 position : IN_POSITION;\n" - " float4 color : IN_COLOR;\n" - "};\n" - "struct VsOutput {\n" - " float4 position : SV_POSITION;\n" - " float4 color : PS_COLOR;\n" - "};\n" - "VsOutput main(VsInput vsIn) {\n" - " VsOutput vsOut;\n" - " vsOut.position = vsIn.position;\n" - " vsOut.color = vsIn.color;\n" - " return vsOut;\n" + "float4 main(float4 vsIn : IN_POSITION) : SV_POSITION {\n" + " return vsIn;\n" "}\n"; const std::string g_pixelShaderCode = - "struct PsInput {\n" - " float4 position : SV_POSITION;\n" - " float4 color : PS_COLOR;\n" - "};\n" - "float4 main(PsInput psIn) : SV_TARGET {\n" - " return psIn.color;\n" + "cbuffer c_buffer { float4 ccolor[2]; };\n" + "float4 main() : SV_TARGET {\n" + " return ccolor[0];\n" "}\n"; class TriangleApp { @@ -97,9 +82,9 @@ public: throw DxvkError("Failed to resize window"); std::array vertexData = {{ - { -0.5f, -0.5f, 0.0f, 1.0f, 0.03f, 0.03f, 0.03f, 1.0f }, - { 0.0f, 0.5f, 0.0f, 1.0f, 0.03f, 0.03f, 0.03f, 1.0f }, - { 0.5f, -0.5f, 0.0f, 1.0f, 0.03f, 0.03f, 0.03f, 1.0f }, + { -0.5f, -0.5f, 0.0f, 1.0f }, + { 0.0f, 0.5f, 0.0f, 1.0f }, + { 0.5f, -0.5f, 0.0f, 1.0f }, }}; D3D11_BUFFER_DESC vertexDesc; @@ -115,6 +100,30 @@ public: vertexDataInfo.SysMemPitch = 0; vertexDataInfo.SysMemSlicePitch = 0; + if (FAILED(m_device->CreateBuffer(&vertexDesc, &vertexDataInfo, &m_vertexBuffer))) + throw DxvkError("Failed to create vertex buffer"); + + std::array constantData = {{ + { 0.03f, 0.03f, 0.03f, 1.0f }, + { 1.00f, 1.00f, 1.00f, 1.0f }, + }}; + + D3D11_BUFFER_DESC constantDesc; + constantDesc.ByteWidth = sizeof(Vertex) * constantData.size(); + constantDesc.Usage = D3D11_USAGE_IMMUTABLE; + constantDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantDesc.CPUAccessFlags = 0; + constantDesc.MiscFlags = 0; + constantDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA constantDataInfo; + constantDataInfo.pSysMem = constantData.data(); + constantDataInfo.SysMemPitch = 0; + constantDataInfo.SysMemSlicePitch = 0; + + if (FAILED(m_device->CreateBuffer(&constantDesc, &constantDataInfo, &m_constantBuffer))) + throw DxvkError("Failed to create constant buffer"); + Com vertexShaderBlob; Com pixelShaderBlob; @@ -150,13 +159,8 @@ public: nullptr, &m_pixelShader))) throw DxvkError("Failed to create pixel shader"); - - if (FAILED(m_device->CreateBuffer(&vertexDesc, &vertexDataInfo, &m_vertexBuffer))) - throw DxvkError("Failed to create vertex buffer"); - - std::array vertexFormatDesc = {{ + std::array vertexFormatDesc = {{ { "IN_POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(Vertex, x), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "IN_COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(Vertex, r), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }}; if (FAILED(m_device->CreateInputLayout( @@ -193,6 +197,7 @@ public: m_context->VSSetShader(m_vertexShader.ptr(), nullptr, 0); m_context->PSSetShader(m_pixelShader.ptr(), nullptr, 0); + m_context->PSSetConstantBuffers(0, 1, &m_constantBuffer); UINT vsStride = sizeof(Vertex); UINT vsOffset = 0; @@ -247,6 +252,7 @@ private: Com m_buffer; Com m_bufferView; + Com m_constantBuffer; Com m_vertexBuffer; Com m_vertexFormat;