mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Shader depal: Don't generate a big switch in the shader, generate specialized shaders instead.
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
const char * const vulkan_glsl_preamble_fs =
|
||||
"#extension GL_ARB_separate_shader_objects : enable\n"
|
||||
"#extension GL_ARB_shading_language_420pack : enable\n"
|
||||
"#extension GL_ARB_conservative_depth : enable\n"
|
||||
"#extension GL_ARB_shader_image_load_store : enable\n"
|
||||
"#define splat3(x) vec3(x)\n"
|
||||
"#define DISCARD discard\n"
|
||||
|
||||
@@ -70,6 +70,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
|
||||
bool texture3D = id.Bit(FS_BIT_3D_TEXTURE);
|
||||
bool arrayTexture = id.Bit(FS_BIT_SAMPLE_ARRAY_TEXTURE);
|
||||
bool forceDepthWritesOff = id.Bit(FS_BIT_DEPTH_TEST_NEVER);
|
||||
bool useDiscardStencilBugWorkaround = id.Bit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL) && !forceDepthWritesOff;
|
||||
|
||||
ReplaceAlphaType stencilToAlpha = static_cast<ReplaceAlphaType>(id.Bits(FS_BIT_STENCIL_TO_ALPHA, 2));
|
||||
|
||||
@@ -87,6 +89,10 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
if (gl_extensions.OES_texture_3D && texture3D) {
|
||||
extensions.push_back("#extension GL_OES_texture_3D: enable");
|
||||
}
|
||||
if (useDiscardStencilBugWorkaround) {
|
||||
// The only use of layout (depth_...)
|
||||
extensions.push_back("#extension GL_ARB_conservative_depth : enable\n");
|
||||
}
|
||||
}
|
||||
|
||||
ShaderWriterFlags flags = ShaderWriterFlags::NONE;
|
||||
@@ -129,6 +135,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
}
|
||||
|
||||
ShaderDepalMode shaderDepalMode = (ShaderDepalMode)id.Bits(FS_BIT_SHADER_DEPAL_MODE, 2);
|
||||
GEBufferFormat shaderDepalFmt = (GEBufferFormat)(id.Bits(FS_BIT_SHADER_DEPAL_FORMAT, 3));
|
||||
if (texture3D) {
|
||||
shaderDepalMode = ShaderDepalMode::OFF;
|
||||
}
|
||||
@@ -159,9 +166,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
shading = doFlatShading ? "flat" : "";
|
||||
}
|
||||
|
||||
bool forceDepthWritesOff = id.Bit(FS_BIT_DEPTH_TEST_NEVER);
|
||||
|
||||
bool useDiscardStencilBugWorkaround = id.Bit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL) && !forceDepthWritesOff;
|
||||
|
||||
GEBlendSrcFactor replaceBlendFuncA = (GEBlendSrcFactor)id.Bits(FS_BIT_BLENDFUNC_A, 4);
|
||||
GEBlendDstFactor replaceBlendFuncB = (GEBlendDstFactor)id.Bits(FS_BIT_BLENDFUNC_B, 4);
|
||||
@@ -689,74 +693,77 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
WRITE(p, " } else {\n");
|
||||
WRITE(p, " uv_round = uv;\n");
|
||||
WRITE(p, " }\n");
|
||||
|
||||
p.C(" highp vec4 t = ").SampleTexture2D("tex", "uv_round").C(";\n");
|
||||
p.C(" highp vec4 t1 = ").SampleTexture2DOffset("tex", "uv_round", 1, 0).C(";\n");
|
||||
p.C(" highp vec4 t2 = ").SampleTexture2DOffset("tex", "uv_round", 0, 1).C(";\n");
|
||||
p.C(" highp vec4 t3 = ").SampleTexture2DOffset("tex", "uv_round", 1, 1).C(";\n");
|
||||
|
||||
WRITE(p, " uint depalMask = (u_depal_mask_shift_off_fmt & 0xFFu);\n");
|
||||
WRITE(p, " uint depalShift = (u_depal_mask_shift_off_fmt >> 0x8u) & 0xFFu;\n");
|
||||
WRITE(p, " uint depalOffset = ((u_depal_mask_shift_off_fmt >> 0x10u) & 0xFFu) << 0x4u;\n");
|
||||
WRITE(p, " uint depalFmt = (u_depal_mask_shift_off_fmt >> 0x18u) & 0x3u;\n");
|
||||
WRITE(p, " uvec4 col; uint index0; uint index1; uint index2; uint index3;\n");
|
||||
WRITE(p, " switch (int(depalFmt)) {\n"); // We might want to include fmt in the shader ID if this is a performance issue.
|
||||
WRITE(p, " case 0:\n"); // 565
|
||||
WRITE(p, " col = uvec4(t.rgb * vec3(31.99, 63.99, 31.99), 0);\n");
|
||||
WRITE(p, " index0 = (col.b << 0xBu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " if (bilinear) {\n");
|
||||
WRITE(p, " col = uvec4(t1.rgb * vec3(31.99, 63.99, 31.99), 0);\n");
|
||||
WRITE(p, " index1 = (col.b << 0xBu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t2.rgb * vec3(31.99, 63.99, 31.99), 0);\n");
|
||||
WRITE(p, " index2 = (col.b << 0xBu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t3.rgb * vec3(31.99, 63.99, 31.99), 0);\n");
|
||||
WRITE(p, " index3 = (col.b << 0xBu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " break;\n");
|
||||
WRITE(p, " case 1:\n"); // 5551
|
||||
WRITE(p, " col = uvec4(t.rgba * vec4(31.99, 31.99, 31.99, 1.0));\n");
|
||||
WRITE(p, " index0 = (col.a << 0xFu) | (col.b << 0xAu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " if (bilinear) {\n");
|
||||
WRITE(p, " col = uvec4(t1.rgba * vec4(31.99, 31.99, 31.99, 1.0));\n");
|
||||
WRITE(p, " index1 = (col.a << 0xFu) | (col.b << 0xAu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t2.rgba * vec4(31.99, 31.99, 31.99, 1.0));\n");
|
||||
WRITE(p, " index2 = (col.a << 0xFu) | (col.b << 0xAu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t3.rgba * vec4(31.99, 31.99, 31.99, 1.0));\n");
|
||||
WRITE(p, " index3 = (col.a << 0xFu) | (col.b << 0xAu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " break;\n");
|
||||
WRITE(p, " case 2:\n"); // 4444
|
||||
WRITE(p, " col = uvec4(t.rgba * 15.99);\n");
|
||||
WRITE(p, " index0 = (col.a << 0xCu) | (col.b << 0x8u) | (col.g << 0x4u) | (col.r);\n");
|
||||
WRITE(p, " if (bilinear) {\n");
|
||||
WRITE(p, " col = uvec4(t1.rgba * 15.99);\n");
|
||||
WRITE(p, " index1 = (col.a << 0xCu) | (col.b << 0x8u) | (col.g << 0x4u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t2.rgba * 15.99);\n");
|
||||
WRITE(p, " index2 = (col.a << 0xCu) | (col.b << 0x8u) | (col.g << 0x4u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t3.rgba * 15.99);\n");
|
||||
WRITE(p, " index3 = (col.a << 0xCu) | (col.b << 0x8u) | (col.g << 0x4u) | (col.r);\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " break;\n");
|
||||
WRITE(p, " case 3:\n"); // 8888
|
||||
WRITE(p, " col = uvec4(t.rgba * 255.99);\n");
|
||||
WRITE(p, " index0 = (col.a << 0x18u) | (col.b << 0x10u) | (col.g << 0x8u) | (col.r);\n");
|
||||
WRITE(p, " if (bilinear) {\n");
|
||||
WRITE(p, " col = uvec4(t1.rgba * 255.99);\n");
|
||||
WRITE(p, " index1 = (col.a << 0x18u) | (col.b << 0x10u) | (col.g << 0x8u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t2.rgba * 255.99);\n");
|
||||
WRITE(p, " index2 = (col.a << 0x18u) | (col.b << 0x10u) | (col.g << 0x8u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t3.rgba * 255.99);\n");
|
||||
WRITE(p, " index3 = (col.a << 0x18u) | (col.b << 0x10u) | (col.g << 0x8u) | (col.r);\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " break;\n");
|
||||
WRITE(p, " };\n");
|
||||
|
||||
switch (shaderDepalFmt) {
|
||||
case GE_FORMAT_565:
|
||||
WRITE(p, " col = uvec4(t.rgb * vec3(31.99, 63.99, 31.99), 0);\n");
|
||||
WRITE(p, " index0 = (col.b << 0xBu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " if (bilinear) {\n");
|
||||
WRITE(p, " col = uvec4(t1.rgb * vec3(31.99, 63.99, 31.99), 0);\n");
|
||||
WRITE(p, " index1 = (col.b << 0xBu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t2.rgb * vec3(31.99, 63.99, 31.99), 0);\n");
|
||||
WRITE(p, " index2 = (col.b << 0xBu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t3.rgb * vec3(31.99, 63.99, 31.99), 0);\n");
|
||||
WRITE(p, " index3 = (col.b << 0xBu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " }\n");
|
||||
break;
|
||||
case GE_FORMAT_5551:
|
||||
WRITE(p, " col = uvec4(t.rgba * vec4(31.99, 31.99, 31.99, 1.0));\n");
|
||||
WRITE(p, " index0 = (col.a << 0xFu) | (col.b << 0xAu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " if (bilinear) {\n");
|
||||
WRITE(p, " col = uvec4(t1.rgba * vec4(31.99, 31.99, 31.99, 1.0));\n");
|
||||
WRITE(p, " index1 = (col.a << 0xFu) | (col.b << 0xAu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t2.rgba * vec4(31.99, 31.99, 31.99, 1.0));\n");
|
||||
WRITE(p, " index2 = (col.a << 0xFu) | (col.b << 0xAu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t3.rgba * vec4(31.99, 31.99, 31.99, 1.0));\n");
|
||||
WRITE(p, " index3 = (col.a << 0xFu) | (col.b << 0xAu) | (col.g << 0x5u) | (col.r);\n");
|
||||
WRITE(p, " }\n");
|
||||
break;
|
||||
case GE_FORMAT_4444:
|
||||
WRITE(p, " col = uvec4(t.rgba * 15.99);\n");
|
||||
WRITE(p, " index0 = (col.a << 0xCu) | (col.b << 0x8u) | (col.g << 0x4u) | (col.r);\n");
|
||||
WRITE(p, " if (bilinear) {\n");
|
||||
WRITE(p, " col = uvec4(t1.rgba * 15.99);\n");
|
||||
WRITE(p, " index1 = (col.a << 0xCu) | (col.b << 0x8u) | (col.g << 0x4u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t2.rgba * 15.99);\n");
|
||||
WRITE(p, " index2 = (col.a << 0xCu) | (col.b << 0x8u) | (col.g << 0x4u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t3.rgba * 15.99);\n");
|
||||
WRITE(p, " index3 = (col.a << 0xCu) | (col.b << 0x8u) | (col.g << 0x4u) | (col.r);\n");
|
||||
WRITE(p, " }\n");
|
||||
break;
|
||||
case GE_FORMAT_8888:
|
||||
WRITE(p, " col = uvec4(t.rgba * 255.99);\n");
|
||||
WRITE(p, " index0 = (col.a << 0x18u) | (col.b << 0x10u) | (col.g << 0x8u) | (col.r);\n");
|
||||
WRITE(p, " if (bilinear) {\n");
|
||||
WRITE(p, " col = uvec4(t1.rgba * 255.99);\n");
|
||||
WRITE(p, " index1 = (col.a << 0x18u) | (col.b << 0x10u) | (col.g << 0x8u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t2.rgba * 255.99);\n");
|
||||
WRITE(p, " index2 = (col.a << 0x18u) | (col.b << 0x10u) | (col.g << 0x8u) | (col.r);\n");
|
||||
WRITE(p, " col = uvec4(t3.rgba * 255.99);\n");
|
||||
WRITE(p, " index3 = (col.a << 0x18u) | (col.b << 0x10u) | (col.g << 0x8u) | (col.r);\n");
|
||||
WRITE(p, " }\n");
|
||||
break;
|
||||
}
|
||||
WRITE(p, " index0 = ((index0 >> depalShift) & depalMask) | depalOffset;\n");
|
||||
p.C(" t = ").LoadTexture2D("pal", "ivec2(index0, 0)", 0).C(";\n");
|
||||
WRITE(p, " if (bilinear && !(index0 == index1 && index1 == index2 && index2 == index3)) {\n");
|
||||
WRITE(p, " index1 = ((index1 >> depalShift) & depalMask) | depalOffset;\n");
|
||||
WRITE(p, " index2 = ((index2 >> depalShift) & depalMask) | depalOffset;\n");
|
||||
WRITE(p, " index3 = ((index3 >> depalShift) & depalMask) | depalOffset;\n");
|
||||
p.C(" t1 = ").LoadTexture2D("pal", "ivec2(index1, 0)", 0).C(";\n");
|
||||
p.C(" t2 = ").LoadTexture2D("pal", "ivec2(index2, 0)", 0).C(";\n");
|
||||
p.C(" t3 = ").LoadTexture2D("pal", "ivec2(index3, 0)", 0).C(";\n");
|
||||
p.C(" t1 = ").LoadTexture2D("pal", "ivec2(index1, 0)", 0).C(";\n");
|
||||
p.C(" t2 = ").LoadTexture2D("pal", "ivec2(index2, 0)", 0).C(";\n");
|
||||
p.C(" t3 = ").LoadTexture2D("pal", "ivec2(index3, 0)", 0).C(";\n");
|
||||
WRITE(p, " t = mix(t, t1, fraction.x);\n");
|
||||
WRITE(p, " t2 = mix(t2, t3, fraction.x);\n");
|
||||
WRITE(p, " t = mix(t, t2, fraction.y);\n");
|
||||
|
||||
+19
-6
@@ -202,12 +202,6 @@ std::string FragmentShaderDesc(const FShaderID &id) {
|
||||
if (id.Bit(FS_BIT_FLATSHADE)) desc << "Flat ";
|
||||
if (id.Bit(FS_BIT_BGRA_TEXTURE)) desc << "BGRA ";
|
||||
if (id.Bit(FS_BIT_DEPTH_TEST_NEVER)) desc << "DepthNever ";
|
||||
switch ((ShaderDepalMode)id.Bits(FS_BIT_SHADER_DEPAL_MODE, 2)) {
|
||||
case ShaderDepalMode::OFF: break;
|
||||
case ShaderDepalMode::NORMAL: desc << "Depal "; break;
|
||||
case ShaderDepalMode::SMOOTHED: desc << "SmoothDepal "; break;
|
||||
case ShaderDepalMode::CLUT8_8888: desc << "CLUT8From8888Depal"; break;
|
||||
}
|
||||
if (id.Bit(FS_BIT_COLOR_WRITEMASK)) desc << "WriteMask ";
|
||||
if (id.Bit(FS_BIT_SHADER_TEX_CLAMP)) {
|
||||
desc << "TClamp";
|
||||
@@ -275,6 +269,20 @@ std::string FragmentShaderDesc(const FShaderID &id) {
|
||||
if (id.Bit(FS_BIT_USE_FRAMEBUFFER_FETCH)) desc << "(fetch)";
|
||||
if (id.Bit(FS_BIT_MINMAX_DISCARD)) desc << "FragMinMaxDiscard ";
|
||||
if (id.Bit(FS_BIT_DEPTH_CLAMP)) desc << "FragDepthClamp ";
|
||||
|
||||
const ShaderDepalMode depalMode = (ShaderDepalMode)id.Bits(FS_BIT_SHADER_DEPAL_MODE, 2);
|
||||
switch (depalMode) {
|
||||
case ShaderDepalMode::OFF: break;
|
||||
case ShaderDepalMode::NORMAL: desc << "Depal(";
|
||||
{
|
||||
const GEBufferFormat shaderDepalFormat = (GEBufferFormat)id.Bits(FS_BIT_SHADER_DEPAL_FORMAT, 3);
|
||||
desc << GeBufferFormatToString(shaderDepalFormat) << ") ";
|
||||
break;
|
||||
}
|
||||
case ShaderDepalMode::SMOOTHED: desc << "SmoothDepal "; break;
|
||||
case ShaderDepalMode::CLUT8_8888: desc << "CLUT8From8888Depal"; break;
|
||||
}
|
||||
|
||||
return desc.str();
|
||||
}
|
||||
|
||||
@@ -324,6 +332,10 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip
|
||||
bool enableTexAlpha = gstate.isTextureAlphaUsed();
|
||||
|
||||
ShaderDepalMode shaderDepalMode = gstate_c.shaderDepalMode;
|
||||
GEBufferFormat shaderDepalFormat = {};
|
||||
if (shaderDepalMode == ShaderDepalMode::NORMAL) {
|
||||
shaderDepalFormat = gstate_c.depalTextureFormat;
|
||||
}
|
||||
|
||||
bool colorWriteMask = pipelineState.maskState.applyFramebufferRead;
|
||||
ReplaceBlendType replaceBlend = pipelineState.blendState.replaceBlend;
|
||||
@@ -343,6 +355,7 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip
|
||||
}
|
||||
id.SetBit(FS_BIT_BGRA_TEXTURE, gstate_c.bgraTexture);
|
||||
id.SetBits(FS_BIT_SHADER_DEPAL_MODE, 2, (int)shaderDepalMode);
|
||||
id.SetBits(FS_BIT_SHADER_DEPAL_FORMAT, 3, (int)shaderDepalFormat);
|
||||
id.SetBit(FS_BIT_3D_TEXTURE, gstate_c.curTextureIs3D);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ enum FShaderBit : uint8_t {
|
||||
FS_BIT_SHADER_TEX_CLAMP = 5,
|
||||
FS_BIT_CLAMP_S = 6,
|
||||
FS_BIT_CLAMP_T = 7,
|
||||
// Free bits: 8-11
|
||||
FS_BIT_SHADER_DEPAL_FORMAT = 8, // 3 bits (GEBufferFormat), connected to FS_BIT_SHADER_DEPAL_MODE
|
||||
FS_BIT_ALPHA_TEST = 12,
|
||||
FS_BIT_ALPHA_TEST_FUNC = 13, // 3 bits
|
||||
FS_BIT_ALPHA_AGAINST_ZERO = 16,
|
||||
|
||||
@@ -191,7 +191,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool useBuffe
|
||||
int indexMask = gstate.getClutIndexMask();
|
||||
int indexShift = gstate.getClutIndexShift();
|
||||
int indexOffset = gstate.getClutIndexStartPos() >> 4;
|
||||
int format = gstate_c.depalFramebufferFormat;
|
||||
int format = gstate_c.depalTextureFormat;
|
||||
uint32_t val = BytesToUint32(indexMask, indexShift, indexOffset, format);
|
||||
// Poke in a bilinear filter flag in the top bit.
|
||||
if (gstate.isMagnifyFilteringEnabled())
|
||||
|
||||
@@ -2319,9 +2319,9 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
|
||||
mode = ShaderDepalMode::SMOOTHED;
|
||||
}
|
||||
|
||||
gstate_c.Dirty(DIRTY_DEPAL);
|
||||
gstate_c.Dirty(DIRTY_DEPAL | DIRTY_FRAGMENTSHADER_STATE);
|
||||
gstate_c.SetUseShaderDepal(mode);
|
||||
gstate_c.depalFramebufferFormat = framebuffer->fb_format;
|
||||
gstate_c.depalTextureFormat = framebuffer->fb_format;
|
||||
|
||||
const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
|
||||
const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor;
|
||||
|
||||
@@ -377,7 +377,7 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, const ShaderLanguageDesc
|
||||
int indexMask = gstate.getClutIndexMask();
|
||||
int indexShift = gstate.getClutIndexShift();
|
||||
int indexOffset = gstate.getClutIndexStartPos() >> 4;
|
||||
int format = gstate_c.depalFramebufferFormat;
|
||||
int format = gstate_c.depalTextureFormat;
|
||||
uint32_t val = BytesToUint32(indexMask, indexShift, indexOffset, format);
|
||||
// Poke in a bilinear filter flag in the top bit.
|
||||
val |= gstate.isMagnifyFilteringEnabled() << 31;
|
||||
|
||||
+1
-1
@@ -700,7 +700,7 @@ public:
|
||||
int spline_num_points_u;
|
||||
|
||||
ShaderDepalMode shaderDepalMode;
|
||||
GEBufferFormat depalFramebufferFormat;
|
||||
GEBufferFormat depalTextureFormat;
|
||||
|
||||
u32 getRelativeAddress(u32 data) const {
|
||||
u32 baseExtended = ((gstate.base & 0x000F0000) << 8) | data;
|
||||
|
||||
Reference in New Issue
Block a user