Merge branch 'dev' of github.com:MobileGL-Dev/MobileGL into dev

This commit is contained in:
BZLZHH
2025-08-13 21:53:35 +08:00
11 changed files with 171 additions and 6 deletions
@@ -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;
};
+1
View File
@@ -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
+3
View File
@@ -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;
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"], 4095);
}
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
@@ -131,15 +131,22 @@ namespace MobileGL {
const char* src[] = {sourceStr.data()};
tshader->setStrings(src, 1);
tshader->setInvertY(true);
tshader->setEnvInput(glslang::EShSourceGlsl, lang, glslang::EShClientVulkan, 450);
tshader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_3);
tshader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_5);
if (attrib.flags & ShaderCompileBits::CompileForOpenGL) {
tshader->setEnvInput(glslang::EShSourceGlsl, lang, glslang::EShClientOpenGL, 450);
tshader->setEnvClient(glslang::EShClientOpenGL, glslang::EShTargetOpenGL_450);
tshader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_5);
} else {
tshader->setEnvInput(glslang::EShSourceGlsl, lang, glslang::EShClientVulkan, 450);
tshader->setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_3);
tshader->setEnvTarget(glslang::EShTargetSpv,
((attrib.flags & ShaderCompileBits::EmitDiscardAsDemote) ? glslang::EShTargetSpv_1_6 : glslang::EShTargetSpv_1_5));
}
tshader->setAutoMapLocations(true);
tshader->setAutoMapBindings(true);
tshader->setEnvInputVulkanRulesRelaxed(); // using EXT_vulkan_glsl_relaxed for gl_VertexID and
// gl_InstanceID?
tshader->setGlobalUniformBlockName(GLOBAL_UBO_NAME);
if (!tshader->parse(&GetTBuiltInResourceInstance(), 150, ECoreProfile,
if (!tshader->parse(&GetTBuiltInResourceInstance(), 460, ECoreProfile,
/*forceDefaultVersionAndProfile: */ false,
/*forwardCompatible: */ true, EShMsgDefault)) {
ResultInfo r;
+2 -1
View File
@@ -9,7 +9,8 @@ namespace MobileGL {
struct EmptyType {};
enum class ShaderCompileBits : Uint {
EmitDiscardAsDemote = 1 << 0,
CompileForOpenGL = 1 << 0,
EmitDiscardAsDemote = 1 << 1,
};
struct ShaderAttrib {
@@ -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