Some more renaming and refactoring, extracted from a future PR

This commit is contained in:
Henrik Rydgård
2022-09-03 23:28:03 +02:00
parent 8e39018b95
commit 87b14fe1c2
9 changed files with 69 additions and 55 deletions
+4 -3
View File
@@ -1060,9 +1060,10 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
return false;
}
// TODO: This could support more ops using the shader blending mechanism.
LogicOpReplaceType replaceLogicOpType = (LogicOpReplaceType)id.Bits(FS_BIT_REPLACE_LOGIC_OP_TYPE, 2);
switch (replaceLogicOpType) {
// TODO: We could have a separate mechanism to support more ops using the shader blending mechanism,
// on hardware that can do proper bit math in fragment shaders.
SimulateLogicOpType simulateLogicOpType = (SimulateLogicOpType)id.Bits(FS_BIT_SIMULATE_LOGIC_OP_TYPE, 2);
switch (simulateLogicOpType) {
case LOGICOPTYPE_ONE:
WRITE(p, " %s.rgb = splat3(1.0);\n", compat.fragColor0);
break;
+34 -26
View File
@@ -489,27 +489,6 @@ ReplaceBlendType ReplaceBlendWithShader(GEBufferFormat bufferFormat) {
return REPLACE_BLEND_STANDARD;
}
LogicOpReplaceType ReplaceLogicOpType() {
if (!gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP) && gstate.isLogicOpEnabled()) {
switch (gstate.getLogicOp()) {
case GE_LOGIC_COPY_INVERTED:
case GE_LOGIC_AND_INVERTED:
case GE_LOGIC_OR_INVERTED:
case GE_LOGIC_NOR:
case GE_LOGIC_NAND:
case GE_LOGIC_EQUIV:
return LOGICOPTYPE_INVERT;
case GE_LOGIC_INVERTED:
return LOGICOPTYPE_ONE;
case GE_LOGIC_SET:
return LOGICOPTYPE_ONE;
default:
return LOGICOPTYPE_NORMAL;
}
}
return LOGICOPTYPE_NORMAL;
}
static const float DEPTH_SLICE_FACTOR_HIGH = 4.0f;
static const float DEPTH_SLICE_FACTOR_16BIT = 256.0f;
@@ -874,8 +853,10 @@ static inline bool blendColorSimilar(uint32_t a, uint32_t b, int margin = 25) {
return false;
}
// Try to simulate some common logic ops.
static void ApplyLogicOp(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq &blendEq) {
// Try to simulate some common logic ops by using blend, if needed.
// The shader might also need modification, the below function SimulateLogicOpShaderTypeIfNeeded
// takes care of that.
static void SimulateLogicOpIfNeeded(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq &blendEq) {
// Note: our shader solution applies logic ops BEFORE blending, not correctly after.
// This is however fine for the most common ones, like CLEAR/NOOP/SET, etc.
if (!gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) {
@@ -937,6 +918,28 @@ static void ApplyLogicOp(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq &
}
}
// Choose the shader part of the above logic op fallback simulation.
SimulateLogicOpType SimulateLogicOpShaderTypeIfNeeded() {
if (!gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP) && gstate.isLogicOpEnabled()) {
switch (gstate.getLogicOp()) {
case GE_LOGIC_COPY_INVERTED:
case GE_LOGIC_AND_INVERTED:
case GE_LOGIC_OR_INVERTED:
case GE_LOGIC_NOR:
case GE_LOGIC_NAND:
case GE_LOGIC_EQUIV:
return LOGICOPTYPE_INVERT;
case GE_LOGIC_INVERTED:
return LOGICOPTYPE_ONE;
case GE_LOGIC_SET:
return LOGICOPTYPE_ONE;
default:
return LOGICOPTYPE_NORMAL;
}
}
return LOGICOPTYPE_NORMAL;
}
void ApplyStencilReplaceAndLogicOpIgnoreBlend(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState) {
StencilValueType stencilType = STENCIL_VALUE_KEEP;
if (replaceAlphaWithStencil == REPLACE_ALPHA_YES) {
@@ -947,7 +950,7 @@ void ApplyStencilReplaceAndLogicOpIgnoreBlend(ReplaceAlphaType replaceAlphaWithS
BlendFactor srcBlend = BlendFactor::ONE;
BlendFactor dstBlend = BlendFactor::ZERO;
BlendEq blendEq = BlendEq::ADD;
ApplyLogicOp(srcBlend, dstBlend, blendEq);
SimulateLogicOpIfNeeded(srcBlend, dstBlend, blendEq);
// We're not blending, but we may still want to "blend" for stencil.
// This is only useful for INCR/DECR/INVERT. Others can write directly.
@@ -1245,8 +1248,8 @@ void ConvertBlendState(GenericBlendState &blendState, bool forceReplaceBlend) {
colorEq = eqLookupNoMinMax[blendFuncEq];
}
// Attempt to apply the logic op, if any.
ApplyLogicOp(glBlendFuncA, glBlendFuncB, colorEq);
// Attempt to apply simulated logic ops, if any and if needed.
SimulateLogicOpIfNeeded(glBlendFuncA, glBlendFuncB, colorEq);
// The stencil-to-alpha in fragment shader doesn't apply here (blending is enabled), and we shouldn't
// do any blending in the alpha channel as that doesn't seem to happen on PSP. So, we attempt to
@@ -1508,3 +1511,8 @@ void ConvertStencilFuncState(GenericStencilFuncState &state) {
break;
}
}
void ComputedPipelineState::Convert(bool shaderBitOpsSuppported) {
ConvertMaskState(maskState, shaderBitOpsSuppported);
ConvertBlendState(blendState, maskState.applyFramebufferRead);
}
+14 -2
View File
@@ -45,7 +45,7 @@ enum ReplaceBlendType {
REPLACE_BLEND_BLUE_TO_ALPHA,
};
enum LogicOpReplaceType {
enum SimulateLogicOpType {
LOGICOPTYPE_NORMAL,
LOGICOPTYPE_ONE,
LOGICOPTYPE_INVERT,
@@ -62,7 +62,8 @@ StencilValueType ReplaceAlphaWithStencilType();
ReplaceAlphaType ReplaceAlphaWithStencil(ReplaceBlendType replaceBlend);
ReplaceBlendType ReplaceBlendWithShader(GEBufferFormat bufferFormat);
LogicOpReplaceType ReplaceLogicOpType();
// This is for the fallback path if real logic ops are not available.
SimulateLogicOpType SimulateLogicOpShaderTypeIfNeeded();
// Common representation, should be able to set this directly with any modern API.
struct ViewportAndScissor {
@@ -186,7 +187,16 @@ void ApplyStencilReplaceAndLogicOpIgnoreBlend(ReplaceAlphaType replaceAlphaWithS
struct GenericMaskState {
bool applyFramebufferRead;
uint32_t uniformMask; // For each bit, opposite to the PSP.
// The hardware channel masks, 1 bit per color component. From bit 0, order is RGBA like in all APIs!
uint8_t channelMask;
void ConvertToShaderBlend() {
// If we have to do it in the shader, we simply pass through all channels but mask only in the shader instead.
// Some GPUs have minor penalties for masks that are not all-channels-on or all-channels-off.
channelMask = 0xF;
applyFramebufferRead = true;
}
};
void ConvertMaskState(GenericMaskState &maskState, bool shaderBitOpsSupported);
@@ -207,6 +217,8 @@ struct ComputedPipelineState {
GenericBlendState blendState;
GenericMaskState maskState;
// TODO: Add logic and possibly stencil here.
void Convert(bool shaderBitOpsSupported);
};
// See issue #15898
+4 -7
View File
@@ -267,16 +267,13 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip
ReplaceBlendType replaceBlend = pipelineState.blendState.replaceBlend;
ReplaceAlphaType stencilToAlpha = pipelineState.blendState.replaceAlphaWithStencil;
// For debugging, can probably delete soon.
// _assert_(colorWriteMask == IsColorWriteMaskComplex());
// _assert_(replaceBlend == ReplaceBlendWithShader(gstate_c.framebufFormat);
// _assert_(stencilToAlpha == ReplaceAlphaWithStencil(replaceBlend));
SimulateLogicOpType simulateLogicOpType = SimulateLogicOpShaderTypeIfNeeded();
// All texfuncs except replace are the same for RGB as for RGBA with full alpha.
// Note that checking this means that we must dirty the fragment shader ID whenever textureFullAlpha changes.
if (gstate_c.textureFullAlpha && gstate.getTextureFunction() != GE_TEXFUNC_REPLACE)
if (gstate_c.textureFullAlpha && gstate.getTextureFunction() != GE_TEXFUNC_REPLACE) {
doTextureAlpha = false;
}
if (gstate.isTextureMapEnabled()) {
id.SetBit(FS_BIT_DO_TEXTURE);
@@ -326,7 +323,7 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip
}
// 2 bits.
id.SetBits(FS_BIT_REPLACE_LOGIC_OP_TYPE, 2, ReplaceLogicOpType());
id.SetBits(FS_BIT_SIMULATE_LOGIC_OP_TYPE, 2, simulateLogicOpType);
// If replaceBlend == REPLACE_BLEND_STANDARD (or REPLACE_BLEND_NO) nothing is done, so we kill these bits.
if (replaceBlend == REPLACE_BLEND_BLUE_TO_ALPHA) {
+1 -1
View File
@@ -83,7 +83,7 @@ enum FShaderBit : uint8_t {
FS_BIT_COLOR_DOUBLE = 23,
FS_BIT_STENCIL_TO_ALPHA = 24, // 2 bits
FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE = 26, // 4 bits (ReplaceAlphaType)
FS_BIT_REPLACE_LOGIC_OP_TYPE = 30, // 2 bits
FS_BIT_SIMULATE_LOGIC_OP_TYPE = 30, // 2 bits
FS_BIT_REPLACE_BLEND = 32, // 3 bits (ReplaceBlendType)
FS_BIT_BLENDEQ = 35, // 3 bits
FS_BIT_BLENDFUNC_A = 38, // 4 bits
+1 -2
View File
@@ -147,10 +147,9 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
} else {
keys_.blend.value = 0;
pipelineState_.Convert(draw_->GetDeviceCaps().fragmentShaderInt32Supported);
GenericMaskState &maskState = pipelineState_.maskState;
GenericBlendState &blendState = pipelineState_.blendState;
ConvertMaskState(maskState, draw_->GetDeviceCaps().fragmentShaderInt32Supported);
ConvertBlendState(blendState, maskState.applyFramebufferRead);
if (blendState.applyFramebufferRead || maskState.applyFramebufferRead) {
bool fboTexNeedsBind = false;
+1 -2
View File
@@ -127,10 +127,9 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
}
dxstate.colorMask.set(mask);
} else {
pipelineState_.Convert(draw_->GetDeviceCaps().fragmentShaderInt32Supported);
GenericMaskState &maskState = pipelineState_.maskState;
GenericBlendState &blendState = pipelineState_.blendState;
ConvertMaskState(maskState, draw_->GetDeviceCaps().fragmentShaderInt32Supported);
ConvertBlendState(blendState, maskState.applyFramebufferRead);
if (blendState.applyFramebufferRead || maskState.applyFramebufferRead) {
bool fboTexNeedsBind = false;
+1 -2
View File
@@ -143,10 +143,9 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
bool alphaMask = gstate.isClearModeAlphaMask();
renderManager->SetNoBlendAndMask((colorMask ? 7 : 0) | (alphaMask ? 8 : 0));
} else {
pipelineState_.Convert(draw_->GetDeviceCaps().fragmentShaderInt32Supported);
GenericMaskState &maskState = pipelineState_.maskState;
GenericBlendState &blendState = pipelineState_.blendState;
ConvertMaskState(maskState, draw_->GetDeviceCaps().fragmentShaderInt32Supported);
ConvertBlendState(blendState, maskState.applyFramebufferRead);
if (blendState.applyFramebufferRead || maskState.applyFramebufferRead) {
bool fboTexNeedsBind = false;
+9 -10
View File
@@ -147,18 +147,9 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
bool alphaMask = gstate.isClearModeAlphaMask();
key.colorWriteMask = (colorMask ? (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT) : 0) | (alphaMask ? VK_COLOR_COMPONENT_A_BIT : 0);
} else {
if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP) && gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY) {
key.logicOpEnable = true;
key.logicOp = logicOps[gstate.getLogicOp()];
} else {
key.logicOpEnable = false;
key.logicOp = VK_LOGIC_OP_CLEAR;
}
pipelineState_.Convert(draw_->GetDeviceCaps().fragmentShaderInt32Supported);
GenericMaskState &maskState = pipelineState_.maskState;
GenericBlendState &blendState = pipelineState_.blendState;
ConvertMaskState(maskState, draw_->GetDeviceCaps().fragmentShaderInt32Supported);
ConvertBlendState(blendState, maskState.applyFramebufferRead);
if (blendState.applyFramebufferRead || maskState.applyFramebufferRead) {
ApplyFramebufferRead(&fboTexNeedsBind_);
@@ -218,6 +209,14 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
key.srcColor = VK_BLEND_FACTOR_ZERO;
key.destColor = VK_BLEND_FACTOR_ONE;
}
if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP) && gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY) {
key.logicOpEnable = true;
key.logicOp = logicOps[gstate.getLogicOp()];
} else {
key.logicOpEnable = false;
key.logicOp = VK_LOGIC_OP_CLEAR;
}
}
}