mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Feat]: (MG_Util/ShaderTranspiler): TMglGlslIoResolver: a custom glslang IoResolver to realize glBindAttribLocation semantics
This commit is contained in:
@@ -86,6 +86,7 @@ namespace MobileGL {
|
||||
|
||||
MG_Util::ShaderTranspiler::ProgramAttrib attrib{
|
||||
.shaders = Move(shaders),
|
||||
.explicitAttribLocations = m_explicitAttribLocations
|
||||
};
|
||||
|
||||
MGLOG_D("ProgramObject %u: Calling ShaderCompiler::LinkProgram", m_externalIndex);
|
||||
@@ -246,79 +247,81 @@ namespace MobileGL {
|
||||
m_attribTypes[location] = inVar.glDefineType;
|
||||
MGLOG_D("ProgramObject %u: Reflection - placed attrib '%s' at explicit location %d",
|
||||
m_externalIndex, inVar.name.c_str(), location);
|
||||
} else if (location >= (int)m_attribs.size()) {
|
||||
MGLOG_W("ProgramObject %u: ProgramObject::DoReflection - attrib location %d >= attribs.size() "
|
||||
"(%zu). Ignoring.",
|
||||
m_externalIndex, location, m_attribs.size());
|
||||
continue;
|
||||
} else {
|
||||
bool placed = false;
|
||||
for (size_t idx = 0; idx < m_attribs.size(); ++idx) {
|
||||
if (m_attribs[idx].empty()) {
|
||||
m_attribs[idx] = inVar.name;
|
||||
m_attribTypes[idx] = inVar.glDefineType;
|
||||
placed = true;
|
||||
MGLOG_D("ProgramObject %u: Reflection - placed attrib '%s' into free slot %zu",
|
||||
m_externalIndex, inVar.name.c_str(), idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!placed && (int)m_attribs.size() < maxAttribs) {
|
||||
m_attribs.push_back(inVar.name);
|
||||
m_attribTypes.push_back(inVar.glDefineType);
|
||||
placed = true;
|
||||
MGLOG_D("ProgramObject %u: Reflection - pushed attrib '%s' to new slot %zu",
|
||||
m_externalIndex, inVar.name.c_str(), m_attribs.size() - 1);
|
||||
}
|
||||
if (!placed) {
|
||||
MGLOG_W("ProgramObject %u: ProgramObject::DoReflection - cannot place attrib '%s' (no free "
|
||||
"slot and at max capacity). Ignoring.",
|
||||
m_externalIndex, inVar.name.c_str());
|
||||
}
|
||||
}
|
||||
// else if (location >= (int)m_attribs.size()) {
|
||||
// MGLOG_W("ProgramObject %u: ProgramObject::DoReflection - attrib location %d >= attribs.size() "
|
||||
// "(%zu). Ignoring.",
|
||||
// m_externalIndex, location, m_attribs.size());
|
||||
// continue;
|
||||
// }
|
||||
// else {
|
||||
// bool placed = false;
|
||||
// for (size_t idx = 0; idx < m_attribs.size(); ++idx) {
|
||||
// if (m_attribs[idx].empty()) {
|
||||
// m_attribs[idx] = inVar.name;
|
||||
// m_attribTypes[idx] = inVar.glDefineType;
|
||||
// placed = true;
|
||||
// MGLOG_D("ProgramObject %u: Reflection - placed attrib '%s' into free slot %zu",
|
||||
// m_externalIndex, inVar.name.c_str(), idx);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (!placed && (int)m_attribs.size() < maxAttribs) {
|
||||
// m_attribs.push_back(inVar.name);
|
||||
// m_attribTypes.push_back(inVar.glDefineType);
|
||||
// placed = true;
|
||||
// MGLOG_D("ProgramObject %u: Reflection - pushed attrib '%s' to new slot %zu",
|
||||
// m_externalIndex, inVar.name.c_str(), m_attribs.size() - 1);
|
||||
// }
|
||||
// if (!placed) {
|
||||
// MGLOG_W("ProgramObject %u: ProgramObject::DoReflection - cannot place attrib '%s' (no free "
|
||||
// "slot and at max capacity). Ignoring.",
|
||||
// m_externalIndex, inVar.name.c_str());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// Implement glBindAttribLocation semantics (explicit locations set by user)
|
||||
for (auto& [name, location] : m_explicitAttribLocations) {
|
||||
MGLOG_D("ProgramObject %u: Reflection - explicit attrib location request: name='%s' location=%d",
|
||||
m_externalIndex, name.c_str(), location);
|
||||
if (location < 0) continue;
|
||||
if (location >= (int)m_attribs.size()) {
|
||||
if (location >= maxAttribs) {
|
||||
MGLOG_W("ProgramObject %u: SetExplicitAttribLocation: requested location %d >= "
|
||||
"GL_MAX_VERTEX_ATTRIBS (%d). Ignored for attribute '%s'.",
|
||||
m_externalIndex, location, maxAttribs, name.c_str());
|
||||
continue;
|
||||
}
|
||||
m_attribs.resize(location + 1);
|
||||
m_attribTypes.resize(location + 1);
|
||||
MGLOG_D("ProgramObject %u: Reflection - resized attrib arrays to %zu to accommodate explicit "
|
||||
"location %d",
|
||||
m_externalIndex, m_attribs.size(), location);
|
||||
}
|
||||
|
||||
if (m_attribs[location] != name) {
|
||||
auto it = std::find(m_attribs.begin(), m_attribs.end(), name);
|
||||
if (it == m_attribs.end()) {
|
||||
MGLOG_D("ProgramObject %u: Reflection - explicit attrib '%s' not found in current list, "
|
||||
"skipping swap",
|
||||
m_externalIndex, name.c_str());
|
||||
continue;
|
||||
}
|
||||
auto idx = std::distance(m_attribs.begin(), it);
|
||||
std::swap(m_attribs[location], m_attribs[idx]);
|
||||
std::swap(m_attribTypes[location], m_attribTypes[idx]);
|
||||
MGLOG_D("ProgramObject %u: Reflection - swapped attrib '%s' from idx %zu to explicit "
|
||||
"location %d",
|
||||
m_externalIndex, name.c_str(), idx, location);
|
||||
}
|
||||
|
||||
for (SizeT idx = 0; idx < m_attribs.size(); ++idx) {
|
||||
m_attribLocation[m_attribs[idx]] = idx;
|
||||
MGLOG_D("ProgramObject %u: Reflection - attribLocation['%s'] = %zu", m_externalIndex,
|
||||
m_attribs[idx].c_str(), idx);
|
||||
}
|
||||
}
|
||||
// for (auto& [name, location] : m_explicitAttribLocations) {
|
||||
// MGLOG_D("ProgramObject %u: Reflection - explicit attrib location request: name='%s' location=%d",
|
||||
// m_externalIndex, name.c_str(), location);
|
||||
// if (location < 0) continue;
|
||||
// if (location >= (int)m_attribs.size()) {
|
||||
// if (location >= maxAttribs) {
|
||||
// MGLOG_W("ProgramObject %u: SetExplicitAttribLocation: requested location %d >= "
|
||||
// "GL_MAX_VERTEX_ATTRIBS (%d). Ignored for attribute '%s'.",
|
||||
// m_externalIndex, location, maxAttribs, name.c_str());
|
||||
// continue;
|
||||
// }
|
||||
// m_attribs.resize(location + 1);
|
||||
// m_attribTypes.resize(location + 1);
|
||||
// MGLOG_D("ProgramObject %u: Reflection - resized attrib arrays to %zu to accommodate explicit "
|
||||
// "location %d",
|
||||
// m_externalIndex, m_attribs.size(), location);
|
||||
// }
|
||||
//
|
||||
// if (m_attribs[location] != name) {
|
||||
// auto it = std::find(m_attribs.begin(), m_attribs.end(), name);
|
||||
// if (it == m_attribs.end()) {
|
||||
// MGLOG_D("ProgramObject %u: Reflection - explicit attrib '%s' not found in current list, "
|
||||
// "skipping swap",
|
||||
// m_externalIndex, name.c_str());
|
||||
// continue;
|
||||
// }
|
||||
// auto idx = std::distance(m_attribs.begin(), it);
|
||||
// std::swap(m_attribs[location], m_attribs[idx]);
|
||||
// std::swap(m_attribTypes[location], m_attribTypes[idx]);
|
||||
// MGLOG_D("ProgramObject %u: Reflection - swapped attrib '%s' from idx %zu to explicit "
|
||||
// "location %d",
|
||||
// m_externalIndex, name.c_str(), idx, location);
|
||||
// }
|
||||
//
|
||||
// for (SizeT idx = 0; idx < m_attribs.size(); ++idx) {
|
||||
// m_attribLocation[m_attribs[idx]] = idx;
|
||||
// MGLOG_D("ProgramObject %u: Reflection - attribLocation['%s'] = %zu", m_externalIndex,
|
||||
// m_attribs[idx].c_str(), idx);
|
||||
// }
|
||||
// }
|
||||
|
||||
// ---------- UBO ----------
|
||||
int uboCount = m_program->getNumUniformBlocks();
|
||||
|
||||
@@ -26,6 +26,7 @@ in float fIn2;
|
||||
in float fIn5;
|
||||
in float fIn6;
|
||||
in float fIn1;
|
||||
layout (location = 0) in float fIn0;
|
||||
in float fIn3;
|
||||
|
||||
layout(location = 0) uniform mat4 ProjMat;
|
||||
@@ -45,7 +46,7 @@ void main(){
|
||||
vec2 dummy2 = TestMat2[0];
|
||||
vec3 dummy3 = TestMat3[0];
|
||||
|
||||
oneTexel = (1.0 * (fIn1 * fIn2 * fIn3 * fIn4 * fIn5 * fIn6)) / InSize;
|
||||
oneTexel = (1.0 * (fIn1 * fIn2 * fIn3 * fIn4 * fIn5 * fIn6 * fIn0)) / InSize;
|
||||
|
||||
texCoord = Position.xy / OutSize;
|
||||
})";
|
||||
@@ -135,6 +136,9 @@ TEST_F(ProgramTest, CompileAndLink) {
|
||||
BindAttribLocation(program, 5, "fIn5");
|
||||
printf("Linking program...\n");
|
||||
LinkProgram(program);
|
||||
GLint linkStatus = GL_FALSE;
|
||||
GetProgramiv(program, GL_LINK_STATUS, &linkStatus);
|
||||
ASSERT_EQ(linkStatus, GL_TRUE);
|
||||
printf("Program linked.\n");
|
||||
|
||||
ASSERT_EQ(GetUniformLocation(program, "ProjMat"), 0);
|
||||
@@ -151,6 +155,7 @@ TEST_F(ProgramTest, CompileAndLink) {
|
||||
ASSERT_EQ(GetAttribLocation(program, "fIn1"), 1);
|
||||
ASSERT_EQ(GetAttribLocation(program, "fIn3"), 3);
|
||||
ASSERT_EQ(GetAttribLocation(program, "fIn5"), 5);
|
||||
ASSERT_EQ(GetAttribLocation(program, "fIn0"), 0);
|
||||
|
||||
UseProgram(program);
|
||||
|
||||
|
||||
@@ -174,13 +174,13 @@ namespace MobileGL {
|
||||
return std::unexpected(r);
|
||||
}
|
||||
|
||||
UniquePtr<glslang::TIoMapResolver> resolver;
|
||||
// UniquePtr<glslang::TIoMapResolver> resolver;
|
||||
UniquePtr<TMglGlslIoResolver> resolver;
|
||||
for (unsigned stage = 0; stage < EShLangCount; stage++) {
|
||||
auto* pResolver = program->getGlslIoResolver((EShLanguage)stage);
|
||||
if (pResolver) {
|
||||
resolver = UniquePtr<glslang::TIoMapResolver>(pResolver);
|
||||
break;
|
||||
}
|
||||
if (program->getIntermediate((EShLanguage)stage) == nullptr)
|
||||
continue;
|
||||
resolver = MakeUnique<TMglGlslIoResolver>(*program, (EShLanguage)stage, attrib.explicitAttribLocations);
|
||||
break;
|
||||
}
|
||||
auto ioMapper = UniquePtr<glslang::TIoMapper>(glslang::GetGlslIoMapper());
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace MobileGL {
|
||||
|
||||
struct ProgramAttrib {
|
||||
Vector<SharedPtr<glslang::TShader>> shaders;
|
||||
UnorderedMap<String, Uint> explicitAttribLocations;
|
||||
};
|
||||
|
||||
struct ProgramBinaryAttrib {
|
||||
|
||||
@@ -4,10 +4,17 @@
|
||||
|
||||
#include "TMglGlslIoResolver.h"
|
||||
|
||||
int TMglGlslIoResolver::resolveInOutLocation(EShLanguage stage, glslang::TVarEntryInfo &ent) {
|
||||
return glslang::TDefaultGlslIoResolver::resolveInOutLocation(stage, ent);
|
||||
}
|
||||
|
||||
int TMglGlslIoResolver::resolveUniformLocation(EShLanguage stage, glslang::TVarEntryInfo &ent) {
|
||||
return glslang::TDefaultGlslIoResolver::resolveUniformLocation(stage, ent);
|
||||
}
|
||||
namespace MobileGL {
|
||||
void TMglGlslIoResolver::reserverStorageSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) {
|
||||
const glslang::TType& type = ent.symbol->getType();
|
||||
const glslang::TString& name = ent.symbol->getAccessName();
|
||||
if (type.getQualifier().isPipeInput()) {
|
||||
auto it = m_explicitAttribLocations.find(name.c_str());
|
||||
if (it != m_explicitAttribLocations.end()) {
|
||||
auto& writableType = ent.symbol->getWritableType();
|
||||
writableType.getQualifier().layoutLocation = it->second;
|
||||
}
|
||||
}
|
||||
TDefaultGlslIoResolver::reserverStorageSlot(ent, infoSink);
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,21 @@
|
||||
#include <glslang/Include/intermediate.h>
|
||||
#include <glslang/MachineIndependent/iomapper.h>
|
||||
#include "TVarEntryInfo.h"
|
||||
#include "MG_Util/Types.h"
|
||||
|
||||
class TMglGlslIoResolver: public glslang::TDefaultGlslIoResolver {
|
||||
int resolveInOutLocation(EShLanguage stage, glslang::TVarEntryInfo& ent) override;
|
||||
int resolveUniformLocation(EShLanguage /*stage*/, glslang::TVarEntryInfo& ent) override;
|
||||
};
|
||||
namespace MobileGL {
|
||||
class TMglGlslIoResolver: public glslang::TDefaultGlslIoResolver {
|
||||
public:
|
||||
using ExplicitVarSlotMap = UnorderedMap<String, Uint>;
|
||||
TMglGlslIoResolver(const glslang::TIntermediate& intermediate, const ExplicitVarSlotMap& attribLocations):
|
||||
TDefaultGlslIoResolver(intermediate), m_explicitAttribLocations(attribLocations) {}
|
||||
TMglGlslIoResolver(const glslang::TProgram& program, const EShLanguage stage, const ExplicitVarSlotMap& attribLocations):
|
||||
TDefaultGlslIoResolver(*program.getIntermediate(stage)),
|
||||
m_explicitAttribLocations(attribLocations) {}
|
||||
void reserverStorageSlot(glslang::TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
||||
protected:
|
||||
const ExplicitVarSlotMap& m_explicitAttribLocations;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user