mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 21:28:32 +09:00
[Feat] (MG_Util/ShaderCompiler, MG_State/Program): reflect uniform location
This commit is contained in:
@@ -63,6 +63,7 @@ namespace MobileGL {
|
||||
Vector<SharedPtr<ShaderObject>>& ProgramObject::GetAttachedShaders() {
|
||||
return m_shaders;
|
||||
}
|
||||
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "ShaderObject.h"
|
||||
#include <MG_Util/ShaderTranspiler/ShaderCompiler.h>
|
||||
|
||||
#include "MG_Util/ShaderTranspiler/glslang/UniformTraverser.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_State {
|
||||
namespace GLState {
|
||||
@@ -13,6 +15,10 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
void ShaderObject::Compile() {
|
||||
if (!DoReflection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace MG_Util::ShaderTranspiler;
|
||||
ShaderAttrib attrib{
|
||||
.shaderType = GetGLShaderTypeByMGLShaderStage(m_stage),
|
||||
@@ -36,6 +42,36 @@ namespace MobileGL {
|
||||
void ShaderObject::MarkAsDeleted() {
|
||||
m_deleteStatus = true;
|
||||
}
|
||||
|
||||
bool ShaderObject::DoReflection() {
|
||||
using namespace MG_Util::ShaderTranspiler;
|
||||
ShaderAttrib attrib{
|
||||
.shaderType = GetGLShaderTypeByMGLShaderStage(m_stage),
|
||||
.sourceStr = m_source,
|
||||
.flags = ShaderCompileBits::CompileForOpenGL
|
||||
};
|
||||
|
||||
auto result = ShaderCompiler::CompileShader(attrib);
|
||||
if (!result) {
|
||||
m_compileStatus = false;
|
||||
m_infoLog = result.error().log;
|
||||
|
||||
const std::string e = std::format("Shader compilation failed: \nerrc: {}\nmsg: {}\n",
|
||||
result.error().errc, result.error().log);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto pShader = result.value();
|
||||
auto root = pShader->getIntermediate()->getTreeRoot();
|
||||
UniformTraverser traverser;
|
||||
root->traverse(&traverser);
|
||||
auto& symbols = traverser.GetCollectedSymbols();
|
||||
for (const auto& symbol : symbols) {
|
||||
m_uniforms[symbol->getName().c_str()] = symbol->getQualifier().layoutLocation;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace GLState
|
||||
} // namespace MG_State
|
||||
} // namespace MobileGL
|
||||
@@ -68,12 +68,14 @@ namespace MobileGL {
|
||||
SharedPtr<glslang::TShader> GetCompiledShader() const { return m_shader; }
|
||||
const String& GetInfoLog() const { return m_infoLog; }
|
||||
private:
|
||||
bool DoReflection();
|
||||
const Uint m_id = 0;
|
||||
const ShaderStage m_stage;
|
||||
String m_source;
|
||||
SharedPtr<glslang::TShader> m_shader;
|
||||
String m_infoLog;
|
||||
UnorderedMap<String, Int> m_uniforms;
|
||||
|
||||
String m_infoLog;
|
||||
Bool m_deleteStatus = false;
|
||||
Bool m_compileStatus = false;
|
||||
};
|
||||
|
||||
@@ -36,6 +36,7 @@ add_executable(
|
||||
${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_Backend/Init.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_Util/Debug/Log.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/glslang/UniformTraverser.cpp
|
||||
)
|
||||
|
||||
target_include_directories(BufferTest PRIVATE
|
||||
|
||||
@@ -8,6 +8,7 @@ add_executable(
|
||||
${MGL_ROOT}/MobileGL/MG_Util/Converters/GLToGlslang/GLShaderLangConverter.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/glslang/UniformTraverser.cpp
|
||||
)
|
||||
|
||||
target_include_directories(ProgramUtilTest PRIVATE
|
||||
@@ -35,6 +36,8 @@ add_executable(
|
||||
${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp
|
||||
|
||||
${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/glslang/UniformTraverser.cpp
|
||||
|
||||
${MGL_ROOT}/MobileGL/MG_State/GLState/Core.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_State/GLState/BufferState/BufferState.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
|
||||
#include <MG_Util/ShaderTranspiler/ShaderCompiler.h>
|
||||
#include <MG_Util/ShaderTranspiler/Types.h>
|
||||
|
||||
#include "MG_Util/ShaderTranspiler/glslang/UniformTraverser.h"
|
||||
using namespace MobileGL;
|
||||
|
||||
class ProgramUtilTest : public ::testing::Test {
|
||||
@@ -165,6 +167,54 @@ TEST_F(ProgramUtilTest, CompileFragmentShaderWithDiscard) {
|
||||
}
|
||||
}
|
||||
|
||||
const char* vs_location = R"(#version 460
|
||||
|
||||
in vec4 Position;
|
||||
|
||||
layout(location = 1) uniform mat4 ProjMat;
|
||||
layout(location = 20) uniform vec2 InSize;
|
||||
layout(location = 0) uniform vec2 OutSize;
|
||||
|
||||
out vec2 texCoord;
|
||||
out vec2 oneTexel;
|
||||
|
||||
void main(){
|
||||
vec4 outPos = ProjMat * vec4(Position.xy, 0.0, 1.0);
|
||||
gl_Position = vec4(outPos.xy, 0.2, 1.0);
|
||||
|
||||
oneTexel = 1.0 / InSize;
|
||||
|
||||
texCoord = Position.xy / OutSize;
|
||||
})";
|
||||
|
||||
TEST_F(ProgramUtilTest, CompileVertexShaderWithLocation) {
|
||||
using namespace MG_Util::ShaderTranspiler;
|
||||
ShaderAttrib attrib {
|
||||
.shaderType = GL_VERTEX_SHADER,
|
||||
.sourceStr = vs_location,
|
||||
.flags = ShaderCompileBits::CompileForOpenGL
|
||||
};
|
||||
auto res = ShaderCompiler::CompileShader(attrib);
|
||||
if (!res) {
|
||||
ASSERT_NE(res.error().errc, 0);
|
||||
FAIL() << "errc: " << res.error().errc << "\nlog: " << res.error().log;
|
||||
}
|
||||
UnorderedMap<String, Int> uniforms;
|
||||
|
||||
auto pShader = res.value();
|
||||
auto root = pShader->getIntermediate()->getTreeRoot();
|
||||
UniformTraverser traverser;
|
||||
root->traverse(&traverser);
|
||||
auto& symbols = traverser.GetCollectedSymbols();
|
||||
for (const auto& symbol : symbols) {
|
||||
uniforms[symbol->getName().c_str()] = symbol->getQualifier().layoutLocation;
|
||||
}
|
||||
|
||||
EXPECT_EQ(uniforms["ProjMat"], 1);
|
||||
EXPECT_EQ(uniforms["InSize"], 20);
|
||||
EXPECT_EQ(uniforms["OutSize"], 0);
|
||||
}
|
||||
|
||||
TEST_F(ProgramUtilTest, CompileAndLinkProgram) {
|
||||
using namespace MG_Util::ShaderTranspiler;
|
||||
ShaderAttrib vs_attrib {
|
||||
|
||||
@@ -36,6 +36,7 @@ add_executable(
|
||||
${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/SpvcSession.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_Backend/Init.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_Util/Debug/Log.cpp
|
||||
${MGL_ROOT}/MobileGL/MG_Util/ShaderTranspiler/glslang/UniformTraverser.cpp
|
||||
)
|
||||
|
||||
target_include_directories(VertexArrayTest PRIVATE
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Created by Swung 0x48 on 2025/7/20.
|
||||
//
|
||||
|
||||
#include "UniformTraverser.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
namespace ShaderTranspiler {
|
||||
void UniformTraverser::visitSymbol(glslang::TIntermSymbol *symbol) {
|
||||
auto parent = getParentNode();
|
||||
if (!parent)
|
||||
return;
|
||||
auto parentAgg = parent->getAsAggregate();
|
||||
if (!parentAgg || parentAgg->getOp() != glslang::EOpLinkerObjects)
|
||||
return;
|
||||
|
||||
const auto &type = symbol->getType();
|
||||
if (symbol->getQualifier().isUniform()) {
|
||||
m_collectedSymbols.emplace_back(symbol);
|
||||
// auto& name = symbol->getName();
|
||||
// auto qualifier = symbol->getQualifier();
|
||||
//
|
||||
// printf("layout(location = %d) uniform %s\n", qualifier.layoutLocation, name.c_str());
|
||||
// auto &uniform = uniforms.emplace_back();
|
||||
// uniform.name = name;
|
||||
// uniform.storageQualifier = qualifier.storage;
|
||||
// uniform.layoutLocation = qualifier.layoutLocation;
|
||||
// uniform.layoutBinding = qualifier.layoutBinding;
|
||||
// uniform.layoutPacking = qualifier.layoutPacking;
|
||||
} else if (type.getBasicType() == glslang::EbtSampler) {
|
||||
// auto &uniform = samplers.emplace_back();
|
||||
// uniform.name = symbol->getName();
|
||||
// uniform.sampler = type.getSampler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Created by Swung 0x48 on 2025/7/20.
|
||||
//
|
||||
|
||||
#ifndef MOBILEGL_UNIFORMTRAVERSER_H
|
||||
#define MOBILEGL_UNIFORMTRAVERSER_H
|
||||
|
||||
#include "Includes.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
namespace ShaderTranspiler {
|
||||
class UniformTraverser : public glslang::TIntermTraverser {
|
||||
public:
|
||||
void visitSymbol(glslang::TIntermSymbol *symbol) override;
|
||||
Vector<glslang::TIntermSymbol*>& GetCollectedSymbols() { return m_collectedSymbols; }
|
||||
private:
|
||||
Vector<glslang::TIntermSymbol*> m_collectedSymbols;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //MOBILEGL_UNIFORMTRAVERSER_H
|
||||
Reference in New Issue
Block a user