diff --git a/src/d3d11/d3d11_blend.cpp b/src/d3d11/d3d11_blend.cpp index a7d6dd650..f866bc101 100644 --- a/src/d3d11/d3d11_blend.cpp +++ b/src/d3d11/d3d11_blend.cpp @@ -23,6 +23,11 @@ namespace dxvk { m_msState.enableAlphaToOne = VK_FALSE; m_msState.enableSampleShading = VK_FALSE; m_msState.minSampleShading = 0.0f; + + // In 11_0, there is no logic op state. Later versions + // of D3D11 however put it into the blend state object. + m_loState.enableLogicOp = VK_FALSE; + m_loState.logicOp = VK_LOGIC_OP_NO_OP; } @@ -64,6 +69,11 @@ namespace dxvk { DxvkMultisampleState msState = m_msState; msState.sampleMask = sampleMask; ctx->setMultisampleState(msState); + + // Set up logic op state as well + ctx->setLogicOpState(m_loState); + + // TODO set blend factor } diff --git a/src/d3d11/d3d11_blend.h b/src/d3d11/d3d11_blend.h index b8f418c16..d476001a5 100644 --- a/src/d3d11/d3d11_blend.h +++ b/src/d3d11/d3d11_blend.h @@ -32,7 +32,7 @@ namespace dxvk { void BindToContext( const Rc& ctx, - uint32_t sampleMask) const; + UINT sampleMask) const; private: @@ -41,6 +41,7 @@ namespace dxvk { std::array m_blendModes; DxvkMultisampleState m_msState; + DxvkLogicOpState m_loState; static DxvkBlendMode DecodeBlendMode( const D3D11_RENDER_TARGET_BLEND_DESC& blendDesc); diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 09aa5b1f8..415edef42 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -15,9 +15,30 @@ namespace dxvk { m_context = m_device->createContext(); m_context->beginRecording( m_device->createCommandList()); - this->SetDefaultBlendState(); - this->SetDefaultDepthStencilState(); - this->SetDefaultRasterizerState(); + // Create default state objects. We won't ever return them + // to the application, but we'll use them to apply state. + Com defaultBlendState; + Com defaultDepthStencilState; + Com defaultRasterizerState; + + if (FAILED(m_parent->CreateBlendState (nullptr, &defaultBlendState)) + || FAILED(m_parent->CreateDepthStencilState(nullptr, &defaultDepthStencilState)) + || FAILED(m_parent->CreateRasterizerState (nullptr, &defaultRasterizerState))) + throw DxvkError("D3D11DeviceContext: Failed to create default state objects"); + + // Apply default state to the context. This is required + // in order to initialize the DXVK contex properly. + m_defaultBlendState = static_cast(defaultBlendState.ptr()); + m_defaultBlendState->BindToContext(m_context, 0xFFFFFFFF); + + m_defaultDepthStencilState = static_cast(defaultDepthStencilState.ptr()); + m_defaultDepthStencilState->BindToContext(m_context); + + m_defaultRasterizerState = static_cast(defaultRasterizerState.ptr()); + m_defaultRasterizerState->BindToContext(m_context); + + m_context->setBlendConstants(m_state.om.blendFactor); + m_context->setStencilReference(m_state.om.stencilRef); } @@ -1201,14 +1222,44 @@ namespace dxvk { ID3D11BlendState* pBlendState, const FLOAT BlendFactor[4], UINT SampleMask) { - Logger::err("D3D11DeviceContext::OMSetBlendState: Not implemented"); + auto blendState = static_cast(pBlendState); + + if (m_state.om.cbState != blendState + || m_state.om.sampleMask != SampleMask) { + m_state.om.cbState = blendState; + m_state.om.sampleMask = SampleMask; + + if (blendState == nullptr) + blendState = m_defaultBlendState.ptr(); + + blendState->BindToContext(m_context, SampleMask); + } + + if ((BlendFactor != nullptr) && (!std::memcmp(m_state.om.blendFactor, BlendFactor, 4 * sizeof(FLOAT)))) { + std::memcpy(m_state.om.blendFactor, BlendFactor, 4 * sizeof(FLOAT)); + m_context->setBlendConstants(BlendFactor); + } } void D3D11DeviceContext::OMSetDepthStencilState( ID3D11DepthStencilState* pDepthStencilState, UINT StencilRef) { - Logger::err("D3D11DeviceContext::OMSetDepthStencilState: Not implemented"); + auto depthStencilState = static_cast(pDepthStencilState); + + if (m_state.om.dsState != depthStencilState) { + m_state.om.dsState = depthStencilState; + + if (depthStencilState == nullptr) + depthStencilState = m_defaultDepthStencilState.ptr(); + + depthStencilState->BindToContext(m_context); + } + + if (m_state.om.stencilRef != StencilRef) { + m_state.om.stencilRef = StencilRef; + m_context->setStencilReference(StencilRef); + } } @@ -1262,10 +1313,10 @@ namespace dxvk { if (m_state.rs.state != rasterizerState) { m_state.rs.state = rasterizerState; - if (rasterizerState != nullptr) - rasterizerState->BindToContext(m_context); - else - this->SetDefaultRasterizerState(); + if (rasterizerState == nullptr) + rasterizerState = m_defaultRasterizerState.ptr(); + + rasterizerState->BindToContext(m_context); // In D3D11, the rasterizer state defines // whether the scissor test is enabled, so @@ -1553,75 +1604,4 @@ namespace dxvk { scissors.data()); } - - void D3D11DeviceContext::SetDefaultBlendState() { - DxvkMultisampleState msState; - msState.sampleMask = 0xffffffff; - msState.enableAlphaToCoverage = VK_FALSE; - msState.enableAlphaToOne = VK_FALSE; - msState.enableSampleShading = VK_FALSE; - msState.minSampleShading = 0.0f; - m_context->setMultisampleState(msState); - - DxvkLogicOpState loState; - loState.enableLogicOp = VK_FALSE; - loState.logicOp = VK_LOGIC_OP_CLEAR; - m_context->setLogicOpState(loState); - - DxvkBlendMode blendMode; - blendMode.enableBlending = VK_FALSE; - blendMode.colorSrcFactor = VK_BLEND_FACTOR_ONE; - blendMode.colorDstFactor = VK_BLEND_FACTOR_ZERO; - blendMode.colorBlendOp = VK_BLEND_OP_ADD; - blendMode.alphaSrcFactor = VK_BLEND_FACTOR_ONE; - blendMode.alphaDstFactor = VK_BLEND_FACTOR_ZERO; - blendMode.alphaBlendOp = VK_BLEND_OP_ADD; - blendMode.writeMask = VK_COLOR_COMPONENT_R_BIT - | VK_COLOR_COMPONENT_G_BIT - | VK_COLOR_COMPONENT_B_BIT - | VK_COLOR_COMPONENT_A_BIT; - - for (uint32_t i = 0; i < DxvkLimits::MaxNumRenderTargets; i++) - m_context->setBlendMode(i, blendMode); - } - - - void D3D11DeviceContext::SetDefaultDepthStencilState() { - VkStencilOpState stencilOp; - stencilOp.failOp = VK_STENCIL_OP_KEEP; - stencilOp.passOp = VK_STENCIL_OP_KEEP; - stencilOp.depthFailOp = VK_STENCIL_OP_KEEP; - stencilOp.compareOp = VK_COMPARE_OP_ALWAYS; - stencilOp.compareMask = D3D11_DEFAULT_STENCIL_READ_MASK; - stencilOp.writeMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; - stencilOp.reference = 0; - - DxvkDepthStencilState dsState; - dsState.enableDepthTest = VK_TRUE; - dsState.enableDepthWrite = VK_TRUE; - dsState.enableDepthBounds = VK_FALSE; - dsState.enableStencilTest = VK_FALSE; - dsState.depthCompareOp = VK_COMPARE_OP_LESS; - dsState.stencilOpFront = stencilOp; - dsState.stencilOpBack = stencilOp; - dsState.depthBoundsMin = 0.0f; - dsState.depthBoundsMax = 1.0f; - m_context->setDepthStencilState(dsState); - } - - - void D3D11DeviceContext::SetDefaultRasterizerState() { - DxvkRasterizerState rsState; - rsState.enableDepthClamp = VK_FALSE; - rsState.enableDiscard = VK_FALSE; - rsState.polygonMode = VK_POLYGON_MODE_FILL; - rsState.cullMode = VK_CULL_MODE_BACK_BIT; - rsState.frontFace = VK_FRONT_FACE_CLOCKWISE; - rsState.depthBiasEnable = VK_FALSE; - rsState.depthBiasConstant = 0.0f; - rsState.depthBiasClamp = 0.0f; - rsState.depthBiasSlope = 0.0f; - m_context->setRasterizerState(rsState); - } - } diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index add5a5ad8..192cb4977 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -547,6 +547,10 @@ namespace dxvk { Rc m_device; Rc m_context; + Com m_defaultBlendState; + Com m_defaultDepthStencilState; + Com m_defaultRasterizerState; + D3D11ContextState m_state; void BindConstantBuffers( @@ -572,14 +576,6 @@ namespace dxvk { void ApplyViewportState(); - void SetupIAStateObjects(); - - void SetDefaultBlendState(); - - void SetDefaultDepthStencilState(); - - void SetDefaultRasterizerState(); - }; } diff --git a/src/d3d11/d3d11_context_state.h b/src/d3d11/d3d11_context_state.h index 226f8341d..520c008f2 100644 --- a/src/d3d11/d3d11_context_state.h +++ b/src/d3d11/d3d11_context_state.h @@ -97,6 +97,13 @@ namespace dxvk { struct D3D11ContextStateOM { std::array, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> renderTargetViews; Com depthStencilView; + + Com cbState = nullptr; + Com dsState = nullptr; + + FLOAT blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + UINT sampleMask = 0xFFFFFFFFu; + UINT stencilRef = 0u; }; diff --git a/src/d3d11/d3d11_depth_stencil.cpp b/src/d3d11/d3d11_depth_stencil.cpp index 6be5def8a..829aae3b0 100644 --- a/src/d3d11/d3d11_depth_stencil.cpp +++ b/src/d3d11/d3d11_depth_stencil.cpp @@ -48,7 +48,7 @@ namespace dxvk { void D3D11DepthStencilState::BindToContext( - const Rc& ctx) { + const Rc& ctx) { ctx->setDepthStencilState(m_state); } diff --git a/src/dxvk/dxvk_cmdlist.cpp b/src/dxvk/dxvk_cmdlist.cpp index 956d8d53c..057fdf2d0 100644 --- a/src/dxvk/dxvk_cmdlist.cpp +++ b/src/dxvk/dxvk_cmdlist.cpp @@ -284,6 +284,12 @@ namespace dxvk { } + void DxvkCommandList::cmdSetBlendConstants( + float blendConstants[4]) { + m_vkd->vkCmdSetBlendConstants(m_buffer, blendConstants); + } + + void DxvkCommandList::cmdSetScissor( uint32_t firstScissor, uint32_t scissorCount, @@ -293,6 +299,14 @@ namespace dxvk { } + void DxvkCommandList::cmdSetStencilReference( + VkStencilFaceFlags faceMask, + uint32_t reference) { + m_vkd->vkCmdSetStencilReference(m_buffer, + faceMask, reference); + } + + void DxvkCommandList::cmdSetViewport( uint32_t firstViewport, uint32_t viewportCount, diff --git a/src/dxvk/dxvk_cmdlist.h b/src/dxvk/dxvk_cmdlist.h index c451d0f65..1a07af80b 100644 --- a/src/dxvk/dxvk_cmdlist.h +++ b/src/dxvk/dxvk_cmdlist.h @@ -169,11 +169,18 @@ namespace dxvk { VkDeviceSize dataSize, const void* pData); + void cmdSetBlendConstants( + float blendConstants[4]); + void cmdSetScissor( uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* scissors); + void cmdSetStencilReference( + VkStencilFaceFlags faceMask, + uint32_t reference); + void cmdSetViewport( uint32_t firstViewport, uint32_t viewportCount, diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 915baf04e..da00f94f3 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -538,6 +538,23 @@ namespace dxvk { } + void DxvkContext::setBlendConstants( + const float blendConstants[4]) { + for (uint32_t i = 0; i < 4; i++) + m_state.om.blendConstants[i] = blendConstants[i]; + + this->updateBlendConstants(); + } + + + void DxvkContext::setStencilReference( + const uint32_t reference) { + m_state.om.stencilReference = reference; + + this->updateStencilReference(); + } + + void DxvkContext::setInputAssemblyState( const DxvkInputAssemblyState& state) { m_state.ia = state; @@ -785,6 +802,8 @@ namespace dxvk { m_flags.clr(DxvkContextFlag::GpDirtyDynamicState); this->updateViewports(); + this->updateBlendConstants(); + this->updateStencilReference(); } } @@ -795,6 +814,18 @@ namespace dxvk { } + void DxvkContext::updateBlendConstants() { + m_cmd->cmdSetBlendConstants(m_state.om.blendConstants); + } + + + void DxvkContext::updateStencilReference() { + m_cmd->cmdSetStencilReference( + VK_STENCIL_FRONT_AND_BACK, + m_state.om.stencilReference); + } + + void DxvkContext::updateIndexBufferBinding() { if (m_flags.test(DxvkContextFlag::GpDirtyIndexBuffer)) { m_flags.clr(DxvkContextFlag::GpDirtyIndexBuffer); diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 68e4678d2..9211b47a8 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -295,6 +295,26 @@ namespace dxvk { const VkViewport* viewports, const VkRect2D* scissorRects); + /** + * \brief Sets blend constants + * + * Blend constants are a set of four floating + * point numbers that may be used as an input + * for blending operations. + * \param [in] blendConstants Blend constants + */ + void setBlendConstants( + const float blendConstants[4]); + + /** + * \brief Sets stencil reference + * + * Sets the reference value for stencil compare operations. + * \param [in] reference Reference value + */ + void setStencilReference( + const uint32_t reference); + /** * \brief Sets input assembly state * \param [in] state New state object @@ -377,6 +397,8 @@ namespace dxvk { void updateDynamicState(); void updateViewports(); + void updateBlendConstants(); + void updateStencilReference(); void updateIndexBufferBinding(); void updateVertexBufferBindings(); diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index 5dc9d48d4..2e1cfc716 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -57,7 +57,10 @@ namespace dxvk { struct DxvkOutputMergerState { Rc framebuffer; - std::array blendModes; + std::array blendModes; + float blendConstants[4]; + uint32_t stencilReference; };