diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index e822dbd6..855cacad 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -2320,8 +2320,9 @@ namespace dxvk { void DxvkContext::setLogicOpState(const DxvkLogicOpState& lo) { - m_state.gp.state.omEnableLogicOp = lo.enableLogicOp; - m_state.gp.state.omLogicOp = lo.logicOp; + m_state.gp.state.om = DxvkOmInfo( + lo.enableLogicOp, + lo.logicOp); m_flags.set(DxvkContextFlag::GpDirtyPipelineState); } @@ -2330,14 +2331,15 @@ namespace dxvk { void DxvkContext::setBlendMode( uint32_t attachment, const DxvkBlendMode& blendMode) { - m_state.gp.state.omBlendAttachments[attachment].blendEnable = blendMode.enableBlending; - m_state.gp.state.omBlendAttachments[attachment].srcColorBlendFactor = blendMode.colorSrcFactor; - m_state.gp.state.omBlendAttachments[attachment].dstColorBlendFactor = blendMode.colorDstFactor; - m_state.gp.state.omBlendAttachments[attachment].colorBlendOp = blendMode.colorBlendOp; - m_state.gp.state.omBlendAttachments[attachment].srcAlphaBlendFactor = blendMode.alphaSrcFactor; - m_state.gp.state.omBlendAttachments[attachment].dstAlphaBlendFactor = blendMode.alphaDstFactor; - m_state.gp.state.omBlendAttachments[attachment].alphaBlendOp = blendMode.alphaBlendOp; - m_state.gp.state.omBlendAttachments[attachment].colorWriteMask = blendMode.writeMask; + m_state.gp.state.omBlend[attachment] = DxvkOmAttachmentBlend( + blendMode.enableBlending, + blendMode.colorSrcFactor, + blendMode.colorDstFactor, + blendMode.colorBlendOp, + blendMode.alphaSrcFactor, + blendMode.alphaDstFactor, + blendMode.alphaBlendOp, + blendMode.writeMask); m_flags.set(DxvkContextFlag::GpDirtyPipelineState); } @@ -3984,9 +3986,11 @@ namespace dxvk { for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { Rc attachment = fb->getColorTarget(i).view; - m_state.gp.state.omComponentMapping[i] = attachment != nullptr + VkComponentMapping mapping = attachment != nullptr ? util::invertComponentMapping(attachment->info().swizzle) : VkComponentMapping(); + + m_state.gp.state.omSwizzle[i] = DxvkOmAttachmentSwizzle(mapping); } m_flags.set(DxvkContextFlag::GpDirtyPipelineState); diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 251e7195..dc51c926 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -7,7 +7,7 @@ #include "dxvk_state_cache.h" namespace dxvk { - + DxvkGraphicsPipeline::DxvkGraphicsPipeline( DxvkPipelineManager* pipeMgr, DxvkGraphicsPipelineShaders shaders) @@ -173,10 +173,10 @@ namespace dxvk { for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { if ((m_fsOut & (1 << i)) != 0) { uint32_t specId = uint32_t(DxvkSpecConstantId::ColorComponentMappings) + 4 * i; - specData.set(specId + 0, util::getComponentIndex(state.omComponentMapping[i].r, 0), 0u); - specData.set(specId + 1, util::getComponentIndex(state.omComponentMapping[i].g, 1), 1u); - specData.set(specId + 2, util::getComponentIndex(state.omComponentMapping[i].b, 2), 2u); - specData.set(specId + 3, util::getComponentIndex(state.omComponentMapping[i].a, 3), 3u); + specData.set(specId + 0, state.omSwizzle[i].rIndex(), 0u); + specData.set(specId + 1, state.omSwizzle[i].gIndex(), 1u); + specData.set(specId + 2, state.omSwizzle[i].bIndex(), 2u); + specData.set(specId + 3, state.omSwizzle[i].aIndex(), 3u); } } @@ -186,11 +186,11 @@ namespace dxvk { VkSpecializationInfo specInfo = specData.getSpecInfo(); DxvkShaderModuleCreateInfo moduleInfo; - moduleInfo.fsDualSrcBlend = state.omBlendAttachments[0].blendEnable && ( - util::isDualSourceBlendFactor(state.omBlendAttachments[0].srcColorBlendFactor) || - util::isDualSourceBlendFactor(state.omBlendAttachments[0].dstColorBlendFactor) || - util::isDualSourceBlendFactor(state.omBlendAttachments[0].srcAlphaBlendFactor) || - util::isDualSourceBlendFactor(state.omBlendAttachments[0].dstAlphaBlendFactor)); + moduleInfo.fsDualSrcBlend = state.omBlend[0].blendEnable() && ( + util::isDualSourceBlendFactor(state.omBlend[0].srcColorBlendFactor()) || + util::isDualSourceBlendFactor(state.omBlend[0].dstColorBlendFactor()) || + util::isDualSourceBlendFactor(state.omBlend[0].srcAlphaBlendFactor()) || + util::isDualSourceBlendFactor(state.omBlend[0].dstAlphaBlendFactor())); auto vsm = createShaderModule(m_shaders.vs, moduleInfo); auto gsm = createShaderModule(m_shaders.gs, moduleInfo); @@ -213,15 +213,11 @@ namespace dxvk { | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { - omBlendAttachments[i] = state.omBlendAttachments[i]; + omBlendAttachments[i] = state.omBlend[i].state(); - if (state.omBlendAttachments[i].colorWriteMask == fullMask) { - // Avoid unnecessary partial color write masks - omBlendAttachments[i].colorWriteMask = fullMask; - } else { + if (omBlendAttachments[i].colorWriteMask != fullMask) { omBlendAttachments[i].colorWriteMask = util::remapComponentMask( - state.omBlendAttachments[i].colorWriteMask, - state.omComponentMapping[i]); + state.omBlend[i].colorWriteMask(), state.omSwizzle[i].mapping()); } if ((m_fsOut & (1 << i)) == 0) @@ -372,8 +368,8 @@ namespace dxvk { cbInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; cbInfo.pNext = nullptr; cbInfo.flags = 0; - cbInfo.logicOpEnable = state.omEnableLogicOp; - cbInfo.logicOp = state.omLogicOp; + cbInfo.logicOpEnable = state.om.enableLogicOp(); + cbInfo.logicOp = state.om.logicOp(); cbInfo.attachmentCount = DxvkLimits::MaxNumRenderTargets; cbInfo.pAttachments = omBlendAttachments.data(); diff --git a/src/dxvk/dxvk_graphics_state.h b/src/dxvk/dxvk_graphics_state.h index d38b163b..1b8b080d 100644 --- a/src/dxvk/dxvk_graphics_state.h +++ b/src/dxvk/dxvk_graphics_state.h @@ -436,6 +436,179 @@ namespace dxvk { }; + /** + * \brief Packed output merger metadata + * + * Stores the logic op state in two bytes. + * Blend modes are stored separately. + */ + class DxvkOmInfo { + + public: + + DxvkOmInfo() = default; + + DxvkOmInfo( + VkBool32 enableLogicOp, + VkLogicOp logicOp) + : m_enableLogicOp (uint16_t(enableLogicOp)), + m_logicOp (uint16_t(logicOp)), + m_reserved (0) { } + + VkBool32 enableLogicOp() const { + return VkBool32(m_enableLogicOp); + } + + VkLogicOp logicOp() const { + return VkLogicOp(m_logicOp); + } + + private: + + uint16_t m_enableLogicOp : 1; + uint16_t m_logicOp : 4; + uint16_t m_reserved : 11; + + }; + + + /** + * \brief Packed attachment blend mode + * + * Stores blendig parameters for a single + * color attachment in four bytes. + */ + class DxvkOmAttachmentBlend { + + public: + + DxvkOmAttachmentBlend() = default; + + DxvkOmAttachmentBlend( + VkBool32 blendEnable, + VkBlendFactor srcColorBlendFactor, + VkBlendFactor dstColorBlendFactor, + VkBlendOp colorBlendOp, + VkBlendFactor srcAlphaBlendFactor, + VkBlendFactor dstAlphaBlendFactor, + VkBlendOp alphaBlendOp, + VkColorComponentFlags colorWriteMask) + : m_blendEnable (uint32_t(blendEnable)), + m_srcColorBlendFactor (uint32_t(srcColorBlendFactor)), + m_dstColorBlendFactor (uint32_t(dstColorBlendFactor)), + m_colorBlendOp (uint32_t(colorBlendOp)), + m_srcAlphaBlendFactor (uint32_t(srcAlphaBlendFactor)), + m_dstAlphaBlendFactor (uint32_t(dstAlphaBlendFactor)), + m_alphaBlendOp (uint32_t(alphaBlendOp)), + m_colorWriteMask (uint32_t(colorWriteMask)), + m_reserved (0) { } + + VkBool32 blendEnable() const { + return m_blendEnable; + } + + VkBlendFactor srcColorBlendFactor() const { + return VkBlendFactor(m_srcColorBlendFactor); + } + + VkBlendFactor dstColorBlendFactor() const { + return VkBlendFactor(m_dstColorBlendFactor); + } + + VkBlendOp colorBlendOp() const { + return VkBlendOp(m_colorBlendOp); + } + + VkBlendFactor srcAlphaBlendFactor() const { + return VkBlendFactor(m_srcAlphaBlendFactor); + } + + VkBlendFactor dstAlphaBlendFactor() const { + return VkBlendFactor(m_dstAlphaBlendFactor); + } + + VkBlendOp alphaBlendOp() const { + return VkBlendOp(m_alphaBlendOp); + } + + VkColorComponentFlags colorWriteMask() const { + return VkColorComponentFlags(m_colorWriteMask); + } + + VkPipelineColorBlendAttachmentState state() const { + VkPipelineColorBlendAttachmentState result; + result.blendEnable = VkBool32(m_blendEnable); + result.srcColorBlendFactor = VkBlendFactor(m_srcColorBlendFactor); + result.dstColorBlendFactor = VkBlendFactor(m_dstColorBlendFactor); + result.colorBlendOp = VkBlendOp(m_colorBlendOp); + result.srcAlphaBlendFactor = VkBlendFactor(m_srcAlphaBlendFactor); + result.dstAlphaBlendFactor = VkBlendFactor(m_dstAlphaBlendFactor); + result.alphaBlendOp = VkBlendOp(m_alphaBlendOp); + result.colorWriteMask = VkColorComponentFlags(m_colorWriteMask); + return result; + } + + private: + + uint32_t m_blendEnable : 1; + uint32_t m_srcColorBlendFactor : 5; + uint32_t m_dstColorBlendFactor : 5; + uint32_t m_colorBlendOp : 3; + uint32_t m_srcAlphaBlendFactor : 5; + uint32_t m_dstAlphaBlendFactor : 5; + uint32_t m_alphaBlendOp : 3; + uint32_t m_colorWriteMask : 4; + uint32_t m_reserved : 1; + + }; + + + /** + * \brief Packed attachment swizzle + * + * Stores the component mapping for one + * single color attachment in one byte. + */ + class DxvkOmAttachmentSwizzle { + + public: + + DxvkOmAttachmentSwizzle() = default; + + DxvkOmAttachmentSwizzle(VkComponentMapping mapping) + : m_r(util::getComponentIndex(mapping.r, 0)), + m_g(util::getComponentIndex(mapping.g, 1)), + m_b(util::getComponentIndex(mapping.b, 2)), + m_a(util::getComponentIndex(mapping.a, 3)) { } + + uint32_t rIndex() const { return m_r; } + uint32_t gIndex() const { return m_g; } + uint32_t bIndex() const { return m_b; } + uint32_t aIndex() const { return m_a; } + + VkComponentMapping mapping() const { + VkComponentMapping result; + result.r = decodeSwizzle(m_r); + result.g = decodeSwizzle(m_g); + result.b = decodeSwizzle(m_b); + result.a = decodeSwizzle(m_a); + return result; + } + + private: + + uint8_t m_r : 2; + uint8_t m_g : 2; + uint8_t m_b : 2; + uint8_t m_a : 2; + + static VkComponentSwizzle decodeSwizzle(uint8_t swizzle) { + return VkComponentSwizzle(uint32_t(swizzle) + uint32_t(VK_COMPONENT_SWIZZLE_R)); + } + + }; + + /** * \brief Packed graphics pipeline state * @@ -481,11 +654,11 @@ namespace dxvk { bool result = false; for (uint32_t i = 0; i < MaxNumRenderTargets && !result; i++) { - result |= omBlendAttachments[i].blendEnable - && (util::isBlendConstantBlendFactor(omBlendAttachments[i].srcColorBlendFactor) - || util::isBlendConstantBlendFactor(omBlendAttachments[i].dstColorBlendFactor) - || util::isBlendConstantBlendFactor(omBlendAttachments[i].srcAlphaBlendFactor) - || util::isBlendConstantBlendFactor(omBlendAttachments[i].dstAlphaBlendFactor)); + result |= omBlend[i].blendEnable() + && (util::isBlendConstantBlendFactor(omBlend[i].srcColorBlendFactor()) + || util::isBlendConstantBlendFactor(omBlend[i].dstColorBlendFactor()) + || util::isBlendConstantBlendFactor(omBlend[i].srcAlphaBlendFactor()) + || util::isBlendConstantBlendFactor(omBlend[i].dstAlphaBlendFactor())); } return result; @@ -497,16 +670,14 @@ namespace dxvk { DxvkRsInfo rs; DxvkMsInfo ms; DxvkDsInfo ds; + DxvkOmInfo om; - VkBool32 omEnableLogicOp; - VkLogicOp omLogicOp; - VkPipelineColorBlendAttachmentState omBlendAttachments[MaxNumRenderTargets]; - VkComponentMapping omComponentMapping[MaxNumRenderTargets]; - uint32_t scSpecConstants[MaxNumSpecConstants]; DxvkDsStencilOp dsFront; DxvkDsStencilOp dsBack; + DxvkOmAttachmentSwizzle omSwizzle [DxvkLimits::MaxNumRenderTargets]; + DxvkOmAttachmentBlend omBlend [DxvkLimits::MaxNumRenderTargets]; DxvkIlAttribute ilAttributes [DxvkLimits::MaxNumVertexAttributes]; DxvkIlBinding ilBindings [DxvkLimits::MaxNumVertexBindings]; };