1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-28 02:19:26 +01:00

[dxvk,d3d9,d3d11] Refactor blend state object

This commit is contained in:
Philip Rebohle 2025-03-22 16:26:15 +01:00
parent 4a5c50b2de
commit e25f9db61b
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 need to be identical in that case.
for (uint32_t i = 0; i < m_blendModes.size(); i++) {
m_blendModes.at(i) = DecodeBlendMode(
m_blendModes[i] = DecodeBlendMode(
desc.IndependentBlendEnable
? desc.RenderTarget[i]
: 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 dstDesc;
dstDesc.AlphaToCoverageEnable = pSrcDesc->AlphaToCoverageEnable;
@ -183,15 +173,15 @@ namespace dxvk {
DxvkBlendMode D3D11BlendState::DecodeBlendMode(
const D3D11_RENDER_TARGET_BLEND_DESC1& BlendDesc) {
DxvkBlendMode mode;
mode.enableBlending = BlendDesc.BlendEnable;
mode.colorSrcFactor = DecodeBlendFactor(BlendDesc.SrcBlend, false);
mode.colorDstFactor = DecodeBlendFactor(BlendDesc.DestBlend, false);
mode.colorBlendOp = DecodeBlendOp(BlendDesc.BlendOp);
mode.alphaSrcFactor = DecodeBlendFactor(BlendDesc.SrcBlendAlpha, true);
mode.alphaDstFactor = DecodeBlendFactor(BlendDesc.DestBlendAlpha, true);
mode.alphaBlendOp = DecodeBlendOp(BlendDesc.BlendOpAlpha);
mode.writeMask = BlendDesc.RenderTargetWriteMask;
DxvkBlendMode mode = { };
mode.setBlendEnable(BlendDesc.BlendEnable);
mode.setColorOp(DecodeBlendFactor(BlendDesc.SrcBlend, false),
DecodeBlendFactor(BlendDesc.DestBlend, false),
DecodeBlendOp(BlendDesc.BlendOp));
mode.setAlphaOp(DecodeBlendFactor(BlendDesc.SrcBlendAlpha, true),
DecodeBlendFactor(BlendDesc.DestBlendAlpha, true),
DecodeBlendOp(BlendDesc.BlendOpAlpha));
mode.setWriteMask(BlendDesc.RenderTargetWriteMask);
return mode;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -344,15 +344,74 @@ namespace dxvk {
* Stores the blend state for a single color attachment.
* Blend modes can be set separately for each attachment.
*/
struct DxvkBlendMode {
VkBool32 enableBlending;
VkBlendFactor colorSrcFactor;
VkBlendFactor colorDstFactor;
VkBlendOp colorBlendOp;
VkBlendFactor alphaSrcFactor;
VkBlendFactor alphaDstFactor;
VkBlendOp alphaBlendOp;
VkColorComponentFlags writeMask;
class DxvkBlendMode {
public:
bool blendEnable() const {
return m_enableBlending;
}
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

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