From 43661abbfc1cb8d3669c810fa48a1df0f93e8f79 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 3 Aug 2022 17:55:39 +0200 Subject: [PATCH] [d3d11] Add binding methods to D3D11CommonContext Uses mutable lambdas to avoid redundant ref counting on immediate contexts. --- src/d3d11/d3d11_context_common.cpp | 266 +++++++++++++++++++++++++++++ src/d3d11/d3d11_context_common.h | 56 ++++++ 2 files changed, 322 insertions(+) diff --git a/src/d3d11/d3d11_context_common.cpp b/src/d3d11/d3d11_context_common.cpp index 188d9b344..e694fadf6 100644 --- a/src/d3d11/d3d11_context_common.cpp +++ b/src/d3d11/d3d11_context_common.cpp @@ -96,6 +96,272 @@ namespace dxvk { } + template + template + void D3D11CommonContext::BindShader( + const D3D11CommonShader* pShaderModule) { + // Bind the shader and the ICB at once + EmitCs([ + cSlice = pShaderModule != nullptr + && pShaderModule->GetIcb() != nullptr + ? DxvkBufferSlice(pShaderModule->GetIcb()) + : DxvkBufferSlice(), + cShader = pShaderModule != nullptr + ? pShaderModule->GetShader() + : nullptr + ] (DxvkContext* ctx) mutable { + VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); + + uint32_t slotId = computeConstantBufferBinding(ShaderStage, + D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); + + ctx->bindShader(stage, + Forwarder::move(cShader)); + ctx->bindResourceBuffer(stage, slotId, + Forwarder::move(cSlice)); + }); + } + + + template + void D3D11CommonContext::BindFramebuffer() { + DxvkRenderTargets attachments; + uint32_t sampleCount = 0; + + // D3D11 doesn't have the concept of a framebuffer object, + // so we'll just create a new one every time the render + // target bindings are updated. Set up the attachments. + for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) { + if (m_state.om.renderTargetViews[i] != nullptr) { + attachments.color[i] = { + m_state.om.renderTargetViews[i]->GetImageView(), + m_state.om.renderTargetViews[i]->GetRenderLayout() }; + sampleCount = m_state.om.renderTargetViews[i]->GetSampleCount(); + } + } + + if (m_state.om.depthStencilView != nullptr) { + attachments.depth = { + m_state.om.depthStencilView->GetImageView(), + m_state.om.depthStencilView->GetRenderLayout() }; + sampleCount = m_state.om.depthStencilView->GetSampleCount(); + } + + // Create and bind the framebuffer object to the context + EmitCs([ + cAttachments = std::move(attachments) + ] (DxvkContext* ctx) mutable { + ctx->bindRenderTargets(Forwarder::move(cAttachments)); + }); + + // If necessary, update push constant for the sample count + if (m_state.om.sampleCount != sampleCount) { + m_state.om.sampleCount = sampleCount; + ApplyRasterizerSampleCount(); + } + } + + + template + void D3D11CommonContext::BindDrawBuffers( + D3D11Buffer* pBufferForArgs, + D3D11Buffer* pBufferForCount) { + EmitCs([ + cArgBuffer = pBufferForArgs ? pBufferForArgs->GetBufferSlice() : DxvkBufferSlice(), + cCntBuffer = pBufferForCount ? pBufferForCount->GetBufferSlice() : DxvkBufferSlice() + ] (DxvkContext* ctx) mutable { + ctx->bindDrawBuffers( + Forwarder::move(cArgBuffer), + Forwarder::move(cCntBuffer)); + }); + } + + + template + void D3D11CommonContext::BindVertexBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset, + UINT Stride) { + if (likely(pBuffer != nullptr)) { + EmitCs([ + cSlotId = Slot, + cBufferSlice = pBuffer->GetBufferSlice(Offset), + cStride = Stride + ] (DxvkContext* ctx) mutable { + ctx->bindVertexBuffer(cSlotId, + Forwarder::move(cBufferSlice), + cStride); + }); + } else { + EmitCs([ + cSlotId = Slot + ] (DxvkContext* ctx) { + ctx->bindVertexBuffer(cSlotId, DxvkBufferSlice(), 0); + }); + } + } + + + template + void D3D11CommonContext::BindIndexBuffer( + D3D11Buffer* pBuffer, + UINT Offset, + DXGI_FORMAT Format) { + VkIndexType indexType = Format == DXGI_FORMAT_R16_UINT + ? VK_INDEX_TYPE_UINT16 + : VK_INDEX_TYPE_UINT32; + + EmitCs([ + cBufferSlice = pBuffer != nullptr ? pBuffer->GetBufferSlice(Offset) : DxvkBufferSlice(), + cIndexType = indexType + ] (DxvkContext* ctx) mutable { + ctx->bindIndexBuffer( + Forwarder::move(cBufferSlice), + cIndexType); + }); + } + + + template + void D3D11CommonContext::BindXfbBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset) { + DxvkBufferSlice bufferSlice; + DxvkBufferSlice counterSlice; + + if (pBuffer != nullptr) { + bufferSlice = pBuffer->GetBufferSlice(); + counterSlice = pBuffer->GetSOCounter(); + } + + EmitCs([ + cSlotId = Slot, + cOffset = Offset, + cBufferSlice = bufferSlice, + cCounterSlice = counterSlice + ] (DxvkContext* ctx) mutable { + if (cCounterSlice.defined() && cOffset != ~0u) { + ctx->updateBuffer( + cCounterSlice.buffer(), + cCounterSlice.offset(), + sizeof(cOffset), + &cOffset); + } + + ctx->bindXfbBuffer(cSlotId, + Forwarder::move(cBufferSlice), + Forwarder::move(cCounterSlice)); + }); + } + + + template + template + void D3D11CommonContext::BindConstantBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset, + UINT Length) { + EmitCs([ + cSlotId = Slot, + cBufferSlice = pBuffer ? pBuffer->GetBufferSlice(16 * Offset, 16 * Length) : DxvkBufferSlice() + ] (DxvkContext* ctx) mutable { + VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); + ctx->bindResourceBuffer(stage, cSlotId, + Forwarder::move(cBufferSlice)); + }); + } + + + template + template + void D3D11CommonContext::BindConstantBufferRange( + UINT Slot, + UINT Offset, + UINT Length) { + EmitCs([ + cSlotId = Slot, + cOffset = 16 * Offset, + cLength = 16 * Length + ] (DxvkContext* ctx) { + VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); + ctx->bindResourceBufferRange(stage, cSlotId, cOffset, cLength); + }); + } + + + template + template + void D3D11CommonContext::BindSampler( + UINT Slot, + D3D11SamplerState* pSampler) { + EmitCs([ + cSlotId = Slot, + cSampler = pSampler != nullptr ? pSampler->GetDXVKSampler() : nullptr + ] (DxvkContext* ctx) mutable { + VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); + ctx->bindResourceSampler(stage, cSlotId, + Forwarder::move(cSampler)); + }); + } + + + template + template + void D3D11CommonContext::BindShaderResource( + UINT Slot, + D3D11ShaderResourceView* pResource) { + EmitCs([ + cSlotId = Slot, + cImageView = pResource != nullptr ? pResource->GetImageView() : nullptr, + cBufferView = pResource != nullptr ? pResource->GetBufferView() : nullptr + ] (DxvkContext* ctx) mutable { + VkShaderStageFlagBits stage = GetShaderStage(ShaderStage); + ctx->bindResourceView(stage, cSlotId, + Forwarder::move(cImageView), + Forwarder::move(cBufferView)); + }); + } + + + template + template + void D3D11CommonContext::BindUnorderedAccessView( + UINT UavSlot, + D3D11UnorderedAccessView* pUav, + UINT CtrSlot, + UINT Counter) { + EmitCs([ + cUavSlotId = UavSlot, + cCtrSlotId = CtrSlot, + cImageView = pUav != nullptr ? pUav->GetImageView() : nullptr, + cBufferView = pUav != nullptr ? pUav->GetBufferView() : nullptr, + cCounterSlice = pUav != nullptr ? pUav->GetCounterSlice() : DxvkBufferSlice(), + cCounterValue = Counter + ] (DxvkContext* ctx) mutable { + VkShaderStageFlags stages = ShaderStage == DxbcProgramType::PixelShader + ? VK_SHADER_STAGE_ALL_GRAPHICS + : VK_SHADER_STAGE_COMPUTE_BIT; + + if (cCounterSlice.defined() && cCounterValue != ~0u) { + ctx->updateBuffer( + cCounterSlice.buffer(), + cCounterSlice.offset(), + sizeof(uint32_t), + &cCounterValue); + } + + ctx->bindResourceView(stages, cUavSlotId, + Forwarder::move(cImageView), + Forwarder::move(cBufferView)); + ctx->bindResourceBuffer(stages, cCtrSlotId, + Forwarder::move(cCounterSlice)); + }); + } + + template void D3D11CommonContext::UpdateResource( ID3D11Resource* pDstResource, diff --git a/src/d3d11/d3d11_context_common.h b/src/d3d11/d3d11_context_common.h index 544e8b0c9..49b2870ef 100644 --- a/src/d3d11/d3d11_context_common.h +++ b/src/d3d11/d3d11_context_common.h @@ -92,6 +92,62 @@ namespace dxvk { D3D11DeviceContextExt m_contextExt; D3D11UserDefinedAnnotation m_annotation; + template + void BindShader( + const D3D11CommonShader* pShaderModule); + + void BindFramebuffer(); + + void BindDrawBuffers( + D3D11Buffer* pBufferForArgs, + D3D11Buffer* pBufferForCount); + + void BindVertexBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset, + UINT Stride); + + void BindIndexBuffer( + D3D11Buffer* pBuffer, + UINT Offset, + DXGI_FORMAT Format); + + void BindXfbBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset); + + template + void BindConstantBuffer( + UINT Slot, + D3D11Buffer* pBuffer, + UINT Offset, + UINT Length); + + template + void BindConstantBufferRange( + UINT Slot, + UINT Offset, + UINT Length); + + template + void BindSampler( + UINT Slot, + D3D11SamplerState* pSampler); + + template + void BindShaderResource( + UINT Slot, + D3D11ShaderResourceView* pResource); + + template + void BindUnorderedAccessView( + UINT UavSlot, + D3D11UnorderedAccessView* pUav, + UINT CtrSlot, + UINT Counter); + void UpdateResource( ID3D11Resource* pDstResource, UINT DstSubresource,