mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-07-10 01:24:41 -06:00
Latte: Omit FragCoordScale uniform in shader if unused
We insert padding when needed to keep alignment intact for backwards compatibility with gfx pack shaders.
This commit is contained in:
parent
45eedb4cd3
commit
c7ee701edd
@ -562,7 +562,7 @@ namespace LatteDecompiler
|
|||||||
bool alphaTestEnable = decompilerContext->contextRegistersNew->SX_ALPHA_TEST_CONTROL.get_ALPHA_TEST_ENABLE();
|
bool alphaTestEnable = decompilerContext->contextRegistersNew->SX_ALPHA_TEST_CONTROL.get_ALPHA_TEST_ENABLE();
|
||||||
if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel && alphaTestEnable != 0)
|
if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel && alphaTestEnable != 0)
|
||||||
decompilerContext->hasUniformVarBlock = true; // uf_alphaTestRef
|
decompilerContext->hasUniformVarBlock = true; // uf_alphaTestRef
|
||||||
if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel)
|
if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel && decompilerContext->analyzer.hasFragCoordAccess)
|
||||||
decompilerContext->hasUniformVarBlock = true; // uf_fragCoordScale
|
decompilerContext->hasUniformVarBlock = true; // uf_fragCoordScale
|
||||||
if (decompilerContext->shaderType == LatteConst::ShaderType::Vertex && decompilerContext->analyzer.outputPointSize && decompilerContext->analyzer.writesPointSize == false)
|
if (decompilerContext->shaderType == LatteConst::ShaderType::Vertex && decompilerContext->analyzer.outputPointSize && decompilerContext->analyzer.writesPointSize == false)
|
||||||
decompilerContext->hasUniformVarBlock = true; // uf_pointSize
|
decompilerContext->hasUniformVarBlock = true; // uf_pointSize
|
||||||
@ -607,6 +607,11 @@ namespace LatteDecompiler
|
|||||||
decompilerContext->output->resourceMappingMTL.uniformVarsBufferBindingPoint = decompilerContext->currentBufferBindingPointMTL;
|
decompilerContext->output->resourceMappingMTL.uniformVarsBufferBindingPoint = decompilerContext->currentBufferBindingPointMTL;
|
||||||
decompilerContext->currentBufferBindingPointMTL++;
|
decompilerContext->currentBufferBindingPointMTL++;
|
||||||
}
|
}
|
||||||
|
else if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel) // compatibility workaround to keep binding indices the same with existing gfx pack shader replacements, we now only emit uf_fragCoord when needed and it can lead to hasUniformVarBlock being false
|
||||||
|
{
|
||||||
|
decompilerContext->currentBindingPointVK++;
|
||||||
|
decompilerContext->currentBufferBindingPointMTL++;
|
||||||
|
}
|
||||||
// assign binding points to uniform buffers
|
// assign binding points to uniform buffers
|
||||||
if (decompilerContext->shader->uniformMode == LATTE_DECOMPILER_UNIFORM_MODE_FULL_CBANK)
|
if (decompilerContext->shader->uniformMode == LATTE_DECOMPILER_UNIFORM_MODE_FULL_CBANK)
|
||||||
{
|
{
|
||||||
@ -1006,6 +1011,23 @@ void LatteDecompiler_analyze(LatteDecompilerShaderContext* shaderContext, LatteD
|
|||||||
shaderContext->analyzer.gprUseMask[i / 8] |= (1 << (i % 8));
|
shaderContext->analyzer.gprUseMask[i / 8] |= (1 << (i % 8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// check if shader accesses frag coord
|
||||||
|
if (shader->shaderType == LatteConst::ShaderType::Pixel)
|
||||||
|
{
|
||||||
|
LatteShaderPSInputTable* psInputTable = LatteSHRC_GetPSInputTable();
|
||||||
|
for (sint32 i = 0; i < psInputTable->count; i++)
|
||||||
|
{
|
||||||
|
sint32 gprIndex = i;
|
||||||
|
if ((shaderContext->analyzer.gprUseMask[gprIndex / 8] & (1 << (gprIndex % 8))) == 0 && shaderContext->analyzer.usesRelativeGPRRead == false)
|
||||||
|
continue;
|
||||||
|
uint32 psInputSemanticId = psInputTable->import[i].semanticId;
|
||||||
|
if (psInputSemanticId == LATTE_ANALYZER_IMPORT_INDEX_SPIPOSITION)
|
||||||
|
{
|
||||||
|
shaderContext->analyzer.hasFragCoordAccess = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// analyze CF stack
|
// analyze CF stack
|
||||||
sint32 cfCurrentStackDepth = 0;
|
sint32 cfCurrentStackDepth = 0;
|
||||||
sint32 cfCurrentMaxStackDepth = 0;
|
sint32 cfCurrentMaxStackDepth = 0;
|
||||||
|
|||||||
@ -83,9 +83,15 @@ namespace LatteDecompiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// define uf_fragCoordScale which holds the xy scale for render target resolution vs effective resolution
|
// define uf_fragCoordScale which holds the xy scale for render target resolution vs effective resolution
|
||||||
|
bool compatNeedFragCoordScalePadding = false; // 2026-06-15 - uf_fragCoordScale is only emitted when accessed now. To keep compatible with old shader replacements we insert padding if its not the last element
|
||||||
if (shader->shaderType == LatteConst::ShaderType::Pixel)
|
if (shader->shaderType == LatteConst::ShaderType::Pixel)
|
||||||
{
|
{
|
||||||
if (rendererType == RendererAPI::OpenGL)
|
if (!decompilerContext->analyzer.hasFragCoordAccess)
|
||||||
|
{
|
||||||
|
// omit uf_fragCoordScale
|
||||||
|
compatNeedFragCoordScalePadding = true;
|
||||||
|
}
|
||||||
|
else if (rendererType == RendererAPI::OpenGL)
|
||||||
{
|
{
|
||||||
uniformCurrentOffset = (uniformCurrentOffset + 7)&~7;
|
uniformCurrentOffset = (uniformCurrentOffset + 7)&~7;
|
||||||
shaderSrc->add("uniform vec2 uf_fragCoordScale;" _CRLF);
|
shaderSrc->add("uniform vec2 uf_fragCoordScale;" _CRLF);
|
||||||
@ -106,6 +112,20 @@ namespace LatteDecompiler
|
|||||||
{
|
{
|
||||||
if (decompilerContext->analyzer.texUnitUsesTexelCoordinates.test(t) == false)
|
if (decompilerContext->analyzer.texUnitUsesTexelCoordinates.test(t) == false)
|
||||||
continue;
|
continue;
|
||||||
|
if (compatNeedFragCoordScalePadding)
|
||||||
|
{
|
||||||
|
if (rendererType == RendererAPI::OpenGL)
|
||||||
|
{
|
||||||
|
uniformCurrentOffset = (uniformCurrentOffset + 7)&~7;
|
||||||
|
shaderSrc->add("uniform vec2 uf_fragCoordScaleCompatPadding;" _CRLF); uniformCurrentOffset += 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uniformCurrentOffset = (uniformCurrentOffset + 15)&~15;
|
||||||
|
shaderSrc->add("uniform vec4 uf_fragCoordScaleCompatPadding;" _CRLF); uniformCurrentOffset += 16;
|
||||||
|
}
|
||||||
|
compatNeedFragCoordScalePadding = false;
|
||||||
|
}
|
||||||
uniformCurrentOffset = (uniformCurrentOffset + 7) & ~7;
|
uniformCurrentOffset = (uniformCurrentOffset + 7) & ~7;
|
||||||
shaderSrc->addFmt("uniform vec2 uf_tex{}Scale;" _CRLF, t);
|
shaderSrc->addFmt("uniform vec2 uf_tex{}Scale;" _CRLF, t);
|
||||||
uniformOffsets.offset_texScale[t] = uniformCurrentOffset;
|
uniformOffsets.offset_texScale[t] = uniformCurrentOffset;
|
||||||
@ -116,6 +136,7 @@ namespace LatteDecompiler
|
|||||||
(shader->shaderType == LatteConst::ShaderType::Vertex && decompilerContext->options->usesGeometryShader == false) ||
|
(shader->shaderType == LatteConst::ShaderType::Vertex && decompilerContext->options->usesGeometryShader == false) ||
|
||||||
(shader->shaderType == LatteConst::ShaderType::Geometry) )
|
(shader->shaderType == LatteConst::ShaderType::Geometry) )
|
||||||
{
|
{
|
||||||
|
// note - we dont need to handle compatNeedFragCoordScalePadding here because it's pixel shader only
|
||||||
shaderSrc->add("uniform int uf_verticesPerInstance;" _CRLF);
|
shaderSrc->add("uniform int uf_verticesPerInstance;" _CRLF);
|
||||||
uniformOffsets.offset_verticesPerInstance = uniformCurrentOffset;
|
uniformOffsets.offset_verticesPerInstance = uniformCurrentOffset;
|
||||||
uniformCurrentOffset += 4;
|
uniformCurrentOffset += 4;
|
||||||
@ -280,7 +301,7 @@ namespace LatteDecompiler
|
|||||||
src->add("#define V2G_LAYOUT layout(location = 0)" _CRLF);
|
src->add("#define V2G_LAYOUT layout(location = 0)" _CRLF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel)
|
else if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel && decompilerContext->analyzer.hasFragCoordAccess)
|
||||||
{
|
{
|
||||||
src->add("#define GET_FRAGCOORD() vec4(gl_FragCoord.xy*uf_fragCoordScale.xy,gl_FragCoord.z, 1.0/gl_FragCoord.w)" _CRLF);
|
src->add("#define GET_FRAGCOORD() vec4(gl_FragCoord.xy*uf_fragCoordScale.xy,gl_FragCoord.z, 1.0/gl_FragCoord.w)" _CRLF);
|
||||||
}
|
}
|
||||||
@ -305,7 +326,7 @@ namespace LatteDecompiler
|
|||||||
if (decompilerContext->options->usesGeometryShader)
|
if (decompilerContext->options->usesGeometryShader)
|
||||||
src->add("#define V2G_LAYOUT" _CRLF);
|
src->add("#define V2G_LAYOUT" _CRLF);
|
||||||
}
|
}
|
||||||
else if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel)
|
else if (decompilerContext->shaderType == LatteConst::ShaderType::Pixel && decompilerContext->analyzer.hasFragCoordAccess)
|
||||||
{
|
{
|
||||||
src->add("#define GET_FRAGCOORD() vec4(gl_FragCoord.xy*uf_fragCoordScale,gl_FragCoord.zw)" _CRLF);
|
src->add("#define GET_FRAGCOORD() vec4(gl_FragCoord.xy*uf_fragCoordScale,gl_FragCoord.zw)" _CRLF);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,18 +68,34 @@ namespace LatteDecompiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// define fragCoordScale which holds the xy scale for render target resolution vs effective resolution
|
// define fragCoordScale which holds the xy scale for render target resolution vs effective resolution
|
||||||
|
bool compatNeedFragCoordScalePadding = false; // 2026-06-15 - fragCoordScale is only emitted when accessed now. To keep compatible with old shader replacements we insert padding if its not the last element
|
||||||
if (shader->shaderType == LatteConst::ShaderType::Pixel)
|
if (shader->shaderType == LatteConst::ShaderType::Pixel)
|
||||||
{
|
{
|
||||||
uniformCurrentOffset = (uniformCurrentOffset + 7)&~7;
|
if (!decompilerContext->analyzer.hasFragCoordAccess)
|
||||||
src->add("float2 fragCoordScale;" _CRLF);
|
{
|
||||||
uniformOffsets.offset_fragCoordScale = uniformCurrentOffset;
|
// omit fragCoordScale
|
||||||
uniformCurrentOffset += 8;
|
compatNeedFragCoordScalePadding = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uniformCurrentOffset = (uniformCurrentOffset + 7)&~7;
|
||||||
|
src->add("float2 fragCoordScale;" _CRLF);
|
||||||
|
uniformOffsets.offset_fragCoordScale = uniformCurrentOffset;
|
||||||
|
uniformCurrentOffset += 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// provide scale factor for every texture that is accessed via texel coordinates (texelFetch)
|
// provide scale factor for every texture that is accessed via texel coordinates (texelFetch)
|
||||||
for (sint32 t = 0; t < LATTE_NUM_MAX_TEX_UNITS; t++)
|
for (sint32 t = 0; t < LATTE_NUM_MAX_TEX_UNITS; t++)
|
||||||
{
|
{
|
||||||
if (decompilerContext->analyzer.texUnitUsesTexelCoordinates.test(t) == false)
|
if (decompilerContext->analyzer.texUnitUsesTexelCoordinates.test(t) == false)
|
||||||
continue;
|
continue;
|
||||||
|
if (compatNeedFragCoordScalePadding)
|
||||||
|
{
|
||||||
|
uniformCurrentOffset = (uniformCurrentOffset + 7)&~7;
|
||||||
|
src->add("float2 fragCoordScaleCompatPadding;" _CRLF);
|
||||||
|
uniformCurrentOffset += 8;
|
||||||
|
compatNeedFragCoordScalePadding = false;
|
||||||
|
}
|
||||||
uniformCurrentOffset = (uniformCurrentOffset + 7) & ~7;
|
uniformCurrentOffset = (uniformCurrentOffset + 7) & ~7;
|
||||||
src->addFmt("float2 tex{}Scale;" _CRLF, t);
|
src->addFmt("float2 tex{}Scale;" _CRLF, t);
|
||||||
uniformOffsets.offset_texScale[t] = uniformCurrentOffset;
|
uniformOffsets.offset_texScale[t] = uniformCurrentOffset;
|
||||||
@ -248,7 +264,8 @@ namespace LatteDecompiler
|
|||||||
{
|
{
|
||||||
auto* src = shaderContext->shaderSource;
|
auto* src = shaderContext->shaderSource;
|
||||||
|
|
||||||
src->add("#define GET_FRAGCOORD() float4(in.position.xy * supportBuffer.fragCoordScale.xy, in.position.z, 1.0 / in.position.w)" _CRLF);
|
if (shaderContext->analyzer.hasFragCoordAccess)
|
||||||
|
src->add("#define GET_FRAGCOORD() float4(in.position.xy * supportBuffer.fragCoordScale.xy, in.position.z, 1.0 / in.position.w)" _CRLF);
|
||||||
|
|
||||||
src->add("struct FragmentIn {" _CRLF);
|
src->add("struct FragmentIn {" _CRLF);
|
||||||
src->add("float4 position [[position]];" _CRLF);
|
src->add("float4 position [[position]];" _CRLF);
|
||||||
|
|||||||
@ -237,6 +237,7 @@ struct LatteDecompilerShaderContext
|
|||||||
uint8 gprUseMask[(LATTE_NUM_GPR + 7) / 8]; // 1 bit per GPR, set if GPR is read/written anywhere in the program (ignores GPR accesses with relative index)
|
uint8 gprUseMask[(LATTE_NUM_GPR + 7) / 8]; // 1 bit per GPR, set if GPR is read/written anywhere in the program (ignores GPR accesses with relative index)
|
||||||
bool hasStreamoutWrite; // stream-out CF instructions are used
|
bool hasStreamoutWrite; // stream-out CF instructions are used
|
||||||
bool hasRedcCUBE; // has cube reduction instruction
|
bool hasRedcCUBE; // has cube reduction instruction
|
||||||
|
bool hasFragCoordAccess{false}; // accesses gl_FragCoord
|
||||||
bool modifiesPixelActiveState; // set if the active mask is changed anywhere in the shader (If false, we can skip active mask checks)
|
bool modifiesPixelActiveState; // set if the active mask is changed anywhere in the shader (If false, we can skip active mask checks)
|
||||||
bool usesIntegerValues; // set if the shader uses any kind of integer instruction or integer-based GPR/AR access
|
bool usesIntegerValues; // set if the shader uses any kind of integer instruction or integer-based GPR/AR access
|
||||||
sint32 activeStackMaxDepth; // maximum depth of pixel state stack
|
sint32 activeStackMaxDepth; // maximum depth of pixel state stack
|
||||||
|
|||||||
@ -19,6 +19,8 @@ uint32 RendererShader::GeneratePrecompiledCacheId()
|
|||||||
// settings that can influence shaders
|
// settings that can influence shaders
|
||||||
v += (uint32)g_current_game_profile->GetAccurateShaderMul() * 133;
|
v += (uint32)g_current_game_profile->GetAccurateShaderMul() * 133;
|
||||||
|
|
||||||
|
v += 0x820a5277; // change this value for manual invalidation
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user