Merge pull request #13637 from hrydgard/shaderblend-cleanup

Shaderblend code cleanup
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2020-11-08 18:50:22 +01:00
commit 7632c12189
17 files changed
+139 -172

No files matched your search

+3 -2
View File
@@ -480,8 +480,9 @@ u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr,
return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & (GE_VTYPE_IDX_MASK | GE_VTYPE_THROUGH));
}
bool DrawEngineCommon::ApplyShaderBlending() {
bool DrawEngineCommon::ApplyFramebufferRead(bool *fboTexNeedsBind) {
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) {
*fboTexNeedsBind = false;
return true;
}
@@ -502,7 +503,7 @@ bool DrawEngineCommon::ApplyShaderBlending() {
return false;
}
fboTexNeedBind_ = true;
*fboTexNeedsBind = true;
gstate_c.Dirty(DIRTY_SHADERBLEND);
return true;
+2 -2
View File
@@ -112,7 +112,7 @@ protected:
// Vertex decoding
void DecodeVertsStep(u8 *dest, int &i, int &decodedVerts);
bool ApplyShaderBlending();
bool ApplyFramebufferRead(bool *fboTexNeedsBind);
inline int IndexSize(u32 vtype) const {
const u32 indexType = (vtype & GE_VTYPE_IDX_MASK);
@@ -169,7 +169,7 @@ protected:
GEPrimitiveType prevPrim_ = GE_PRIM_INVALID;
// Shader blending state
bool fboTexNeedBind_ = false;
bool fboTexNeedsBind_ = false;
bool fboTexBound_ = false;
// Hardware tessellation
+18 -17
View File
@@ -104,6 +104,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
bool earlyFragmentTests = ((!enableAlphaTest && !enableColorTest) || testForceToZero) && !gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT);
bool useAdrenoBugWorkaround = id.Bit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL);
bool readFramebufferTex = replaceBlend == REPLACE_BLEND_COPY_FBO && !gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH);
if (compat.shaderLanguage == ShaderLanguage::GLSL_VULKAN) {
if (earlyFragmentTests) {
WRITE(p, "layout (early_fragment_tests) in;\n");
@@ -116,10 +118,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
WRITE(p, "layout (binding = 0) uniform sampler2D tex;\n");
}
if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
if (replaceBlend == REPLACE_BLEND_COPY_FBO) {
WRITE(p, "layout (binding = 1) uniform sampler2D fbotex;\n");
}
if (readFramebufferTex) {
WRITE(p, "layout (binding = 1) uniform sampler2D fbotex;\n");
}
if (shaderDepal) {
@@ -151,11 +151,13 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
if (compat.shaderLanguage == HLSL_D3D9) {
if (doTexture)
WRITE(p, "sampler tex : register(s0);\n");
if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
if (replaceBlend == REPLACE_BLEND_COPY_FBO) {
WRITE(p, "vec2 u_fbotexSize : register(c%i);\n", CONST_PS_FBOTEXSIZE);
WRITE(p, "sampler fbotex : register(s1);\n");
}
if (readFramebufferTex) {
WRITE(p, "vec2 u_fbotexSize : register(c%i);\n", CONST_PS_FBOTEXSIZE);
WRITE(p, "sampler fbotex : register(s1);\n");
}
if (replaceBlend > REPLACE_BLEND_STANDARD) {
if (replaceBlendFuncA >= GE_SRCBLEND_FIXA) {
WRITE(p, "float3 u_blendFixA : register(c%i);\n", CONST_PS_BLENDFIXA);
}
@@ -244,11 +246,11 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
} else if (compat.shaderLanguage == HLSL_D3D9) {
if (doTexture)
WRITE(p, "sampler tex : register(s0);\n");
if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
if (replaceBlend == REPLACE_BLEND_COPY_FBO) {
WRITE(p, "vec2 u_fbotexSize : register(c%i);\n", CONST_PS_FBOTEXSIZE);
WRITE(p, "sampler fbotex : register(s1);\n");
}
if (readFramebufferTex) {
WRITE(p, "vec2 u_fbotexSize : register(c%i);\n", CONST_PS_FBOTEXSIZE);
WRITE(p, "sampler fbotex : register(s1);\n");
}
if (replaceBlend > REPLACE_BLEND_STANDARD) {
if (replaceBlendFuncA >= GE_SRCBLEND_FIXA) {
WRITE(p, "float3 u_blendFixA : register(c%i);\n", CONST_PS_BLENDFIXA);
}
@@ -276,7 +278,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
if (enableFog) {
WRITE(p, "float3 u_fogcolor : register(c%i);\n", CONST_PS_FOGCOLOR);
}
} else if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) {
if (shaderDepal && gl_extensions.IsGLES) {
WRITE(p, "precision highp int;\n");
@@ -287,7 +288,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
*uniformMask |= DIRTY_SHADERBLEND;
if (!gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH) && replaceBlend == REPLACE_BLEND_COPY_FBO) {
if (readFramebufferTex) {
if (!compat.texelFetch) {
WRITE(p, "uniform vec2 u_fbotexSize;\n");
}
@@ -869,7 +870,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
}
if (replaceBlend == REPLACE_BLEND_2X_ALPHA || replaceBlend == REPLACE_BLEND_PRE_SRC_2X_ALPHA) {
WRITE(p, " v.a = v.a * 2.0;\n");
WRITE(p, " v.a *= 2.0;\n");
}
}
+29 -29
View File
@@ -253,7 +253,7 @@ StencilValueType ReplaceAlphaWithStencilType() {
return STENCIL_VALUE_KEEP;
}
ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bufferFormat) {
ReplaceBlendType ReplaceBlendWithShader(bool allowFramebufferRead, GEBufferFormat bufferFormat) {
if (!gstate.isAlphaBlendEnabled() || gstate.isModeClear()) {
return REPLACE_BLEND_NO;
}
@@ -262,14 +262,14 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
// Let's get the non-factor modes out of the way first.
switch (eq) {
case GE_BLENDMODE_ABSDIFF:
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
case GE_BLENDMODE_MIN:
case GE_BLENDMODE_MAX:
if (gstate_c.Supports(GPU_SUPPORTS_BLEND_MINMAX)) {
return REPLACE_BLEND_STANDARD;
} else {
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
}
default:
@@ -292,19 +292,19 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
return REPLACE_BLEND_2X_ALPHA;
// Can't double, we need the source color to be correct.
// Doubling only alpha would clamp the src alpha incorrectly.
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
case GE_DSTBLEND_DOUBLEDSTALPHA:
case GE_DSTBLEND_DOUBLEINVDSTALPHA:
if (bufferFormat == GE_FORMAT_565)
return REPLACE_BLEND_2X_ALPHA;
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
case GE_DSTBLEND_DOUBLESRCALPHA:
// We can't technically do this correctly (due to clamping) without reading the dst color.
// Using a copy isn't accurate either, though, when there's overlap.
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH))
return !allowShaderBlend ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return REPLACE_BLEND_PRE_SRC_2X_ALPHA;
case GE_DSTBLEND_DOUBLEINVSRCALPHA:
@@ -331,7 +331,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
return REPLACE_BLEND_STANDARD;
}
// Can't double, we need the source color to be correct.
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
case GE_DSTBLEND_DOUBLEDSTALPHA:
case GE_DSTBLEND_DOUBLEINVDSTALPHA:
@@ -340,7 +340,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
// Doubling will have no effect here.
return REPLACE_BLEND_STANDARD;
}
return !allowShaderBlend ? REPLACE_BLEND_2X_SRC : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_SRC : REPLACE_BLEND_COPY_FBO;
case GE_DSTBLEND_DOUBLESRCALPHA:
case GE_DSTBLEND_DOUBLEINVSRCALPHA:
@@ -349,7 +349,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
}
// Double both src (for dst alpha) and alpha (for dst factor.)
// But to be accurate (clamping), we need to read the dst color.
return !allowShaderBlend ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
case GE_DSTBLEND_SRCALPHA:
case GE_DSTBLEND_INVSRCALPHA:
@@ -361,7 +361,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
return REPLACE_BLEND_STANDARD;
}
// We can't technically do this correctly (due to clamping) without reading the dst alpha.
return !allowShaderBlend ? REPLACE_BLEND_2X_SRC : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_SRC : REPLACE_BLEND_COPY_FBO;
}
case GE_SRCBLEND_DOUBLEINVDSTALPHA:
@@ -375,14 +375,14 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
if (bufferFormat == GE_FORMAT_565) {
return REPLACE_BLEND_STANDARD;
}
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
case GE_DSTBLEND_DOUBLESRCALPHA:
case GE_DSTBLEND_DOUBLEINVSRCALPHA:
if (bufferFormat == GE_FORMAT_565) {
return REPLACE_BLEND_2X_ALPHA;
}
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
case GE_DSTBLEND_SRCALPHA:
case GE_DSTBLEND_INVSRCALPHA:
@@ -393,7 +393,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
if (bufferFormat == GE_FORMAT_565) {
return REPLACE_BLEND_STANDARD;
}
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
}
case GE_SRCBLEND_FIXA:
@@ -401,7 +401,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
switch (funcB) {
case GE_DSTBLEND_DOUBLESRCALPHA:
// Can't safely double alpha, will clamp.
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
case GE_DSTBLEND_DOUBLEINVSRCALPHA:
// Doubling alpha is safe for the inverse, will clamp to zero either way.
@@ -412,7 +412,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
if (bufferFormat == GE_FORMAT_565) {
return REPLACE_BLEND_STANDARD;
}
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
case GE_DSTBLEND_FIXB:
default:
@@ -446,14 +446,14 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
if (funcA == GE_SRCBLEND_SRCALPHA || funcA == GE_SRCBLEND_INVSRCALPHA) {
// Can't safely double alpha, will clamp. However, a copy may easily be worse due to overlap.
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH))
return !allowShaderBlend ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return REPLACE_BLEND_PRE_SRC_2X_ALPHA;
} else {
// This means dst alpha/color is used in the src factor.
// Unfortunately, copying here causes overlap problems in Silent Hill games (it seems?)
// We will just hope that doubling alpha for the dst factor will not clamp too badly.
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH))
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return REPLACE_BLEND_2X_ALPHA;
}
@@ -470,7 +470,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
if (bufferFormat == GE_FORMAT_565) {
return REPLACE_BLEND_STANDARD;
}
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
default:
return REPLACE_BLEND_STANDARD;
@@ -906,7 +906,7 @@ static void ApplyLogicOp(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq &
}
// Try to simulate some common logic ops.
void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState) {
void ApplyStencilReplaceAndLogicOpIgnoreBlend(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState) {
StencilValueType stencilType = STENCIL_VALUE_KEEP;
if (replaceAlphaWithStencil == REPLACE_ALPHA_YES) {
stencilType = ReplaceAlphaWithStencilType();
@@ -958,7 +958,7 @@ void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, Gen
// Called even if AlphaBlendEnable == false - it also deals with stencil-related blend state.
void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
void ConvertBlendState(GenericBlendState &blendState, bool allowFramebufferRead) {
// Blending is a bit complex to emulate. This is due to several reasons:
//
// * Doubled blend modes (src, dst, inversed) aren't supported in OpenGL.
@@ -969,25 +969,25 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
//
// If we can't apply blending, we make a copy of the framebuffer and do it manually.
blendState.applyShaderBlending = false;
blendState.dirtyShaderBlend = false;
blendState.applyFramebufferRead = false;
blendState.dirtyShaderBlendFixValues = false;
blendState.useBlendColor = false;
blendState.replaceAlphaWithStencil = REPLACE_ALPHA_NO;
ReplaceBlendType replaceBlend = ReplaceBlendWithShader(allowShaderBlend, gstate.FrameBufFormat());
ReplaceBlendType replaceBlend = ReplaceBlendWithShader(allowFramebufferRead, gstate.FrameBufFormat());
ReplaceAlphaType replaceAlphaWithStencil = ReplaceAlphaWithStencil(replaceBlend);
bool usePreSrc = false;
switch (replaceBlend) {
case REPLACE_BLEND_NO:
blendState.resetShaderBlending = true;
blendState.resetFramebufferRead = true;
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp(replaceAlphaWithStencil, blendState);
ApplyStencilReplaceAndLogicOpIgnoreBlend(replaceAlphaWithStencil, blendState);
return;
case REPLACE_BLEND_COPY_FBO:
blendState.applyShaderBlending = true;
blendState.resetShaderBlending = false;
blendState.applyFramebufferRead = true;
blendState.resetFramebufferRead = false;
blendState.replaceAlphaWithStencil = replaceAlphaWithStencil;
break;
@@ -1003,7 +1003,7 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
}
blendState.enabled = true;
blendState.resetShaderBlending = true;
blendState.resetFramebufferRead = true;
const GEBlendMode blendFuncEq = gstate.getBlendEq();
GEBlendSrcFactor blendFuncA = gstate.getBlendFuncA();
@@ -1071,7 +1071,7 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
glBlendFuncA = BlendFactor::ONE;
// Need to pull in the fixed color. TODO: If it hasn't changed, no need to dirty.
if (blendFuncA == GE_SRCBLEND_FIXA) {
blendState.dirtyShaderBlend = true;
blendState.dirtyShaderBlendFixValues = true;
}
}
+4 -4
View File
@@ -121,9 +121,9 @@ enum class BlendEq : uint8_t {
struct GenericBlendState {
bool enabled;
bool resetShaderBlending;
bool applyShaderBlending;
bool dirtyShaderBlend;
bool resetFramebufferRead;
bool applyFramebufferRead;
bool dirtyShaderBlendFixValues;
ReplaceAlphaType replaceAlphaWithStencil;
BlendFactor srcColor;
@@ -158,7 +158,7 @@ struct GenericBlendState {
};
void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend);
void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState);
void ApplyStencilReplaceAndLogicOpIgnoreBlend(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState);
struct GenericStencilFuncState {
bool enabled;
+3 -1
View File
@@ -240,7 +240,9 @@ void ComputeFragmentShaderID(FShaderID *id_out, const Draw::Bugs &bugs) {
bool doFlatShading = gstate.getShadeMode() == GE_SHADE_FLAT;
bool useShaderDepal = gstate_c.useShaderDepal;
ReplaceBlendType replaceBlend = ReplaceBlendWithShader(gstate_c.allowShaderBlend, gstate.FrameBufFormat());
// Note how we here recompute some of the work already done in state mapping.
// Not ideal! At least we share the code.
ReplaceBlendType replaceBlend = ReplaceBlendWithShader(gstate_c.allowFramebufferRead, gstate.FrameBufFormat());
ReplaceAlphaType stencilToAlpha = ReplaceAlphaWithStencil(replaceBlend);
// All texfuncs except replace are the same for RGB as for RGBA with full alpha.
+1 -1
View File
@@ -160,7 +160,7 @@ private:
void ApplyDrawState(int prim);
void ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRef);
void ResetShaderBlending();
void ResetFramebufferRead();
ID3D11InputLayout *SetupDecFmtForDraw(D3D11VertexShader *vshader, const DecVtxFormat &decFmt, u32 pspFmt);
+15 -14
View File
@@ -122,7 +122,7 @@ static const D3D11_LOGIC_OP logicOps[] = {
D3D11_LOGIC_OP_SET,
};
void DrawEngineD3D11::ResetShaderBlending() {
void DrawEngineD3D11::ResetFramebufferRead() {
if (fboTexBound_) {
ID3D11ShaderResourceView *srv = nullptr;
context_->PSSetShaderResources(0, 1, &srv);
@@ -144,7 +144,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
bool useBufferedRendering = framebufferManager_->UseBufferedRendering();
// Blend
if (gstate_c.IsDirty(DIRTY_BLEND_STATE)) {
gstate_c.SetAllowShaderBlend(!g_Config.bDisableSlowFramebufEffects);
gstate_c.SetAllowFramebufferRead(!g_Config.bDisableSlowFramebufEffects);
if (gstate.isModeClear()) {
keys_.blend.value = 0; // full wipe
keys_.blend.blendEnable = false;
@@ -157,18 +157,19 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
keys_.blend.value = 0;
// Set blend - unless we need to do it in the shader.
GenericBlendState blendState;
ConvertBlendState(blendState, gstate_c.allowShaderBlend);
if (blendState.applyShaderBlending) {
if (ApplyShaderBlending()) {
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp(blendState.replaceAlphaWithStencil, blendState);
ConvertBlendState(blendState, gstate_c.allowFramebufferRead);
if (blendState.applyFramebufferRead) {
if (ApplyFramebufferRead(&fboTexNeedsBind_)) {
// The shader takes over the responsibility for blending, so recompute.
ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState);
} else {
// Until next time, force it off.
ResetShaderBlending();
gstate_c.SetAllowShaderBlend(false);
ResetFramebufferRead();
gstate_c.SetAllowFramebufferRead(false);
}
} else if (blendState.resetShaderBlending) {
ResetShaderBlending();
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
} else if (blendState.resetFramebufferRead) {
ResetFramebufferRead();
}
if (blendState.enabled) {
@@ -180,7 +181,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
keys_.blend.srcAlpha = d3d11BlendFactorLookup[(size_t)blendState.srcAlpha];
keys_.blend.destColor = d3d11BlendFactorLookup[(size_t)blendState.dstColor];
keys_.blend.destAlpha = d3d11BlendFactorLookup[(size_t)blendState.dstAlpha];
if (blendState.dirtyShaderBlend) {
if (blendState.dirtyShaderBlendFixValues) {
gstate_c.Dirty(DIRTY_SHADERBLEND);
}
dynState_.useBlendColor = blendState.useBlendColor;
@@ -446,11 +447,11 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
void DrawEngineD3D11::ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRef) {
if (!gstate.isModeClear()) {
if (fboTexNeedBind_) {
if (fboTexNeedsBind_) {
framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY);
// No sampler required, we do a plain Load in the pixel shader.
fboTexBound_ = true;
fboTexNeedBind_ = false;
fboTexNeedsBind_ = false;
}
textureCache_->ApplyTexture();
}
+1 -1
View File
@@ -150,7 +150,7 @@ private:
void ApplyDrawState(int prim);
void ApplyDrawStateLate();
void ResetShaderBlending();
void ResetFramebufferRead();
IDirect3DVertexDeclaration9 *SetupDecFmtForDraw(VSShader *vshader, const DecVtxFormat &decFmt, u32 pspFmt);
+16 -29
View File
@@ -90,7 +90,7 @@ static const D3DSTENCILOP stencilOps[] = {
D3DSTENCILOP_KEEP, // reserved
};
inline void DrawEngineDX9::ResetShaderBlending() {
inline void DrawEngineDX9::ResetFramebufferRead() {
if (fboTexBound_) {
device_->SetTexture(1, nullptr);
fboTexBound_ = false;
@@ -115,8 +115,8 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
if (gstate_c.IsDirty(DIRTY_BLEND_STATE)) {
gstate_c.Clean(DIRTY_BLEND_STATE);
// Unfortunately, this isn't implemented yet.
gstate_c.SetAllowShaderBlend(false);
// Unfortunately, this isn't implemented on DX9 yet.
gstate_c.SetAllowFramebufferRead(false);
if (gstate.isModeClear()) {
dxstate.blend.disable();
@@ -127,19 +127,20 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
} else {
// Set blend - unless we need to do it in the shader.
GenericBlendState blendState;
ConvertBlendState(blendState, gstate_c.allowShaderBlend);
ConvertBlendState(blendState, gstate_c.allowFramebufferRead);
if (blendState.applyShaderBlending) {
if (ApplyShaderBlending()) {
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp(blendState.replaceAlphaWithStencil, blendState);
if (blendState.applyFramebufferRead) {
if (ApplyFramebufferRead(&fboTexNeedsBind_)) {
// The shader takes over the responsibility for blending, so recompute.
ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState);
} else {
// Until next time, force it off.
ResetShaderBlending();
gstate_c.SetAllowShaderBlend(false);
ResetFramebufferRead();
gstate_c.SetAllowFramebufferRead(false);
}
} else if (blendState.resetShaderBlending) {
ResetShaderBlending();
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
} else if (blendState.resetFramebufferRead) {
ResetFramebufferRead();
}
if (blendState.enabled) {
@@ -149,7 +150,7 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
dxstate.blendFunc.set(
dxBlendFactorLookup[(size_t)blendState.srcColor], dxBlendFactorLookup[(size_t)blendState.dstColor],
dxBlendFactorLookup[(size_t)blendState.srcAlpha], dxBlendFactorLookup[(size_t)blendState.dstAlpha]);
if (blendState.dirtyShaderBlend) {
if (blendState.dirtyShaderBlendFixValues) {
gstate_c.Dirty(DIRTY_SHADERBLEND);
}
if (blendState.useBlendColor) {
@@ -166,20 +167,6 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
bool bmask = ((gstate.pmskc >> 16) & 0xFF) < 128;
bool amask = (gstate.pmska & 0xFF) < 128;
#ifndef MOBILE_DEVICE
u8 abits = (gstate.pmska >> 0) & 0xFF;
u8 rbits = (gstate.pmskc >> 0) & 0xFF;
u8 gbits = (gstate.pmskc >> 8) & 0xFF;
u8 bbits = (gstate.pmskc >> 16) & 0xFF;
if ((rbits != 0 && rbits != 0xFF) || (gbits != 0 && gbits != 0xFF) || (bbits != 0 && bbits != 0xFF)) {
WARN_LOG_REPORT_ONCE(rgbmask, G3D, "Unsupported RGB mask: r=%02x g=%02x b=%02x", rbits, gbits, bbits);
}
if (abits != 0 && abits != 0xFF) {
// The stencil part of the mask is supported.
WARN_LOG_REPORT_ONCE(amask, G3D, "Unsupported alpha/stencil mask: %02x", abits);
}
#endif
// Let's not write to alpha if stencil isn't enabled.
if (IsStencilTestOutputDisabled()) {
amask = false;
@@ -297,14 +284,14 @@ void DrawEngineDX9::ApplyDrawStateLate() {
if (!gstate.isModeClear()) {
textureCache_->ApplyTexture();
if (fboTexNeedBind_) {
if (fboTexNeedsBind_) {
// Note that this is positions, not UVs, that we need the copy from.
framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY);
// If we are rendering at a higher resolution, linear is probably best for the dest color.
device_->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device_->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
fboTexBound_ = true;
fboTexNeedBind_ = false;
fboTexNeedsBind_ = false;
}
// TODO: Test texture?
+1 -1
View File
@@ -193,7 +193,7 @@ private:
void DoFlush();
void ApplyDrawState(int prim);
void ApplyDrawStateLate(bool setStencil, int stencilValue);
void ResetShaderBlending();
void ResetFramebufferRead();
GLRInputLayout *SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt);
+16 -27
View File
@@ -121,7 +121,7 @@ static const GLushort logicOps[] = {
};
#endif
inline void DrawEngineGLES::ResetShaderBlending() {
inline void DrawEngineGLES::ResetFramebufferRead() {
if (fboTexBound_) {
GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager->BindTexture(TEX_SLOT_SHADERBLEND_SRC, nullptr);
@@ -156,7 +156,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
if (gstate_c.IsDirty(DIRTY_BLEND_STATE)) {
gstate_c.Clean(DIRTY_BLEND_STATE);
gstate_c.SetAllowShaderBlend(!g_Config.bDisableSlowFramebufEffects);
gstate_c.SetAllowFramebufferRead(!g_Config.bDisableSlowFramebufEffects);
if (gstate.isModeClear()) {
// Color Test
@@ -167,22 +167,22 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
// Do the large chunks of state conversion. We might be able to hide these two behind a dirty-flag each,
// to avoid recomputing heavy stuff unnecessarily every draw call.
GenericBlendState blendState;
ConvertBlendState(blendState, gstate_c.allowShaderBlend);
ConvertBlendState(blendState, gstate_c.allowFramebufferRead);
if (blendState.applyShaderBlending) {
if (ApplyShaderBlending()) {
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp(blendState.replaceAlphaWithStencil, blendState);
if (blendState.applyFramebufferRead) {
if (ApplyFramebufferRead(&fboTexNeedsBind_)) {
// The shader takes over the responsibility for blending, so recompute.
ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState);
// We copy the framebuffer here, as doing so will wipe any blend state if we do it later.
if (fboTexNeedBind_) {
if (fboTexNeedsBind_) {
// Note that this is positions, not UVs, that we need the copy from.
// TODO: If the device doesn't support blit, this will corrupt the currently applied texture.
framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY);
// If we are rendering at a higher resolution, linear is probably best for the dest color.
renderManager->SetTextureSampler(1, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f);
fboTexBound_ = true;
fboTexNeedBind_ = false;
fboTexNeedsBind_ = false;
framebufferManager_->RebindFramebuffer("RebindFramebuffer - ApplyDrawState");
// Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects.
@@ -190,15 +190,17 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
}
} else {
// Until next time, force it off.
ResetShaderBlending();
gstate_c.SetAllowShaderBlend(false);
ResetFramebufferRead();
gstate_c.SetAllowFramebufferRead(false);
}
} else if (blendState.resetShaderBlending) {
ResetShaderBlending();
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
} else if (blendState.resetFramebufferRead) {
ResetFramebufferRead();
}
if (blendState.enabled) {
if (blendState.dirtyShaderBlend) {
if (blendState.dirtyShaderBlendFixValues) {
// Not quite sure how necessary this is.
gstate_c.Dirty(DIRTY_SHADERBLEND);
}
if (blendState.useBlendColor) {
@@ -219,19 +221,6 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
bool gmask = ((gstate.pmskc >> 8) & 0xFF) < 128;
bool bmask = ((gstate.pmskc >> 16) & 0xFF) < 128;
#ifndef MOBILE_DEVICE
u8 abits = (gstate.pmska >> 0) & 0xFF;
u8 rbits = (gstate.pmskc >> 0) & 0xFF;
u8 gbits = (gstate.pmskc >> 8) & 0xFF;
u8 bbits = (gstate.pmskc >> 16) & 0xFF;
if ((rbits != 0 && rbits != 0xFF) || (gbits != 0 && gbits != 0xFF) || (bbits != 0 && bbits != 0xFF)) {
WARN_LOG_REPORT_ONCE(rgbmask, G3D, "Unsupported RGB mask: r=%02x g=%02x b=%02x", rbits, gbits, bbits);
}
if (abits != 0 && abits != 0xFF) {
// The stencil part of the mask is supported.
WARN_LOG_REPORT_ONCE(amask, G3D, "Unsupported alpha/stencil mask: %02x", abits);
}
#endif
int mask = (int)rmask | ((int)gmask << 1) | ((int)bmask << 2) | ((int)amask << 3);
if (blendState.enabled) {
renderManager->SetBlendAndMask(mask, blendState.enabled,
+4 -4
View File
@@ -540,9 +540,9 @@ struct GPUStateCache {
Dirty(DIRTY_TEXCLAMP);
}
}
void SetAllowShaderBlend(bool allow) {
if (allowShaderBlend != allow) {
allowShaderBlend = allow;
void SetAllowFramebufferRead(bool allow) {
if (allowFramebufferRead != allow) {
allowFramebufferRead = allow;
Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
}
@@ -564,7 +564,7 @@ struct GPUStateCache {
bool bgraTexture;
bool needShaderTexClamp;
bool allowShaderBlend;
bool allowFramebufferRead;
float morphWeights[8];
u32 deferredVertTypeDirty;
+1 -1
View File
@@ -199,7 +199,7 @@ private:
void ApplyDrawStateLate(VulkanRenderManager *renderManager, bool applyStencilRef, uint8_t stencilRef, bool useBlendConstant);
void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerVulkan *shaderManager, int prim, VulkanPipelineRasterStateKey &key, VulkanDynamicState &dynState);
void BindShaderBlendTex();
void ResetShaderBlending();
void ResetFramebufferRead();
void InitDeviceObjects();
void DestroyDeviceObjects();
+15 -29
View File
@@ -122,7 +122,7 @@ static const VkLogicOp logicOps[] = {
VK_LOGIC_OP_SET,
};
void DrawEngineVulkan::ResetShaderBlending() {
void DrawEngineVulkan::ResetFramebufferRead() {
boundSecondary_ = VK_NULL_HANDLE;
}
@@ -135,7 +135,7 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
bool useBufferedRendering = framebufferManager_->UseBufferedRendering();
if (gstate_c.IsDirty(DIRTY_BLEND_STATE)) {
gstate_c.SetAllowShaderBlend(!g_Config.bDisableSlowFramebufEffects);
gstate_c.SetAllowFramebufferRead(!g_Config.bDisableSlowFramebufEffects);
if (gstate.isModeClear()) {
key.logicOpEnable = false;
key.logicOp = VK_LOGIC_OP_CLEAR;
@@ -163,21 +163,21 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
// Set blend - unless we need to do it in the shader.
GenericBlendState blendState;
ConvertBlendState(blendState, gstate_c.allowShaderBlend);
ConvertBlendState(blendState, gstate_c.allowFramebufferRead);
if (blendState.applyShaderBlending) {
if (ApplyShaderBlending()) {
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp(blendState.replaceAlphaWithStencil, blendState);
if (blendState.applyFramebufferRead) {
if (ApplyFramebufferRead(&fboTexNeedsBind_)) {
// The shader takes over the responsibility for blending, so recompute.
ApplyStencilReplaceAndLogicOpIgnoreBlend(blendState.replaceAlphaWithStencil, blendState);
} else {
// Until next time, force it off.
ResetShaderBlending();
gstate_c.SetAllowShaderBlend(false);
ResetFramebufferRead();
gstate_c.SetAllowFramebufferRead(false);
// Make sure we recompute the fragment shader ID to one that doesn't try to use shader blending.
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
} else if (blendState.resetShaderBlending) {
ResetShaderBlending();
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
} else if (blendState.resetFramebufferRead) {
ResetFramebufferRead();
}
if (blendState.enabled) {
@@ -188,7 +188,7 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
key.srcAlpha = vkBlendFactorLookup[(size_t)blendState.srcAlpha];
key.destColor = vkBlendFactorLookup[(size_t)blendState.dstColor];
key.destAlpha = vkBlendFactorLookup[(size_t)blendState.dstAlpha];
if (blendState.dirtyShaderBlend) {
if (blendState.dirtyShaderBlendFixValues) {
gstate_c.Dirty(DIRTY_SHADERBLEND);
}
dynState.useBlendColor = blendState.useBlendColor;
@@ -213,20 +213,6 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
bool bmask = ((gstate.pmskc >> 16) & 0xFF) < 128;
bool amask = (gstate.pmska & 0xFF) < 128;
#ifndef MOBILE_DEVICE
u8 abits = (gstate.pmska >> 0) & 0xFF;
u8 rbits = (gstate.pmskc >> 0) & 0xFF;
u8 gbits = (gstate.pmskc >> 8) & 0xFF;
u8 bbits = (gstate.pmskc >> 16) & 0xFF;
if ((rbits != 0 && rbits != 0xFF) || (gbits != 0 && gbits != 0xFF) || (bbits != 0 && bbits != 0xFF)) {
WARN_LOG_REPORT_ONCE(rgbmask, G3D, "Unsupported RGB mask: r=%02x g=%02x b=%02x", rbits, gbits, bbits);
}
if (abits != 0 && abits != 0xFF) {
// The stencil part of the mask is supported.
WARN_LOG_REPORT_ONCE(amask, G3D, "Unsupported alpha/stencil mask: %02x", abits);
}
#endif
// Let's not write to alpha if stencil isn't enabled.
if (IsStencilTestOutputDisabled()) {
amask = false;
@@ -395,13 +381,13 @@ void DrawEngineVulkan::BindShaderBlendTex() {
// TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)?
if (!gstate.isModeClear()) {
// TODO: Test texture?
if (fboTexNeedBind_) {
if (fboTexNeedsBind_) {
// Note that this is positions, not UVs, that we need the copy from.
framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY);
// If we are rendering at a higher resolution, linear is probably best for the dest color.
boundSecondary_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE1_IMAGEVIEW);
fboTexBound_ = true;
fboTexNeedBind_ = false;
fboTexNeedsBind_ = false;
}
}
+7 -7
View File
@@ -462,8 +462,8 @@ void RasterizeFonts(const FontReferenceList &fontRefs, vector<CharRange> &ranges
} else {
dist = -closest.find_closest(ctx, cty, 1);
}
dist = dist / supersample * distmult + 127.5;
dist = floor(dist + 0.5);
dist = dist / supersample * distmult + 127.5f;
dist = floor(dist + 0.5f);
if (dist < 0) dist = 0;
if (dist > 255) dist = 255;
@@ -564,7 +564,7 @@ struct FontDesc {
}
}
height = metrics_height / 64.0 / supersample;
height = metrics_height / 64.0f / supersample;
}
void OutputSelf(FILE *fil, float tw, float th, const vector<Data> &results) const {
@@ -987,7 +987,7 @@ int main(int argc, char **argv) {
fwrite(&header, 1, sizeof(header), meta);
// For each image
for (int i = 0; i < (int)images.size(); i++) {
AtlasImage atlas_image = images[i].ToAtlasImage(dest.width(), dest.height(), results);
AtlasImage atlas_image = images[i].ToAtlasImage((float)dest.width(), (float)dest.height(), results);
fwrite(&atlas_image, 1, sizeof(atlas_image), meta);
}
// For each font
@@ -998,7 +998,7 @@ int main(int argc, char **argv) {
fwrite(&font_header, 1, sizeof(font_header), meta);
auto ranges = font.GetRanges();
fwrite(ranges.data(), sizeof(AtlasCharRange), ranges.size(), meta);
auto chars = font.GetChars(dest.width(), dest.height(), results);
auto chars = font.GetChars((float)dest.width(), (float)dest.height(), results);
fwrite(chars.data(), sizeof(AtlasChar), chars.size(), meta);
}
fclose(meta);
@@ -1010,7 +1010,7 @@ int main(int argc, char **argv) {
for (int i = 0; i < (int)fonts.size(); i++) {
FontDesc &xfont = fonts[i];
xfont.ComputeHeight(results, distmult);
xfont.OutputSelf(cpp_file, dest.width(), dest.height(), results);
xfont.OutputSelf(cpp_file, (float)dest.width(), (float)dest.height(), results);
}
if (fonts.size()) {
@@ -1024,7 +1024,7 @@ int main(int argc, char **argv) {
if (images.size()) {
fprintf(cpp_file, "const AtlasImage %s_images[%i] = {\n", atlas_name, (int)images.size());
for (int i = 0; i < (int)images.size(); i++) {
images[i].OutputSelf(cpp_file, dest.width(), dest.height(), results);
images[i].OutputSelf(cpp_file, (float)dest.width(), (float)dest.height(), results);
}
fprintf(cpp_file, "};\n");
}
+3 -3
View File
@@ -70,7 +70,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
@@ -90,7 +90,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../../../../;../../ext;../../;../../../../ext;../prebuilt</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -108,4 +108,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>