[Fix]: fix Chocapic V6 Lite

- prune unused SPIR-V interface variables before GLES transpilation

- remap shader varyings through glslang IO resolver bindings

- initialize opaque uniforms from explicit sampler bindings only

- avoid side effects in texture binding assertions

- register Chocapic V6 Lite retrace fixture
This commit is contained in:
2026-06-19 18:42:32 +08:00
parent 7d101182cd
commit 19e4ba386d
11 changed files with 231 additions and 39 deletions
@@ -197,7 +197,8 @@ namespace MobileGL {
if (program->getIntermediate((EShLanguage)stage) == nullptr) continue;
resolver =
MakeUnique<TMglGlslIoResolver>(*program, (EShLanguage)stage, attrib.explicitVertexInLocations,
attrib.explicitFragmentOutLocations);
attrib.explicitFragmentOutLocations,
attrib.explicitOpaqueUniformBindings);
break;
}
auto ioMapper = UniquePtr<glslang::TIoMapper>(glslang::GetGlslIoMapper());
@@ -235,6 +236,8 @@ namespace MobileGL {
Optimizer optimizer(SPV_ENV_VULKAN_1_1);
optimizer.RegisterPass(CreateAggressiveDCEPass(false));
optimizer.RegisterPass(CreateRemoveUnusedInterfaceVariablesPass());
optimizer.RegisterPass(FlattenInterfaceStructPass::CreateFlattenInterfaceStructPass());
optimizer.RegisterPass(EliminateFloatEqualsZeroPass::CreateEliminateFloatEqualsZeroPass());
@@ -31,6 +31,7 @@ namespace MobileGL {
Vector<SharedPtr<glslang::TShader>> shaders;
UnorderedMap<String, Uint> explicitVertexInLocations;
UnorderedMap<String, Uint> explicitFragmentOutLocations;
UnorderedMap<String, Uint>* explicitOpaqueUniformBindings = nullptr;
};
struct ProgramBinaryAttrib {
@@ -13,6 +13,53 @@
#include "TMglGlslIoResolver.h"
namespace MobileGL {
bool TMglGlslIoResolver::ShouldAssignPlainUniformLocation(const glslang::TType& type) const {
if (!doAutoLocationMapping()) {
return false;
}
if (type.getQualifier().hasLocation()) {
return false;
}
if (type.isBuiltIn() || type.getBasicType() == glslang::EbtBlock || type.isAtomic() || type.isSpirvType() ||
(type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) {
return false;
}
if (type.isStruct()) {
if (type.getStruct()->size() < 1) {
return false;
}
if ((*type.getStruct())[0].type->isBuiltIn()) {
return false;
}
}
return true;
}
void TMglGlslIoResolver::EnsurePlainUniformLocationsAssigned() {
if (m_plainUniformLocationsAssigned) {
return;
}
m_plainUniformLocationsAssigned = true;
const int resourceKey = buildStorageKey(EShLangCount, glslang::EvqUniform);
auto& slotMap = storageSlotMap[resourceKey];
for (const auto& [name, size] : m_plainUniformLocationSizeByName) {
const auto existingLocation = slotMap.find(name);
if (existingLocation != slotMap.end()) {
m_plainUniformLocationByName[name] = existingLocation->second;
continue;
}
const int location = getFreeSlot(resourceKey, 0, size);
slotMap[name] = location;
m_plainUniformLocationByName[name] = location;
}
}
void TMglGlslIoResolver::reserverStorageSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) {
const glslang::TType& type = ent.symbol->getType();
const glslang::TString& name = ent.symbol->getAccessName();
@@ -30,6 +77,43 @@ namespace MobileGL {
writableType.getQualifier().layoutLocation = it->second;
}
}
if (ShouldAssignPlainUniformLocation(type)) {
const int size = glslang::TIntermediate::computeTypeUniformLocationSize(type);
auto& recordedSize = m_plainUniformLocationSizeByName[name];
recordedSize = std::max(recordedSize, size);
}
TDefaultGlslIoResolver::reserverStorageSlot(ent, infoSink);
}
} // namespace MobileGL
void TMglGlslIoResolver::reserverResourceSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) {
const glslang::TType& type = ent.symbol->getType();
if (m_explicitOpaqueUniformBindings != nullptr && type.getBasicType() == glslang::EbtSampler &&
type.getQualifier().hasBinding()) {
const glslang::TString& name = ent.symbol->getAccessName();
(*m_explicitOpaqueUniformBindings)[name.c_str()] = type.getQualifier().layoutBinding;
}
TDefaultGlslIoResolver::reserverResourceSlot(ent, infoSink);
}
int TMglGlslIoResolver::resolveUniformLocation(EShLanguage stage, glslang::TVarEntryInfo& ent) {
const glslang::TType& type = ent.symbol->getType();
if (type.getQualifier().hasLocation()) {
return TDefaultGlslIoResolver::resolveUniformLocation(stage, ent);
}
if (!ShouldAssignPlainUniformLocation(type)) {
return TDefaultGlslIoResolver::resolveUniformLocation(stage, ent);
}
EnsurePlainUniformLocationsAssigned();
const glslang::TString& name = ent.symbol->getAccessName();
const auto location = m_plainUniformLocationByName.find(name);
if (location == m_plainUniformLocationByName.end()) {
return ent.newLocation = -1;
}
return ent.newLocation = location->second;
}
} // namespace MobileGL
@@ -26,15 +26,26 @@ namespace MobileGL {
public:
using ExplicitVarSlotMap = UnorderedMap<String, Uint>;
TMglGlslIoResolver(const glslang::TIntermediate& intermediate, const ExplicitVarSlotMap& vertexIns,
const ExplicitVarSlotMap& fragOuts)
: TDefaultGlslIoResolver(intermediate), m_explicitVertexIns(vertexIns), m_explicitFragOuts(fragOuts) {}
const ExplicitVarSlotMap& fragOuts, ExplicitVarSlotMap* opaqueUniformBindings)
: TDefaultGlslIoResolver(intermediate), m_explicitVertexIns(vertexIns), m_explicitFragOuts(fragOuts),
m_explicitOpaqueUniformBindings(opaqueUniformBindings) {}
TMglGlslIoResolver(const glslang::TProgram& program, const EShLanguage stage,
const ExplicitVarSlotMap& vertexIns, const ExplicitVarSlotMap& fragOuts)
: TMglGlslIoResolver(*program.getIntermediate(stage), vertexIns, fragOuts) {}
const ExplicitVarSlotMap& vertexIns, const ExplicitVarSlotMap& fragOuts,
ExplicitVarSlotMap* opaqueUniformBindings)
: TMglGlslIoResolver(*program.getIntermediate(stage), vertexIns, fragOuts, opaqueUniformBindings) {}
void reserverStorageSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) override;
void reserverResourceSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) override;
int resolveUniformLocation(EShLanguage stage, glslang::TVarEntryInfo& ent) override;
protected:
bool ShouldAssignPlainUniformLocation(const glslang::TType& type) const;
void EnsurePlainUniformLocationsAssigned();
const ExplicitVarSlotMap& m_explicitVertexIns;
const ExplicitVarSlotMap& m_explicitFragOuts;
ExplicitVarSlotMap* m_explicitOpaqueUniformBindings = nullptr;
std::map<glslang::TString, int> m_plainUniformLocationSizeByName;
std::map<glslang::TString, int> m_plainUniformLocationByName;
bool m_plainUniformLocationsAssigned = false;
};
} // namespace MobileGL