mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-08 02:23:23 +09:00
[Fix] (ShaderTranspiler, Link, DirectGLES, DirectVulkan): demote tessellation/geometry gl_PointSize to an ordinary varying where the device cannot host the built-in - the value survives for gl_in reads and by-name capture, both backends' declines stay for shapes the pass refuses, and the verdict rides the L1 key
This commit is contained in:
@@ -128,8 +128,15 @@ namespace MobileGL::MG_State::GLState {
|
||||
// with (ProgramLinkTask::BuildSpirvCacheKey reads the same env) or a memo written under
|
||||
// one answer could be handed back under the other.
|
||||
const Bool nativeFloat64 = m_phaseA->in.env != nullptr && m_phaseA->in.env->ConsumesFloat64Natively();
|
||||
// The point-size demotion verdicts, read from the SAME snapshot for the same reason
|
||||
// - and the same bits BuildSpirvCacheKey put in the L1 key, so a memo written under
|
||||
// one answer can never be handed back under the other.
|
||||
const Bool demoteTessellationPointSize =
|
||||
m_phaseA->in.env != nullptr && m_phaseA->in.env->DemotesTessellationPointSize();
|
||||
const Bool demoteGeometryPointSize =
|
||||
m_phaseA->in.env != nullptr && m_phaseA->in.env->DemotesGeometryPointSize();
|
||||
GenerateSpirv(handoff, externalIndex, deferOutputValidationForDirectVulkan, enableSpirvValidation,
|
||||
nativeFloat64);
|
||||
nativeFloat64, demoteTessellationPointSize, demoteGeometryPointSize);
|
||||
// GlslangToSpv was the only consumer of the parsed ASTs; everything after this point
|
||||
// works on the SPIR-V and on the TProgram's own self-contained reflection pool. Drop
|
||||
// them here rather than at the end of the body, which is ~87% of this node's runtime
|
||||
@@ -188,7 +195,9 @@ namespace MobileGL::MG_State::GLState {
|
||||
|
||||
void ProgramSpirvTask::GenerateSpirv(const ProgramLinkTask::SpirvHandoff& handoff, const Uint externalIndex,
|
||||
const Bool deferOutputValidationForDirectVulkan,
|
||||
const Bool enableSpirvValidation, const Bool nativeFloat64) {
|
||||
const Bool enableSpirvValidation, const Bool nativeFloat64,
|
||||
const Bool demoteTessellationPointSize,
|
||||
const Bool demoteGeometryPointSize) {
|
||||
/* As we passed first stage compilation/linking,
|
||||
* we'll assume all the operations here should
|
||||
* pass. We may be able to employ some optimizations
|
||||
@@ -267,6 +276,44 @@ namespace MobileGL::MG_State::GLState {
|
||||
}
|
||||
}
|
||||
artifacts.spirvStatus = allOptimized;
|
||||
|
||||
// The point-size demotion, program-wide and after the sanitize chain, so it works
|
||||
// on the final shared bytes both backends consume and nothing downstream can trim
|
||||
// the carriers it declares. Only the env half of the verdict lives here (and in the
|
||||
// L1 key); whether the program actually declares the capability is probed inside,
|
||||
// so the common case on an affected device - a program that never touches point
|
||||
// size in those stages - pays one module parse per stage and no rewrite.
|
||||
artifacts.pointSizeDemoted = false;
|
||||
if (allOptimized && (demoteTessellationPointSize || demoteGeometryPointSize)) {
|
||||
Bool captureRequestsPointSize = false;
|
||||
for (const auto& varying : handoff.reflection.xfbVaryings) {
|
||||
if (varying.name == "gl_PointSize") {
|
||||
captureRequestsPointSize = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ShaderCompiler::PointSizeDemotionOutcome outcome;
|
||||
if (!ShaderCompiler::DemoteTessellationGeometryPointSizeForProgram(
|
||||
artifacts.generatedSpirv, handoff.shaderTypes, demoteTessellationPointSize,
|
||||
demoteGeometryPointSize, captureRequestsPointSize, outcome,
|
||||
!deferOutputValidationForDirectVulkan, enableSpirvValidation)) {
|
||||
// Optimizer failure: modules untouched, so the capability is still declared
|
||||
// and the backends' existing refusals stay in charge - honest, just slower.
|
||||
DeferLog(std::format("ProgramObject {}: point-size demotion failed in the optimizer; the "
|
||||
"program keeps its built-in and the device's declines apply",
|
||||
externalIndex));
|
||||
} else if (outcome.demoted) {
|
||||
artifacts.pointSizeDemoted = true;
|
||||
DeferLog(std::format("ProgramObject {}: gl_PointSize demoted to an ordinary varying across "
|
||||
"the tessellation/geometry chain (value preserved for capture and "
|
||||
"gl_in reads; rasterized size falls back to 1.0)",
|
||||
externalIndex));
|
||||
} else if (!outcome.declineDetail.empty()) {
|
||||
DeferLog(std::format("ProgramObject {}: point-size demotion declined ({}); the program "
|
||||
"keeps its built-in and the device's declines apply",
|
||||
externalIndex, outcome.declineDetail));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProgramSpirvTask::BuildGlobalUboRouting(const ProgramLinkTask::SpirvHandoff& handoff,
|
||||
|
||||
Reference in New Issue
Block a user