mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Some more renaming and refactoring, extracted from a future PR
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user