1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-04-01 09:25:24 +02:00

[dxvk,d3d9,d3d11] Refactor blend state object

This commit is contained in:
Philip Rebohle 2025-03-22 16:26:15 +01:00
parent 3c097046b2
commit a1106db71f
7 changed files with 133 additions and 95 deletions

View File

@ -12,7 +12,7 @@ namespace dxvk {
// blend modes for render target 1 to 7. In Vulkan, all // blend modes for render target 1 to 7. In Vulkan, all
// blend modes need to be identical in that case. // blend modes need to be identical in that case.
for (uint32_t i = 0; i < m_blendModes.size(); i++) { for (uint32_t i = 0; i < m_blendModes.size(); i++) {
m_blendModes.at(i) = DecodeBlendMode( m_blendModes[i] = DecodeBlendMode(
desc.IndependentBlendEnable desc.IndependentBlendEnable
? desc.RenderTarget[i] ? desc.RenderTarget[i]
: desc.RenderTarget[0]); : desc.RenderTarget[0]);
@ -89,16 +89,6 @@ namespace dxvk {
} }
void D3D11BlendState::BindToContext(
DxvkContext* ctx) const {
// We handled Independent Blend during object creation
// already, so if it is disabled, all elements in the
// blend mode array will be identical
for (uint32_t i = 0; i < m_blendModes.size(); i++)
ctx->setBlendMode(i, m_blendModes.at(i));
}
D3D11_BLEND_DESC1 D3D11BlendState::PromoteDesc(const D3D11_BLEND_DESC* pSrcDesc) { D3D11_BLEND_DESC1 D3D11BlendState::PromoteDesc(const D3D11_BLEND_DESC* pSrcDesc) {
D3D11_BLEND_DESC1 dstDesc; D3D11_BLEND_DESC1 dstDesc;
dstDesc.AlphaToCoverageEnable = pSrcDesc->AlphaToCoverageEnable; dstDesc.AlphaToCoverageEnable = pSrcDesc->AlphaToCoverageEnable;
@ -183,15 +173,15 @@ namespace dxvk {
DxvkBlendMode D3D11BlendState::DecodeBlendMode( DxvkBlendMode D3D11BlendState::DecodeBlendMode(
const D3D11_RENDER_TARGET_BLEND_DESC1& BlendDesc) { const D3D11_RENDER_TARGET_BLEND_DESC1& BlendDesc) {
DxvkBlendMode mode; DxvkBlendMode mode = { };
mode.enableBlending = BlendDesc.BlendEnable; mode.setBlendEnable(BlendDesc.BlendEnable);
mode.colorSrcFactor = DecodeBlendFactor(BlendDesc.SrcBlend, false); mode.setColorOp(DecodeBlendFactor(BlendDesc.SrcBlend, false),
mode.colorDstFactor = DecodeBlendFactor(BlendDesc.DestBlend, false); DecodeBlendFactor(BlendDesc.DestBlend, false),
mode.colorBlendOp = DecodeBlendOp(BlendDesc.BlendOp); DecodeBlendOp(BlendDesc.BlendOp));
mode.alphaSrcFactor = DecodeBlendFactor(BlendDesc.SrcBlendAlpha, true); mode.setAlphaOp(DecodeBlendFactor(BlendDesc.SrcBlendAlpha, true),
mode.alphaDstFactor = DecodeBlendFactor(BlendDesc.DestBlendAlpha, true); DecodeBlendFactor(BlendDesc.DestBlendAlpha, true),
mode.alphaBlendOp = DecodeBlendOp(BlendDesc.BlendOpAlpha); DecodeBlendOp(BlendDesc.BlendOpAlpha));
mode.writeMask = BlendDesc.RenderTargetWriteMask; mode.setWriteMask(BlendDesc.RenderTargetWriteMask);
return mode; return mode;
} }

View File

@ -42,9 +42,10 @@ namespace dxvk {
return m_loState; return m_loState;
} }
void BindToContext( std::array<DxvkBlendMode, 8> GetBlendState() const {
DxvkContext* ctx) const; return m_blendModes;
}
D3D10BlendState* GetD3D10Iface() { D3D10BlendState* GetD3D10Iface() {
return &m_d3d10; return &m_d3d10;
} }
@ -59,7 +60,7 @@ namespace dxvk {
D3D11_BLEND_DESC1 m_desc; D3D11_BLEND_DESC1 m_desc;
std::array<DxvkBlendMode, 8> m_blendModes; std::array<DxvkBlendMode, 8> m_blendModes = { };
DxvkMultisampleState m_msState = { }; DxvkMultisampleState m_msState = { };
DxvkLogicOpState m_loState = { }; DxvkLogicOpState m_loState = { };

View File

@ -3380,11 +3380,12 @@ namespace dxvk {
void D3D11CommonContext<ContextType>::ApplyBlendState() { void D3D11CommonContext<ContextType>::ApplyBlendState() {
if (m_state.om.cbState != nullptr) { if (m_state.om.cbState != nullptr) {
EmitCs([ EmitCs([
cBlendState = m_state.om.cbState, cBlendState = m_state.om.cbState->GetBlendState(),
cMsState = m_state.om.cbState->GetMsState(m_state.om.sampleMask), cMsState = m_state.om.cbState->GetMsState(m_state.om.sampleMask),
cLoState = m_state.om.cbState->GetLoState() cLoState = m_state.om.cbState->GetLoState()
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
cBlendState->BindToContext(ctx); for (uint32_t i = 0; i < cBlendState.size(); i++)
ctx->setBlendMode(i, cBlendState[i]);
ctx->setMultisampleState(cMsState); ctx->setMultisampleState(cMsState);
ctx->setLogicOpState(cLoState); ctx->setLogicOpState(cLoState);
@ -3393,8 +3394,7 @@ namespace dxvk {
EmitCs([ EmitCs([
cSampleMask = m_state.om.sampleMask cSampleMask = m_state.om.sampleMask
] (DxvkContext* ctx) { ] (DxvkContext* ctx) {
DxvkBlendMode cbState; DxvkBlendMode cbState = InitDefaultBlendState();
InitDefaultBlendState(&cbState);
for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
ctx->setBlendMode(i, cbState); ctx->setBlendMode(i, cbState);
@ -4740,15 +4740,14 @@ namespace dxvk {
DxvkRasterizerState rsState; DxvkRasterizerState rsState;
InitDefaultRasterizerState(&rsState); InitDefaultRasterizerState(&rsState);
DxvkBlendMode cbState;
InitDefaultBlendState(&cbState);
ctx->setInputAssemblyState(iaState); ctx->setInputAssemblyState(iaState);
ctx->setDepthStencilState(InitDefaultDepthStencilState()); ctx->setDepthStencilState(InitDefaultDepthStencilState());
ctx->setRasterizerState(rsState); ctx->setRasterizerState(rsState);
ctx->setLogicOpState(InitDefaultLogicOpState()); ctx->setLogicOpState(InitDefaultLogicOpState());
ctx->setMultisampleState(InitDefaultMultisampleState(D3D11_DEFAULT_SAMPLE_MASK)); ctx->setMultisampleState(InitDefaultMultisampleState(D3D11_DEFAULT_SAMPLE_MASK));
DxvkBlendMode cbState = InitDefaultBlendState();
for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
ctx->setBlendMode(i, cbState); ctx->setBlendMode(i, cbState);
@ -5840,17 +5839,14 @@ namespace dxvk {
template<typename ContextType> template<typename ContextType>
void D3D11CommonContext<ContextType>::InitDefaultBlendState( DxvkBlendMode D3D11CommonContext<ContextType>::InitDefaultBlendState() {
DxvkBlendMode* pCbState) { DxvkBlendMode cbState = { };
pCbState->enableBlending = VK_FALSE; cbState.setBlendEnable(false);
pCbState->colorSrcFactor = VK_BLEND_FACTOR_ONE; cbState.setColorOp(VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD);
pCbState->colorDstFactor = VK_BLEND_FACTOR_ZERO; cbState.setAlphaOp(VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD);
pCbState->colorBlendOp = VK_BLEND_OP_ADD; cbState.setWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
pCbState->alphaSrcFactor = VK_BLEND_FACTOR_ONE; | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
pCbState->alphaDstFactor = VK_BLEND_FACTOR_ZERO; return cbState;
pCbState->alphaBlendOp = VK_BLEND_OP_ADD;
pCbState->writeMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
} }
// Explicitly instantiate here // Explicitly instantiate here

View File

@ -1156,8 +1156,7 @@ namespace dxvk {
static DxvkLogicOpState InitDefaultLogicOpState(); static DxvkLogicOpState InitDefaultLogicOpState();
static void InitDefaultBlendState( static DxvkBlendMode InitDefaultBlendState();
DxvkBlendMode* pCbState);
template<bool AllowFlush = true, typename Cmd> template<bool AllowFlush = true, typename Cmd>
void EmitCs(Cmd&& command) { void EmitCs(Cmd&& command) {

View File

@ -6823,71 +6823,64 @@ namespace dxvk {
auto& state = m_state.renderStates; auto& state = m_state.renderStates;
bool separateAlpha = state[D3DRS_SEPARATEALPHABLENDENABLE]; DxvkBlendMode mode = { };
mode.setBlendEnable(state[D3DRS_ALPHABLENDENABLE]);
DxvkBlendMode mode; D3D9BlendState color = { };
mode.enableBlending = state[D3DRS_ALPHABLENDENABLE] != FALSE;
D3D9BlendState color, alpha;
color.Src = D3DBLEND(state[D3DRS_SRCBLEND]); color.Src = D3DBLEND(state[D3DRS_SRCBLEND]);
color.Dst = D3DBLEND(state[D3DRS_DESTBLEND]); color.Dst = D3DBLEND(state[D3DRS_DESTBLEND]);
color.Op = D3DBLENDOP(state[D3DRS_BLENDOP]); color.Op = D3DBLENDOP(state[D3DRS_BLENDOP]);
FixupBlendState(color); FixupBlendState(color);
if (separateAlpha) { D3D9BlendState alpha = color;
if (state[D3DRS_SEPARATEALPHABLENDENABLE]) {
alpha.Src = D3DBLEND(state[D3DRS_SRCBLENDALPHA]); alpha.Src = D3DBLEND(state[D3DRS_SRCBLENDALPHA]);
alpha.Dst = D3DBLEND(state[D3DRS_DESTBLENDALPHA]); alpha.Dst = D3DBLEND(state[D3DRS_DESTBLENDALPHA]);
alpha.Op = D3DBLENDOP(state[D3DRS_BLENDOPALPHA]); alpha.Op = D3DBLENDOP(state[D3DRS_BLENDOPALPHA]);
FixupBlendState(alpha); FixupBlendState(alpha);
} }
else
alpha = color;
mode.colorSrcFactor = DecodeBlendFactor(color.Src, false); mode.setColorOp(DecodeBlendFactor(color.Src, false),
mode.colorDstFactor = DecodeBlendFactor(color.Dst, false); DecodeBlendFactor(color.Dst, false),
mode.colorBlendOp = DecodeBlendOp (color.Op); DecodeBlendOp(color.Op));
mode.alphaSrcFactor = DecodeBlendFactor(alpha.Src, true); mode.setAlphaOp(DecodeBlendFactor(alpha.Src, true),
mode.alphaDstFactor = DecodeBlendFactor(alpha.Dst, true); DecodeBlendFactor(alpha.Dst, true),
mode.alphaBlendOp = DecodeBlendOp (alpha.Op); DecodeBlendOp(alpha.Op));
mode.writeMask = state[ColorWriteIndex(0)]; uint16_t writeMasks = 0;
std::array<VkColorComponentFlags, 3> extraWriteMasks; for (uint32_t i = 0; i < 4; i++)
for (uint32_t i = 0; i < 3; i++) writeMasks |= (state[ColorWriteIndex(i)] & 0xfu) << (4u * i);
extraWriteMasks[i] = state[ColorWriteIndex(i + 1)];
EmitCs([ EmitCs([
cMode = mode, cMode = mode,
cWriteMasks = extraWriteMasks, cWriteMasks = writeMasks,
cAlphaMasks = m_alphaSwizzleRTs cAlphaMasks = m_alphaSwizzleRTs
](DxvkContext* ctx) { ](DxvkContext* ctx) {
for (uint32_t i = 0; i < 4; i++) { for (uint32_t i = 0; i < 4; i++) {
DxvkBlendMode mode = cMode; DxvkBlendMode mode = cMode;
if (i != 0) mode.setWriteMask(cWriteMasks >> (4u * i));
mode.writeMask = cWriteMasks[i - 1];
// Adjust the blend factor based on the render target alpha swizzle bit mask. // Adjust the blend factor based on the render target alpha swizzle bit mask.
// Specific formats such as the XRGB ones require a ONE swizzle for alpha // Specific formats such as the XRGB ones require a ONE swizzle for alpha
// which cannot be directly applied with the image view of the attachment. // which cannot be directly applied with the image view of the attachment.
const bool alphaSwizzle = cAlphaMasks & (1 << i); if (cAlphaMasks & (1 << i)) {
auto NormalizeFactor = [] (VkBlendFactor Factor) {
auto NormalizeFactor = [alphaSwizzle](VkBlendFactor Factor) {
if (alphaSwizzle) {
if (Factor == VK_BLEND_FACTOR_DST_ALPHA) if (Factor == VK_BLEND_FACTOR_DST_ALPHA)
return VK_BLEND_FACTOR_ONE; return VK_BLEND_FACTOR_ONE;
else if (Factor == VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA) else if (Factor == VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA)
return VK_BLEND_FACTOR_ZERO; return VK_BLEND_FACTOR_ZERO;
} return Factor;
};
return Factor; mode.setColorOp(NormalizeFactor(mode.colorSrcFactor()),
}; NormalizeFactor(mode.colorDstFactor()), mode.colorBlendOp());
mode.setAlphaOp(NormalizeFactor(mode.alphaSrcFactor()),
mode.colorSrcFactor = NormalizeFactor(mode.colorSrcFactor); NormalizeFactor(mode.alphaDstFactor()), mode.alphaBlendOp());
mode.colorDstFactor = NormalizeFactor(mode.colorDstFactor); }
mode.alphaSrcFactor = NormalizeFactor(mode.alphaSrcFactor);
mode.alphaDstFactor = NormalizeFactor(mode.alphaDstFactor);
ctx->setBlendMode(i, mode); ctx->setBlendMode(i, mode);
} }

View File

@ -344,15 +344,74 @@ namespace dxvk {
* Stores the blend state for a single color attachment. * Stores the blend state for a single color attachment.
* Blend modes can be set separately for each attachment. * Blend modes can be set separately for each attachment.
*/ */
struct DxvkBlendMode { class DxvkBlendMode {
VkBool32 enableBlending;
VkBlendFactor colorSrcFactor; public:
VkBlendFactor colorDstFactor;
VkBlendOp colorBlendOp; bool blendEnable() const {
VkBlendFactor alphaSrcFactor; return m_enableBlending;
VkBlendFactor alphaDstFactor; }
VkBlendOp alphaBlendOp;
VkColorComponentFlags writeMask; VkBlendFactor colorSrcFactor() const {
return VkBlendFactor(m_colorSrcFactor);
}
VkBlendFactor colorDstFactor() const {
return VkBlendFactor(m_colorDstFactor);
}
VkBlendOp colorBlendOp() const {
return VkBlendOp(m_colorBlendOp);
}
VkBlendFactor alphaSrcFactor() const {
return VkBlendFactor(m_alphaSrcFactor);
}
VkBlendFactor alphaDstFactor() const {
return VkBlendFactor(m_alphaDstFactor);
}
VkBlendOp alphaBlendOp() const {
return VkBlendOp(m_alphaBlendOp);
}
VkColorComponentFlags writeMask() const {
return VkColorComponentFlags(m_writeMask);
}
void setBlendEnable(bool enable) {
m_enableBlending = enable;
}
void setColorOp(VkBlendFactor srcFactor, VkBlendFactor dstFactor, VkBlendOp op) {
m_colorSrcFactor = uint32_t(srcFactor);
m_colorDstFactor = uint32_t(dstFactor);
m_colorBlendOp = uint32_t(op);
}
void setAlphaOp(VkBlendFactor srcFactor, VkBlendFactor dstFactor, VkBlendOp op) {
m_alphaSrcFactor = uint32_t(srcFactor);
m_alphaDstFactor = uint32_t(dstFactor);
m_alphaBlendOp = uint32_t(op);
}
void setWriteMask(VkColorComponentFlags writeMask) {
m_writeMask = writeMask;
}
private:
uint32_t m_enableBlending : 1;
uint32_t m_colorSrcFactor : 5;
uint32_t m_colorDstFactor : 5;
uint32_t m_colorBlendOp : 3;
uint32_t m_alphaSrcFactor : 5;
uint32_t m_alphaDstFactor : 5;
uint32_t m_alphaBlendOp : 3;
uint32_t m_writeMask : 4;
uint32_t m_reserved : 1;
}; };

View File

@ -2824,15 +2824,15 @@ namespace dxvk {
uint32_t attachment, uint32_t attachment,
const DxvkBlendMode& blendMode) { const DxvkBlendMode& blendMode) {
m_state.gp.state.omBlend[attachment] = DxvkOmAttachmentBlend( m_state.gp.state.omBlend[attachment] = DxvkOmAttachmentBlend(
blendMode.enableBlending, blendMode.blendEnable(),
blendMode.colorSrcFactor, blendMode.colorSrcFactor(),
blendMode.colorDstFactor, blendMode.colorDstFactor(),
blendMode.colorBlendOp, blendMode.colorBlendOp(),
blendMode.alphaSrcFactor, blendMode.alphaSrcFactor(),
blendMode.alphaDstFactor, blendMode.alphaDstFactor(),
blendMode.alphaBlendOp, blendMode.alphaBlendOp(),
blendMode.writeMask); blendMode.writeMask());
m_flags.set(DxvkContextFlag::GpDirtyPipelineState); m_flags.set(DxvkContextFlag::GpDirtyPipelineState);
} }