mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
OpenGL: Generate fragment shaders directly from the ID.
This commit is contained in:
parent
633385252b
commit
39f04ab5d6
3 changed files with 132 additions and 98 deletions
|
@ -16,9 +16,8 @@
|
|||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#if !defined(USING_GLES2)
|
||||
// We do not yet enable OpenGL 3 on Apple, so we need
|
||||
// special treatment in the shader generator. However, the GL version check
|
||||
// should be enough? TODO
|
||||
// SDL 1.2 on Apple does not have support for OpenGL 3 and hence needs
|
||||
// special treatment in the shader generator.
|
||||
#if defined(__APPLE__)
|
||||
#define FORCE_OPENGL_2_0
|
||||
#endif
|
||||
|
@ -300,14 +299,44 @@ static inline LogicOpReplaceType ReplaceLogicOpType() {
|
|||
return LOGICOPTYPE_NORMAL;
|
||||
}
|
||||
|
||||
// Local
|
||||
enum {
|
||||
BIT_CLEARMODE = 0,
|
||||
BIT_DO_TEXTURE = 1,
|
||||
BIT_TEXFUNC = 2, // 3 bits
|
||||
BIT_TEXALPHA = 5,
|
||||
BIT_FLIP_TEXTURE = 6,
|
||||
BIT_SHADER_TEX_CLAMP = 7,
|
||||
BIT_CLAMP_S = 8,
|
||||
BIT_CLAMP_T = 9,
|
||||
BIT_TEXTURE_AT_OFFSET = 10,
|
||||
BIT_LMODE = 11,
|
||||
BIT_ALPHA_TEST = 12,
|
||||
BIT_ALPHA_TEST_FUNC = 13, // 3 bits
|
||||
BIT_ALPHA_AGAINST_ZERO = 16,
|
||||
BIT_COLOR_TEST = 17,
|
||||
BIT_COLOR_TEST_FUNC = 18, // 2 bits
|
||||
BIT_COLOR_AGAINST_ZERO = 20,
|
||||
BIT_ENABLE_FOG = 21,
|
||||
BIT_DO_TEXTURE_PROJ = 22,
|
||||
BIT_COLOR_DOUBLE = 23,
|
||||
BIT_STENCIL_TO_ALPHA = 24, // 2 bits
|
||||
BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE = 26, // 4 bits
|
||||
BIT_REPLACE_LOGIC_OP_TYPE = 30, // 2 bits
|
||||
BIT_REPLACE_BLEND = 32, // 3 bits
|
||||
BIT_BLENDEQ = 35, // 3 bits
|
||||
BIT_BLENDFUNC_A = 38, // 4 bits
|
||||
BIT_BLENDFUNC_B = 42,
|
||||
BIT_FLATSHADE = 46,
|
||||
};
|
||||
|
||||
// Here we must take all the bits of the gstate that determine what the fragment shader will
|
||||
// look like, and concatenate them together into an ID.
|
||||
void ComputeFragmentShaderID(ShaderID *id) {
|
||||
int id0 = 0;
|
||||
int id1 = 0;
|
||||
void ComputeFragmentShaderID(ShaderID *id_out, uint32_t vertType) {
|
||||
ShaderID id;
|
||||
if (gstate.isModeClear()) {
|
||||
// We only need one clear shader, so let's ignore the rest of the bits.
|
||||
id0 = 1;
|
||||
id.SetBit(BIT_CLEARMODE);
|
||||
} else {
|
||||
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled() && !gstate.isModeThrough();
|
||||
bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough();
|
||||
|
@ -317,6 +346,7 @@ void ComputeFragmentShaderID(ShaderID *id) {
|
|||
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
bool doTextureAlpha = gstate.isTextureAlphaUsed();
|
||||
bool doFlatShading = gstate.getShadeMode() == GE_SHADE_FLAT;
|
||||
|
||||
ReplaceBlendType replaceBlend = ReplaceBlendWithShader(gstate_c.allowShaderBlend);
|
||||
ReplaceAlphaType stencilToAlpha = ReplaceAlphaWithStencil(replaceBlend);
|
||||
|
||||
|
@ -326,45 +356,47 @@ void ComputeFragmentShaderID(ShaderID *id) {
|
|||
|
||||
// id0 |= (gstate.isModeClear() & 1);
|
||||
if (gstate.isTextureMapEnabled()) {
|
||||
id0 |= 1 << 1;
|
||||
id0 |= gstate.getTextureFunction() << 2;
|
||||
id0 |= (doTextureAlpha & 1) << 5; // rgb or rgba
|
||||
id0 |= (gstate_c.flipTexture & 1) << 6;
|
||||
|
||||
id.SetBit(BIT_DO_TEXTURE);
|
||||
id.SetBits(BIT_TEXFUNC, 3, gstate.getTextureFunction());
|
||||
id.SetBit(BIT_TEXALPHA, doTextureAlpha & 1); // rgb or rgba
|
||||
id.SetBit(BIT_FLIP_TEXTURE, gstate_c.flipTexture);
|
||||
// TODO
|
||||
if (gstate_c.needShaderTexClamp) {
|
||||
bool textureAtOffset = gstate_c.curTextureXOffset != 0 || gstate_c.curTextureYOffset != 0;
|
||||
// 3 bits total.
|
||||
id0 |= 1 << 7;
|
||||
id0 |= gstate.isTexCoordClampedS() << 8;
|
||||
id0 |= gstate.isTexCoordClampedT() << 9;
|
||||
id0 |= (textureAtOffset & 1) << 10;
|
||||
// 4 bits total.
|
||||
id.SetBit(BIT_SHADER_TEX_CLAMP);
|
||||
id.SetBit(BIT_CLAMP_S, gstate.isTexCoordClampedS());
|
||||
id.SetBit(BIT_CLAMP_T, gstate.isTexCoordClampedT());
|
||||
id.SetBit(BIT_TEXTURE_AT_OFFSET, textureAtOffset);
|
||||
}
|
||||
}
|
||||
|
||||
id0 |= (lmode & 1) << 11;
|
||||
id.SetBit(BIT_LMODE, lmode);
|
||||
#if !defined(DX9_USE_HW_ALPHA_TEST)
|
||||
if (enableAlphaTest) {
|
||||
// 5 bits total.
|
||||
id0 |= 1 << 12;
|
||||
id0 |= gstate.getAlphaTestFunction() << 13;
|
||||
id0 |= (IsAlphaTestAgainstZero() & 1) << 16;
|
||||
id.SetBit(BIT_ALPHA_TEST);
|
||||
id.SetBits(BIT_ALPHA_TEST_FUNC, 3, gstate.getAlphaTestFunction());
|
||||
id.SetBit(BIT_ALPHA_AGAINST_ZERO, IsAlphaTestAgainstZero());
|
||||
}
|
||||
#endif
|
||||
if (enableColorTest) {
|
||||
// 4 bits total.
|
||||
id0 |= 1 << 17;
|
||||
id0 |= gstate.getColorTestFunction() << 18;
|
||||
id0 |= (IsColorTestAgainstZero() & 1) << 20;
|
||||
id.SetBit(BIT_COLOR_TEST);
|
||||
id.SetBits(BIT_COLOR_TEST_FUNC, 2, gstate.getColorTestFunction());
|
||||
id.SetBit(BIT_COLOR_AGAINST_ZERO, IsColorTestAgainstZero());
|
||||
}
|
||||
id0 |= (enableFog & 1) << 21;
|
||||
id0 |= (doTextureProjection & 1) << 22;
|
||||
id0 |= (enableColorDoubling & 1) << 23;
|
||||
|
||||
id.SetBit(BIT_ENABLE_FOG, enableFog);
|
||||
id.SetBit(BIT_DO_TEXTURE_PROJ, doTextureProjection);
|
||||
id.SetBit(BIT_COLOR_DOUBLE, enableColorDoubling);
|
||||
|
||||
// 2 bits
|
||||
id0 |= (stencilToAlpha) << 24;
|
||||
id.SetBits(BIT_STENCIL_TO_ALPHA, 2, stencilToAlpha);
|
||||
|
||||
if (stencilToAlpha != REPLACE_ALPHA_NO) {
|
||||
// 4 bits
|
||||
id0 |= ReplaceAlphaWithStencilType() << 26;
|
||||
id.SetBits(BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, 4, ReplaceAlphaWithStencilType());
|
||||
}
|
||||
|
||||
if (enableAlphaTest)
|
||||
|
@ -373,25 +405,24 @@ void ComputeFragmentShaderID(ShaderID *id) {
|
|||
gpuStats.numNonAlphaTestedDraws++;
|
||||
|
||||
// 2 bits.
|
||||
id0 |= ReplaceLogicOpType() << 30;
|
||||
id.SetBits(BIT_REPLACE_LOGIC_OP_TYPE, 2, ReplaceLogicOpType());
|
||||
|
||||
// 3 bits.
|
||||
id1 |= replaceBlend << 0;
|
||||
id.SetBits(BIT_REPLACE_BLEND, 3, replaceBlend);
|
||||
if (replaceBlend > REPLACE_BLEND_STANDARD) {
|
||||
// 11 bits total.
|
||||
id1 |= gstate.getBlendEq() << 3;
|
||||
id1 |= gstate.getBlendFuncA() << 6;
|
||||
id1 |= gstate.getBlendFuncB() << 10;
|
||||
id.SetBits(BIT_BLENDEQ, 3, gstate.getBlendEq());
|
||||
id.SetBits(BIT_BLENDFUNC_A, 4, gstate.getBlendFuncA());
|
||||
id.SetBits(BIT_BLENDFUNC_B, 4, gstate.getBlendFuncB());
|
||||
}
|
||||
id1 |= (doFlatShading & 1) << 14;
|
||||
id.SetBit(BIT_FLATSHADE, doFlatShading);
|
||||
}
|
||||
|
||||
id->d[0] = id0;
|
||||
id->d[1] = id1;
|
||||
*id_out = id;
|
||||
}
|
||||
|
||||
// Missing: Z depth range
|
||||
void GenerateFragmentShader(char *buffer) {
|
||||
void GenerateFragmentShader(const ShaderID &id, char *buffer) {
|
||||
char *p = buffer;
|
||||
|
||||
// In GLSL ES 3.0, you use "in" variables instead of varying.
|
||||
|
@ -482,48 +513,61 @@ void GenerateFragmentShader(char *buffer) {
|
|||
varying = "in";
|
||||
}
|
||||
|
||||
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled() && !gstate.isModeThrough();
|
||||
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
|
||||
bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear();
|
||||
bool enableAlphaTest = gstate.isAlphaTestEnabled() && !IsAlphaTestTriviallyTrue() && !gstate.isModeClear() && !g_Config.bDisableAlphaTest;
|
||||
bool alphaTestAgainstZero = IsAlphaTestAgainstZero();
|
||||
bool enableColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue() && !gstate.isModeClear();
|
||||
bool colorTestAgainstZero = IsColorTestAgainstZero();
|
||||
bool enableColorDoubling = gstate.isColorDoublingEnabled() && gstate.isTextureMapEnabled();
|
||||
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
bool doTextureAlpha = gstate.isTextureAlphaUsed();
|
||||
bool doFlatShading = gstate.getShadeMode() == GE_SHADE_FLAT && !gstate.isModeClear();
|
||||
bool lmode = id.Bit(BIT_LMODE);
|
||||
bool doTexture = id.Bit(BIT_DO_TEXTURE);
|
||||
bool enableFog = id.Bit(BIT_ENABLE_FOG);
|
||||
bool enableAlphaTest = id.Bit(BIT_ALPHA_TEST);
|
||||
|
||||
bool textureAtOffset = gstate_c.curTextureXOffset != 0 || gstate_c.curTextureYOffset != 0;
|
||||
ReplaceBlendType replaceBlend = ReplaceBlendWithShader(gstate_c.allowShaderBlend);
|
||||
ReplaceAlphaType stencilToAlpha = ReplaceAlphaWithStencil(replaceBlend);
|
||||
bool alphaTestAgainstZero = id.Bit(BIT_ALPHA_AGAINST_ZERO);
|
||||
bool enableColorTest = id.Bit(BIT_COLOR_TEST);
|
||||
bool colorTestAgainstZero = id.Bit(BIT_COLOR_AGAINST_ZERO);
|
||||
bool enableColorDoubling = id.Bit(BIT_COLOR_DOUBLE);
|
||||
bool doTextureProjection = id.Bit(BIT_DO_TEXTURE_PROJ);
|
||||
bool doTextureAlpha = id.Bit(BIT_TEXALPHA);
|
||||
bool doFlatShading = id.Bit(BIT_FLATSHADE);
|
||||
bool flipTexture = id.Bit(BIT_FLIP_TEXTURE);
|
||||
|
||||
GEComparison alphaTestFunc = (GEComparison)id.Bits(BIT_ALPHA_TEST_FUNC, 3);
|
||||
GEComparison colorTestFunc = (GEComparison)id.Bits(BIT_COLOR_TEST_FUNC, 2);
|
||||
bool needShaderTexClamp = id.Bit(BIT_SHADER_TEX_CLAMP);
|
||||
|
||||
GETexFunc texFunc = (GETexFunc)id.Bits(BIT_TEXFUNC, 3);
|
||||
bool textureAtOffset = id.Bit(BIT_TEXTURE_AT_OFFSET);
|
||||
|
||||
ReplaceBlendType replaceBlend = static_cast<ReplaceBlendType>(id.Bits(BIT_REPLACE_BLEND, 3));
|
||||
ReplaceAlphaType stencilToAlpha = static_cast<ReplaceAlphaType>(id.Bits(BIT_STENCIL_TO_ALPHA, 4));
|
||||
|
||||
GEBlendSrcFactor replaceBlendFuncA = (GEBlendSrcFactor)id.Bits(BIT_BLENDFUNC_A, 4);
|
||||
GEBlendDstFactor replaceBlendFuncB = (GEBlendDstFactor)id.Bits(BIT_BLENDFUNC_B, 4);
|
||||
GEBlendMode replaceBlendEq = (GEBlendMode)id.Bits(BIT_BLENDEQ, 3);
|
||||
|
||||
bool isModeClear = id.Bit(BIT_CLEARMODE);
|
||||
|
||||
const char *shading = "";
|
||||
if (glslES30)
|
||||
shading = doFlatShading ? "flat" : "";
|
||||
|
||||
if (gstate_c.textureFullAlpha && gstate.getTextureFunction() != GE_TEXFUNC_REPLACE)
|
||||
doTextureAlpha = false;
|
||||
|
||||
if (doTexture)
|
||||
WRITE(p, "uniform sampler2D tex;\n");
|
||||
if (!gstate.isModeClear() && replaceBlend > REPLACE_BLEND_STANDARD) {
|
||||
if (!(gstate_c.featureFlags & GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH) && replaceBlend == REPLACE_BLEND_COPY_FBO) {
|
||||
|
||||
if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
|
||||
if (!gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH) && replaceBlend == REPLACE_BLEND_COPY_FBO) {
|
||||
if (!texelFetch) {
|
||||
WRITE(p, "uniform vec2 u_fbotexSize;\n");
|
||||
}
|
||||
WRITE(p, "uniform sampler2D fbotex;\n");
|
||||
}
|
||||
if (gstate.getBlendFuncA() == GE_SRCBLEND_FIXA) {
|
||||
if (replaceBlendFuncA == GE_SRCBLEND_FIXA) {
|
||||
WRITE(p, "uniform vec3 u_blendFixA;\n");
|
||||
}
|
||||
if (gstate.getBlendFuncB() == GE_DSTBLEND_FIXB) {
|
||||
if (replaceBlendFuncB == GE_DSTBLEND_FIXB) {
|
||||
WRITE(p, "uniform vec3 u_blendFixB;\n");
|
||||
}
|
||||
}
|
||||
if (gstate_c.needShaderTexClamp && doTexture) {
|
||||
|
||||
if (needShaderTexClamp && doTexture) {
|
||||
WRITE(p, "uniform vec4 u_texclamp;\n");
|
||||
if (textureAtOffset) {
|
||||
if (id.Bit(BIT_TEXTURE_AT_OFFSET)) {
|
||||
WRITE(p, "uniform vec2 u_texclampoff;\n");
|
||||
}
|
||||
}
|
||||
|
@ -538,10 +582,12 @@ void GenerateFragmentShader(char *buffer) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (stencilToAlpha && ReplaceAlphaWithStencilType() == STENCIL_VALUE_UNIFORM) {
|
||||
|
||||
StencilValueType replaceAlphaWithStencilType = (StencilValueType)id.Bits(BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, 4);
|
||||
if (stencilToAlpha && replaceAlphaWithStencilType == STENCIL_VALUE_UNIFORM) {
|
||||
WRITE(p, "uniform float u_stencilReplaceValue;\n");
|
||||
}
|
||||
if (gstate.isTextureMapEnabled() && gstate.getTextureFunction() == GE_TEXFUNC_BLEND)
|
||||
if (doTexture && texFunc == GE_TEXFUNC_BLEND)
|
||||
WRITE(p, "uniform vec3 u_texenv;\n");
|
||||
|
||||
WRITE(p, "%s %s vec4 v_color0;\n", shading, varying);
|
||||
|
@ -587,13 +633,13 @@ void GenerateFragmentShader(char *buffer) {
|
|||
}
|
||||
|
||||
// PowerVR needs a custom modulo function. For some reason, this has far higher precision than the builtin one.
|
||||
if ((gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) && gstate_c.needShaderTexClamp) {
|
||||
if ((gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) && needShaderTexClamp) {
|
||||
WRITE(p, "float mymod(float a, float b) { return a - b * floor(a / b); }\n");
|
||||
}
|
||||
|
||||
WRITE(p, "void main() {\n");
|
||||
|
||||
if (gstate.isModeClear()) {
|
||||
if (isModeClear) {
|
||||
// Clear mode does not allow any fancy shading.
|
||||
WRITE(p, " vec4 v = v_color0;\n");
|
||||
} else {
|
||||
|
@ -606,11 +652,11 @@ void GenerateFragmentShader(char *buffer) {
|
|||
secondary = "";
|
||||
}
|
||||
|
||||
if (gstate.isTextureMapEnabled()) {
|
||||
if (doTexture) {
|
||||
const char *texcoord = "v_texcoord";
|
||||
// TODO: Not sure the right way to do this for projection.
|
||||
// This path destroys resolution on older PowerVR no matter what I do, so we disable it on SGX 540 and lesser, and live with the consequences.
|
||||
if (gstate_c.needShaderTexClamp && !(gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_TERRIBLE)) {
|
||||
if (needShaderTexClamp && !(gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_TERRIBLE)) {
|
||||
// We may be clamping inside a larger surface (tex = 64x64, buffer=480x272).
|
||||
// We may also be wrapping in such a surface, or either one in a too-small surface.
|
||||
// Obviously, clamping to a smaller surface won't work. But better to clamp to something.
|
||||
|
@ -619,19 +665,19 @@ void GenerateFragmentShader(char *buffer) {
|
|||
if (doTextureProjection) {
|
||||
ucoord += " / v_texcoord.z";
|
||||
vcoord = "(v_texcoord.y / v_texcoord.z)";
|
||||
// Vertex texcoords are NOT flipped when projecting despite gstate_c.flipTexture.
|
||||
} else if (gstate_c.flipTexture) {
|
||||
// Vertex texcoords are NOT flipped when projecting despite flipTexture.
|
||||
} else if (flipTexture) {
|
||||
vcoord = "1.0 - " + vcoord;
|
||||
}
|
||||
|
||||
std::string modulo = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) ? "mymod" : "mod";
|
||||
|
||||
if (gstate.isTexCoordClampedS()) {
|
||||
if (id.Bit(BIT_CLAMP_S)) {
|
||||
ucoord = "clamp(" + ucoord + ", u_texclamp.z, u_texclamp.x - u_texclamp.z)";
|
||||
} else {
|
||||
ucoord = modulo + "(" + ucoord + ", u_texclamp.x)";
|
||||
}
|
||||
if (gstate.isTexCoordClampedT()) {
|
||||
if (id.Bit(BIT_CLAMP_T)) {
|
||||
vcoord = "clamp(" + vcoord + ", u_texclamp.w, u_texclamp.y - u_texclamp.w)";
|
||||
} else {
|
||||
vcoord = modulo + "(" + vcoord + ", u_texclamp.y)";
|
||||
|
@ -641,7 +687,7 @@ void GenerateFragmentShader(char *buffer) {
|
|||
vcoord = "(" + vcoord + " + u_texclampoff.y)";
|
||||
}
|
||||
|
||||
if (gstate_c.flipTexture) {
|
||||
if (flipTexture) {
|
||||
vcoord = "1.0 - " + vcoord;
|
||||
}
|
||||
|
||||
|
@ -649,7 +695,7 @@ void GenerateFragmentShader(char *buffer) {
|
|||
texcoord = "fixedcoord";
|
||||
// We already projected it.
|
||||
doTextureProjection = false;
|
||||
} else if (doTextureProjection && gstate_c.flipTexture) {
|
||||
} else if (doTextureProjection && flipTexture) {
|
||||
// Since we need to flip v, we project manually.
|
||||
WRITE(p, " vec2 fixedcoord = vec2(v_texcoord.x / v_texcoord.z, 1.0 - (v_texcoord.y / v_texcoord.z));\n");
|
||||
texcoord = "fixedcoord";
|
||||
|
@ -664,7 +710,7 @@ void GenerateFragmentShader(char *buffer) {
|
|||
WRITE(p, " vec4 p = v_color0;\n");
|
||||
|
||||
if (doTextureAlpha) { // texfmt == RGBA
|
||||
switch (gstate.getTextureFunction()) {
|
||||
switch (texFunc) {
|
||||
case GE_TEXFUNC_MODULATE:
|
||||
WRITE(p, " vec4 v = p * t%s;\n", secondary);
|
||||
break;
|
||||
|
@ -691,7 +737,7 @@ void GenerateFragmentShader(char *buffer) {
|
|||
WRITE(p, " vec4 v = p;\n"); break;
|
||||
}
|
||||
} else { // texfmt == RGB
|
||||
switch (gstate.getTextureFunction()) {
|
||||
switch (texFunc) {
|
||||
case GE_TEXFUNC_MODULATE:
|
||||
WRITE(p, " vec4 v = vec4(t.rgb * p.rgb, p.a)%s;\n", secondary);
|
||||
break;
|
||||
|
@ -738,7 +784,6 @@ void GenerateFragmentShader(char *buffer) {
|
|||
|
||||
if (enableAlphaTest) {
|
||||
if (alphaTestAgainstZero) {
|
||||
GEComparison alphaTestFunc = gstate.getAlphaTestFunction();
|
||||
// When testing against 0 (extremely common), we can avoid some math.
|
||||
// 0.002 is approximately half of 1.0 / 255.0.
|
||||
if (alphaTestFunc == GE_COMP_NOTEQUAL || alphaTestFunc == GE_COMP_GREATER) {
|
||||
|
@ -755,7 +800,6 @@ void GenerateFragmentShader(char *buffer) {
|
|||
WRITE(p, " float aResult = %s(testtex, vec2(%s, 0)).a;\n", texture, alphaTestXCoord.c_str());
|
||||
WRITE(p, " if (aResult < 0.5) discard;\n");
|
||||
} else {
|
||||
GEComparison alphaTestFunc = gstate.getAlphaTestFunction();
|
||||
const char *alphaTestFuncs[] = { "#", "#", " != ", " == ", " >= ", " > ", " <= ", " < " };
|
||||
if (alphaTestFuncs[alphaTestFunc][0] != '#') {
|
||||
if (bitwiseOps) {
|
||||
|
@ -777,7 +821,6 @@ void GenerateFragmentShader(char *buffer) {
|
|||
|
||||
if (enableColorTest) {
|
||||
if (colorTestAgainstZero) {
|
||||
GEComparison colorTestFunc = gstate.getColorTestFunction();
|
||||
// When testing against 0 (common), we can avoid some math.
|
||||
// 0.002 is approximately half of 1.0 / 255.0.
|
||||
if (colorTestFunc == GE_COMP_NOTEQUAL) {
|
||||
|
@ -794,7 +837,6 @@ void GenerateFragmentShader(char *buffer) {
|
|||
WRITE(p, " float rResult = %s(testtex, vec2(vScale256.r, 0)).r;\n", texture);
|
||||
WRITE(p, " float gResult = %s(testtex, vec2(vScale256.g, 0)).g;\n", texture);
|
||||
WRITE(p, " float bResult = %s(testtex, vec2(vScale256.b, 0)).b;\n", texture);
|
||||
GEComparison colorTestFunc = gstate.getColorTestFunction();
|
||||
if (colorTestFunc == GE_COMP_EQUAL) {
|
||||
// Equal means all parts must be equal.
|
||||
WRITE(p, " if (rResult < 0.5 || gResult < 0.5 || bResult < 0.5) discard;\n");
|
||||
|
@ -803,7 +845,6 @@ void GenerateFragmentShader(char *buffer) {
|
|||
WRITE(p, " if (rResult < 0.5 && gResult < 0.5 && bResult < 0.5) discard;\n");
|
||||
}
|
||||
} else {
|
||||
GEComparison colorTestFunc = gstate.getColorTestFunction();
|
||||
const char *colorTestFuncs[] = { "#", "#", " != ", " == " };
|
||||
if (colorTestFuncs[colorTestFunc][0] != '#') {
|
||||
if (bitwiseOps) {
|
||||
|
@ -837,9 +878,8 @@ void GenerateFragmentShader(char *buffer) {
|
|||
}
|
||||
|
||||
if (replaceBlend == REPLACE_BLEND_PRE_SRC || replaceBlend == REPLACE_BLEND_PRE_SRC_2X_ALPHA) {
|
||||
GEBlendSrcFactor funcA = gstate.getBlendFuncA();
|
||||
const char *srcFactor = "ERROR";
|
||||
switch (funcA) {
|
||||
switch (replaceBlendFuncA) {
|
||||
case GE_SRCBLEND_DSTCOLOR: srcFactor = "ERROR"; break;
|
||||
case GE_SRCBLEND_INVDSTCOLOR: srcFactor = "ERROR"; break;
|
||||
case GE_SRCBLEND_SRCALPHA: srcFactor = "vec3(v.a)"; break;
|
||||
|
@ -867,15 +907,10 @@ void GenerateFragmentShader(char *buffer) {
|
|||
WRITE(p, " lowp vec4 destColor = %s(fbotex, ivec2(gl_FragCoord.x, gl_FragCoord.y), 0);\n", texelFetch);
|
||||
}
|
||||
|
||||
GEBlendSrcFactor funcA = gstate.getBlendFuncA();
|
||||
GEBlendDstFactor funcB = gstate.getBlendFuncB();
|
||||
GEBlendMode eq = gstate.getBlendEq();
|
||||
|
||||
const char *srcFactor = "vec3(1.0)";
|
||||
const char *dstFactor = "vec3(0.0)";
|
||||
|
||||
switch (funcA)
|
||||
{
|
||||
switch (replaceBlendFuncA) {
|
||||
case GE_SRCBLEND_DSTCOLOR: srcFactor = "destColor.rgb"; break;
|
||||
case GE_SRCBLEND_INVDSTCOLOR: srcFactor = "(vec3(1.0) - destColor.rgb)"; break;
|
||||
case GE_SRCBLEND_SRCALPHA: srcFactor = "vec3(v.a)"; break;
|
||||
|
@ -888,8 +923,7 @@ void GenerateFragmentShader(char *buffer) {
|
|||
case GE_SRCBLEND_DOUBLEINVDSTALPHA: srcFactor = "vec3(1.0 - destColor.a * 2.0)"; break;
|
||||
case GE_SRCBLEND_FIXA: srcFactor = "u_blendFixA"; break;
|
||||
}
|
||||
switch (funcB)
|
||||
{
|
||||
switch (replaceBlendFuncB) {
|
||||
case GE_DSTBLEND_SRCCOLOR: dstFactor = "v.rgb"; break;
|
||||
case GE_DSTBLEND_INVSRCCOLOR: dstFactor = "(vec3(1.0) - v.rgb)"; break;
|
||||
case GE_DSTBLEND_SRCALPHA: dstFactor = "vec3(v.a)"; break;
|
||||
|
@ -903,8 +937,7 @@ void GenerateFragmentShader(char *buffer) {
|
|||
case GE_DSTBLEND_FIXB: dstFactor = "u_blendFixB"; break;
|
||||
}
|
||||
|
||||
switch (eq)
|
||||
{
|
||||
switch (replaceBlendEq) {
|
||||
case GE_BLENDMODE_MUL_AND_ADD:
|
||||
WRITE(p, " v.rgb = v.rgb * %s + destColor.rgb * %s;\n", srcFactor, dstFactor);
|
||||
break;
|
||||
|
@ -934,7 +967,7 @@ void GenerateFragmentShader(char *buffer) {
|
|||
std::string replacedAlpha = "0.0";
|
||||
char replacedAlphaTemp[64] = "";
|
||||
if (stencilToAlpha != REPLACE_ALPHA_NO) {
|
||||
switch (ReplaceAlphaWithStencilType()) {
|
||||
switch (replaceAlphaWithStencilType) {
|
||||
case STENCIL_VALUE_UNIFORM:
|
||||
replacedAlpha = "u_stencilReplaceValue";
|
||||
break;
|
||||
|
@ -984,7 +1017,8 @@ void GenerateFragmentShader(char *buffer) {
|
|||
break;
|
||||
}
|
||||
|
||||
switch (ReplaceLogicOpType()) {
|
||||
LogicOpReplaceType replaceLogicOpType = (LogicOpReplaceType)id.Bits(BIT_REPLACE_LOGIC_OP_TYPE, 2);
|
||||
switch (replaceLogicOpType) {
|
||||
case LOGICOPTYPE_ONE:
|
||||
WRITE(p, " %s.rgb = vec3(1.0, 1.0, 1.0);\n", fragColor0);
|
||||
break;
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
|
||||
struct ShaderID;
|
||||
|
||||
void ComputeFragmentShaderID(ShaderID *id);
|
||||
void GenerateFragmentShader(char *buffer);
|
||||
void ComputeFragmentShaderID(ShaderID *id, uint32_t vertType);
|
||||
void GenerateFragmentShader(const ShaderID &id, char *buffer);
|
||||
|
||||
enum StencilValueType {
|
||||
STENCIL_VALUE_UNIFORM,
|
||||
|
|
|
@ -826,7 +826,7 @@ Shader *ShaderManager::ApplyVertexShader(int prim, u32 vertType) {
|
|||
|
||||
LinkedShader *ShaderManager::ApplyFragmentShader(Shader *vs, int prim, u32 vertType) {
|
||||
ShaderID FSID;
|
||||
ComputeFragmentShaderID(&FSID);
|
||||
ComputeFragmentShaderID(&FSID, vertType);
|
||||
if (lastVShaderSame_ && FSID == lastFSID_) {
|
||||
lastShader_->UpdateUniforms(vertType);
|
||||
return lastShader_;
|
||||
|
@ -838,7 +838,7 @@ LinkedShader *ShaderManager::ApplyFragmentShader(Shader *vs, int prim, u32 vertT
|
|||
Shader *fs;
|
||||
if (fsIter == fsCache_.end()) {
|
||||
// Fragment shader not in cache. Let's compile it.
|
||||
GenerateFragmentShader(codeBuffer_);
|
||||
GenerateFragmentShader(FSID, codeBuffer_);
|
||||
fs = new Shader(codeBuffer_, GL_FRAGMENT_SHADER, vs->UseHWTransform(), FSID);
|
||||
fsCache_[FSID] = fs;
|
||||
} else {
|
||||
|
|
Loading…
Add table
Reference in a new issue