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

This commit is contained in:
BZLZHH
2025-08-15 18:22:03 +08:00
11 changed files with 330 additions and 161 deletions
+90 -3
View File
@@ -100,7 +100,7 @@ namespace MobileGL {
}
GLuint CreateShader_State(GLenum type) {
auto shaderId = MG_State::pGLContext->CreateShader(MG_State::GLState::GetMGLShaderStageByGLShaderType(type));
auto shaderId = MG_State::pGLContext->CreateShader(MG_State::GLState::ConvertMGLShaderStageByGLShaderType(type));
if (shaderId == 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
@@ -199,7 +199,68 @@ namespace MobileGL {
}
void GetProgramiv_State(GLuint program, GLenum pname, GLint* params) {
THROW_UNIMPL_EXCEPTION;
auto programObject = TryToGetProgramObject(program);
if (!programObject)
return;
switch (pname) {
case GL_DELETE_STATUS:
*params = programObject->GetDeleteStatus();
break;
case GL_LINK_STATUS:
*params = programObject->GetLinkStatus();
break;
case GL_VALIDATE_STATUS:
*params = programObject->GetValidateStatus();
break;
case GL_INFO_LOG_LENGTH: {
const auto& log = programObject->GetInfoLog();
*params = log.length();
break;
}
case GL_ATTACHED_SHADERS: {
const auto& attachedShaders = programObject->GetAttachedShaders();
*params = attachedShaders.size();
break;
}
case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
*params = programObject->GetActiveAtomicCounterCount();
break;
case GL_ACTIVE_ATTRIBUTES:
*params = programObject->GetActiveAttributesCount();
break;
case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
*params = programObject->GetActiveAttributesMaxLength();
break;
case GL_ACTIVE_UNIFORMS:
*params = programObject->GetUniformCount();
break;
case GL_ACTIVE_UNIFORM_MAX_LENGTH:
*params = programObject->GetUniformMaxLength();
break;
case GL_ACTIVE_UNIFORM_BLOCKS: // GL >= 3.1
*params = programObject->GetActiveUniformBlocksCount();
break;
case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: // ditto.
*params = programObject->GetActiveUniformBlocksMaxLength();
break;
case GL_COMPUTE_WORK_GROUP_SIZE: // GL >= 4.3
case GL_PROGRAM_BINARY_LENGTH:
case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
case GL_TRANSFORM_FEEDBACK_VARYINGS:
case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
case GL_GEOMETRY_VERTICES_OUT:
case GL_GEOMETRY_INPUT_TYPE:
case GL_GEOMETRY_OUTPUT_TYPE:
default:
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`pname` is not an accepted value."));
return;
}
}
void GetProgramInfoLog_State(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
@@ -212,7 +273,33 @@ namespace MobileGL {
}
void GetShaderiv_State(GLuint shader, GLenum pname, GLint* params) {
THROW_UNIMPL_EXCEPTION;
auto shaderObject = TryToGetShaderObject(shader);
if (!shaderObject)
return;
switch (pname) {
case GL_SHADER_TYPE:
*params = ConvertGLShaderTypeByMGLShaderStage(shaderObject->GetShaderStage());
break;
case GL_DELETE_STATUS:
*params = shaderObject->GetDeleteStatus();
break;
case GL_COMPILE_STATUS:
*params = shaderObject->GetCompileStatus();
break;
case GL_INFO_LOG_LENGTH:
*params = shaderObject->GetInfoLog().length();
break;
case GL_SHADER_SOURCE_LENGTH:
*params = shaderObject->GetShaderSource().length();
break;
default:
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeShared<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
"`pname` is not an accepted value."));
return;
}
}
void GetShaderInfoLog_State(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
@@ -26,12 +26,12 @@ namespace MobileGL {
}
void ProgramObject::Link() {
PreLink();
// PreLink();
Vector<GLenum> shaderTypes(m_shaders.size());
Vector<SharedPtr<glslang::TShader>> shaders(m_shaders.size());
for (SizeT i = 0; i < m_shaders.size(); i++) {
shaderTypes[i] = GetGLShaderTypeByMGLShaderStage(m_shaders[i]->GetShaderStage());
shaderTypes[i] = ConvertGLShaderTypeByMGLShaderStage(m_shaders[i]->GetShaderStage());
shaders[i] = m_shaders[i]->GetCompiledShader();
}
@@ -43,17 +43,15 @@ namespace MobileGL {
auto result = MG_Util::ShaderTranspiler::ShaderCompiler::LinkProgram(attrib);
if (result) {
m_linkStatus = true;
m_programBinary = Move(result.value());
m_program = result.value();
} else {
m_linkStatus = false;
m_infoLog = result.error().log;
const std::string e = std::format("Shader link failed: \nerrc: {}\nmsg: {}\n", result.error().errc,
result.error().log);
THROW_EXCEPTION(e);
}
PostLink();
// PostLink();
DoReflection();
}
void ProgramObject::MarkAsDeleted() {
@@ -64,99 +62,139 @@ namespace MobileGL {
return m_shaders;
}
void ProgramObject::PreLink() {
m_uniforms.clear();
m_uniformOffsets.clear();
for (const auto& shader : m_shaders) {
for (const auto& [name, loc] : shader->GetUniformLocations()) {
// collect all the names to map
if (loc != 4095 || m_uniforms.find(name) == m_uniforms.end()) {
m_uniforms[name] = loc;
}
// set a flag for those who have an explicit location
if (loc != 4095) {
if (loc >= m_uniformOffsets.size()) {
m_uniformOffsets.reserve(std::bit_ceil(loc + 1));
m_uniformOffsets.resize(loc + 1, 0);
}
assert(m_uniformOffsets[loc] == 0);
m_uniformOffsets[loc] = 1;
}
}
void ProgramObject::DoReflection() {
if (!m_program->buildReflection()) {
m_linkStatus = false;
m_infoLog = "Build reflection failed.";
return;
}
// Let's find a location for those who doesn't have one yet
Uint nextLocation = 0;
// Find first empty location
for (SizeT i = 0; i < m_uniformOffsets.size(); i++) {
if (m_uniformOffsets[i] == 0) {
nextLocation = i;
break;
}
auto uniformCount = m_program->getNumUniformVariables();
for (int i = 0; i < uniformCount; i++) {
auto& uniform = m_program->getUniform(i);
auto location = uniform.layoutLocation();
m_maxUniformLocation = std::max(m_maxUniformLocation, location);
m_uniformNameMaxLength = std::max(m_uniformNameMaxLength, (Int)uniform.name.length());
m_uniformLocations[uniform.name] = location;
}
for (auto& [name, loc] : m_uniforms) {
if (loc == 4095) {
// check if we drained all the holes already
if (nextLocation >= m_uniformOffsets.size()) {
loc = nextLocation;
m_uniformOffsets.push_back(1);
nextLocation++;
continue;
}
m_uniformNames.resize(m_maxUniformLocation + 1);
m_uniformTypes.resize(m_maxUniformLocation + 1);
m_uniformOffsets.resize(m_maxUniformLocation + 1);
// assign an empty location
loc = nextLocation;
m_uniformOffsets[loc] = 1;
// Find next empty location
for (nextLocation++; nextLocation < m_uniformOffsets.size(); nextLocation++) {
if (m_uniformOffsets[nextLocation] == 0) break;
}
}
for (int i = 0; i < uniformCount; i++) {
auto& uniform = m_program->getUniform(i);
auto location = uniform.layoutLocation();
m_uniformNames[location] = uniform.name;
m_uniformTypes[location] = uniform.glDefineType;
}
m_uniformNames.resize(m_uniformOffsets.size());
for (auto& [name, loc] : m_uniforms) {
m_uniformNames[loc] = name;
m_uniformNameMaxLength = std::max(m_uniformNameMaxLength, (Int)name.length());
int inCount = m_program->getNumPipeInputs();
for (int i = 0; i < inCount; i++) {
auto& inVar = m_program->getPipeInput(i);
m_attribInNameMaxLength = std::max(m_attribInNameMaxLength, (Int)inVar.name.length());
}
int uboCount = m_program->getNumUniformBlocks();
for (int i = 0; i < uboCount; i++) {
auto& ubo = m_program->getUniformBlock(i);
m_uniformBlockNameMaxLength = std::max(m_uniformBlockNameMaxLength, (Int)ubo.name.length());
}
}
void ProgramObject::PostLink() {
if (m_programBinary.empty()) {
assert(false);
return;
}
MG_Util::ShaderTranspiler::SpvcSession session(m_programBinary[0]);
const char* src = nullptr; // we don't care the source atm
auto result = session.Compile(&src);
if (result != SPVC_SUCCESS) {
assert(false);
return;
}
m_metadata = session.GetMetadata();
auto& uniformOffsets = m_metadata.plainUniformOffsetsInUBO;
for (const auto& [name, offset] : uniformOffsets) {
assert(m_uniforms.find(name) != m_uniforms.end());
assert(m_uniforms[name] < m_uniformOffsets.size());
m_uniformOffsets[m_uniforms[name]] = offset;
}
m_uboScratch.resize(m_metadata.uboSize, 0);
auto& types = m_metadata.plainUniformMemberTypes;
assert(types.size() == m_uniformOffsets.size());
m_uniformTypes.resize(m_uniformOffsets.size());
for (const auto& [name, type] : types) {
auto gltype = MG_Util::ConvertSpvcTypeToGLEnum(type);
auto location = m_uniforms[name];
m_uniformTypes[location] = gltype;
}
}
// void ProgramObject::PreLink() {
// m_uniforms.clear();
// m_uniformOffsets.clear();
//
// for (const auto& shader : m_shaders) {
// for (const auto& [name, loc] : shader->GetUniformLocations()) {
// // collect all the names to map
// if (loc != 4095 || m_uniforms.find(name) == m_uniforms.end()) {
// m_uniforms[name] = loc;
// }
//
// // set a flag for those who have an explicit location
// if (loc != 4095) {
// if (loc >= m_uniformOffsets.size()) {
// m_uniformOffsets.reserve(std::bit_ceil(loc + 1));
// m_uniformOffsets.resize(loc + 1, 0);
// }
// assert(m_uniformOffsets[loc] == 0);
// m_uniformOffsets[loc] = 1;
// }
// }
// }
//
// // Let's find a location for those who doesn't have one yet
// Uint nextLocation = 0;
//
// // Find first empty location
// for (SizeT i = 0; i < m_uniformOffsets.size(); i++) {
// if (m_uniformOffsets[i] == 0) {
// nextLocation = i;
// break;
// }
// }
//
// for (auto& [name, loc] : m_uniforms) {
// if (loc == 4095) {
// // check if we drained all the holes already
// if (nextLocation >= m_uniformOffsets.size()) {
// loc = nextLocation;
// m_uniformOffsets.push_back(1);
// nextLocation++;
// continue;
// }
//
// // assign an empty location
// loc = nextLocation;
// m_uniformOffsets[loc] = 1;
//
// // Find next empty location
// for (nextLocation++; nextLocation < m_uniformOffsets.size(); nextLocation++) {
// if (m_uniformOffsets[nextLocation] == 0) break;
// }
// }
// }
//
// m_uniformNames.resize(m_uniformOffsets.size());
// for (auto& [name, loc] : m_uniforms) {
// m_uniformNames[loc] = name;
// m_uniformNameMaxLength = std::max(m_uniformNameMaxLength, (Int)name.length());
// }
// }
//
// void ProgramObject::PostLink() {
// if (m_programBinary.empty()) {
// assert(false);
// return;
// }
// MG_Util::ShaderTranspiler::SpvcSession session(m_programBinary[0]);
// const char* src = nullptr; // we don't care the source atm
// auto result = session.Compile(&src);
// if (result != SPVC_SUCCESS) {
// assert(false);
// return;
// }
// m_metadata = session.GetMetadata();
// auto& uniformOffsets = m_metadata.plainUniformOffsetsInUBO;
// for (const auto& [name, offset] : uniformOffsets) {
// assert(m_uniforms.find(name) != m_uniforms.end());
// assert(m_uniforms[name] < m_uniformOffsets.size());
// m_uniformOffsets[m_uniforms[name]] = offset;
// }
// m_uboScratch.resize(m_metadata.uboSize, 0);
//
// auto& types = m_metadata.plainUniformMemberTypes;
//
// assert(types.size() == m_uniformOffsets.size());
// m_uniformTypes.resize(m_uniformOffsets.size());
// for (const auto& [name, type] : types) {
// auto gltype = MG_Util::ConvertSpvcTypeToGLEnum(type);
// auto location = m_uniforms[name];
// m_uniformTypes[location] = gltype;
// }
// }
} // namespace GLState
} // namespace MG_State
} // namespace MobileGL
@@ -17,10 +17,10 @@ namespace MobileGL {
Vector<SharedPtr<ShaderObject>>& GetAttachedShaders();
const String& GetInfoLog() const { return m_infoLog; }
Int GetUniformMaxLength() const { return m_uniformNameMaxLength; }
Uint GetUniformCount() { return m_uniformOffsets.size(); }
Uint GetUniformCount() { return m_uniformNames.size(); }
Int GetUniformLocation(const String& name) {
const auto it = m_uniforms.find(name);
return (it == m_uniforms.end()) ? -1 : it->second;
const auto it = m_uniformLocations.find(name);
return (it == m_uniformLocations.end()) ? -1 : it->second;
}
GLenum GetUniformType(Uint index) const {
return m_uniformTypes[index];
@@ -29,28 +29,40 @@ namespace MobileGL {
const String& GetUniformName(Uint index) const {
return m_uniformNames[index];
}
Bool GetDeleteStatus() const { return m_deleteStatus; }
Bool GetLinkStatus() const { return m_linkStatus; }
Bool GetValidateStatus() const { return m_validateStatus; }
Int GetActiveAtomicCounterCount() const { return m_program->getNumAtomicCounters(); }
Int GetActiveAttributesCount() const { return m_program->getNumPipeInputs(); }
Int GetActiveUniformBlocksCount() const { return m_program->getNumUniformBlocks(); }
Int GetActiveAttributesMaxLength() const { return m_attribInNameMaxLength; }
Int GetActiveUniformBlocksMaxLength() const { return m_uniformBlockNameMaxLength; }
private:
void PreLink();
void PostLink();
void DoReflection();
// void PreLink();
// void PostLink();
const Uint m_id = 0;
Vector<SharedPtr<ShaderObject>> m_shaders;
// basically this contains SPIR-V in binary format
Vector<Vector<Uint>> m_programBinary;
SharedPtr<glslang::TProgram> m_program;
// Uniforms
MG_Util::ShaderTranspiler::SpvcMetadata m_metadata;
// MG_Util::ShaderTranspiler::SpvcMetadata m_metadata;
UnorderedMap<String, Uint> m_uniforms;
// 0 or 1 for if the location is explicitly specified at PreLink stage,
// offsets into global ubo for PostLink
Vector<Uint> m_uniformOffsets;
UnorderedMap<String, Uint> m_uniformLocations;
Vector<String> m_uniformNames;
Vector<GLenum> m_uniformTypes;
// Need to be reflected after linking of SPIR-V binary
Vector<Uint> m_uniformOffsets;
Vector<Uint8> m_uboScratch;
Uint m_maxUniformLocation = 0;
Int m_uniformNameMaxLength = 0;
Int m_attribInNameMaxLength = 0;
Int m_uniformBlockNameMaxLength = 0;
String m_infoLog;
Bool m_deleteStatus = false;
@@ -15,15 +15,19 @@ namespace MobileGL {
}
void ShaderObject::Compile() {
if (!DoReflection()) {
return;
}
// if (!DoReflection()) {
// return;
// }
using namespace MG_Util::ShaderTranspiler;
// Compile for OpenGL here, so that we can do validation and link
// like a real OpenGL driver at linking stage
// Will compile for other backends later.
ShaderAttrib attrib{
.shaderType = GetGLShaderTypeByMGLShaderStage(m_stage),
.shaderType = ConvertGLShaderTypeByMGLShaderStage(m_stage),
.sourceStr = m_source,
.flags = 0
.flags = ShaderCompileBits::CompileForOpenGL
};
auto result = ShaderCompiler::CompileShader(attrib);
@@ -33,9 +37,6 @@ namespace MobileGL {
} else {
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);
}
}
@@ -43,35 +44,36 @@ namespace MobileGL {
m_deleteStatus = true;
}
bool ShaderObject::DoReflection() {
using namespace MG_Util::ShaderTranspiler;
ShaderAttrib attrib{
.shaderType = GetGLShaderTypeByMGLShaderStage(m_stage),
.sourceStr = m_source,
.flags = ShaderCompileBits::CompileForOpenGL
};
// 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;
// }
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
@@ -14,7 +14,7 @@ namespace MobileGL {
Unknown = -1
};
inline static GLenum GetGLShaderTypeByMGLShaderStage(ShaderStage stage) {
inline static GLenum ConvertGLShaderTypeByMGLShaderStage(ShaderStage stage) {
switch (stage) {
case ShaderStage::Vertex:
return GL_VERTEX_SHADER;
@@ -34,7 +34,7 @@ namespace MobileGL {
}
}
inline static ShaderStage GetMGLShaderStageByGLShaderType(GLenum type) {
inline static ShaderStage ConvertMGLShaderStageByGLShaderType(GLenum type) {
switch (type) {
case GL_VERTEX_SHADER:
return ShaderStage::Vertex;
@@ -68,8 +68,10 @@ namespace MobileGL {
SharedPtr<glslang::TShader> GetCompiledShader() const { return m_shader; }
const String& GetInfoLog() const { return m_infoLog; }
const UnorderedMap<String, Uint>& GetUniformLocations() const { return m_uniforms; }
Bool GetCompileStatus() const { return m_compileStatus; }
Bool GetDeleteStatus() const { return m_deleteStatus; }
private:
bool DoReflection();
// bool DoReflection();
const Uint m_id = 0;
const ShaderStage m_stage;
String m_source;
-2
View File
@@ -3,8 +3,6 @@ project(MobileGLTest)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0")
include(FetchContent)
FetchContent_Declare(
+9 -2
View File
@@ -52,11 +52,12 @@ uniform vec2 InSize;
layout(location = 1) uniform vec3 Gray;
uniform vec3 RedMatrix;
uniform vec3 GreenMatrix;
uniform vec3 GreenMatrix0;
uniform vec3 BlueMatrix;
uniform vec3 Offset;
uniform vec3 ColorScale;
layout(location = 6) uniform float Saturation;
uniform int AQuickFoxJumpsOverALazyDog;
out vec4 fragColor;
@@ -65,7 +66,7 @@ void main() {
// Color Matrix
float RedValue = dot(InTexel.rgb, RedMatrix);
float GreenValue = dot(InTexel.rgb, GreenMatrix);
float GreenValue = dot(InTexel.rgb, GreenMatrix0);
float BlueValue = dot(InTexel.rgb, BlueMatrix);
vec3 OutColor = vec3(RedValue, GreenValue, BlueValue);
@@ -116,4 +117,10 @@ TEST_F(ProgramTest, CompileAndLink) {
EXPECT_EQ(GetUniformLocation(program, "ProjMat"), 0);
EXPECT_EQ(GetUniformLocation(program, "Gray"), 1);
EXPECT_EQ(GetUniformLocation(program, "Saturation"), 6);
GLint uniformCount = 0;
GetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniformCount);
EXPECT_EQ(uniformCount, 11);
GLint uniformNameMaxLength = 0;
GetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformNameMaxLength);
EXPECT_EQ(uniformNameMaxLength, 12);
}
+15 -2
View File
@@ -143,8 +143,15 @@ TEST_F(ProgramUtilTest, CompileFragmentShaderWithDiscard) {
FAIL() << "errc: " << program_res.error().errc << "\nlog: " << program_res.error().log;
}
auto program = program_res.value();
auto spirvs = program_res.value();
ProgramBinaryAttrib binaryAttrib {
.shaderTypes = { GL_FRAGMENT_SHADER },
.program = *program,
};
auto bin_res = ShaderCompiler::GetSpirvBinaryFromProgram(binaryAttrib);
auto spirvs = bin_res.value();
Vector<SpvcSession> sessions(spirvs.size());
for (SizeT i = 0; i < spirvs.size(); ++i) {
@@ -282,7 +289,13 @@ TEST_F(ProgramUtilTest, DecompProgram) {
FAIL() << "errc: " << program_res.error().errc << "\nlog: " << program_res.error().log;
}
auto spirvs = program_res.value();
ProgramBinaryAttrib binaryAttrib {
.shaderTypes = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER },
.program = *program_res.value(),
};
auto bin_res = ShaderCompiler::GetSpirvBinaryFromProgram(binaryAttrib);
auto spirvs = bin_res.value();
Vector<SpvcSession> sessions(spirvs.size());
for (SizeT i = 0; i < spirvs.size(); ++i) {
@@ -159,22 +159,22 @@ namespace MobileGL {
return res;
}
Result<Vector<Vector<unsigned>>> ShaderCompiler::LinkProgram(const ProgramAttrib& attrib) {
glslang::TProgram program;
Result<SharedPtr<glslang::TProgram>> ShaderCompiler::LinkProgram(const ProgramAttrib& attrib) {
SharedPtr<glslang::TProgram> program = MakeShared<glslang::TProgram>();
for (auto& s : attrib.shaders) {
program.addShader(s.get());
program->addShader(s.get());
}
if (!program.link(EShMsgDefault)) {
if (!program->link(EShMsgDefault)) {
ResultInfo r;
r.log = "Error: [glslang] Cannot link the program:\n" + std::string(program.getInfoLog());
r.log = "Error: [glslang] Cannot link the program:\n" + std::string(program->getInfoLog());
r.errc = -3;
return std::unexpected(r);
}
UniquePtr<glslang::TIoMapResolver> resolver;
for (unsigned stage = 0; stage < EShLangCount; stage++) {
auto* pResolver = program.getGlslIoResolver((EShLanguage)stage);
auto* pResolver = program->getGlslIoResolver((EShLanguage)stage);
if (pResolver) {
resolver = UniquePtr<glslang::TIoMapResolver>(pResolver);
break;
@@ -182,20 +182,24 @@ namespace MobileGL {
}
auto ioMapper = UniquePtr<glslang::TIoMapper>(glslang::GetGlslIoMapper());
if (!program.mapIO(resolver.get(), ioMapper.get())) {
if (!program->mapIO(resolver.get(), ioMapper.get())) {
ResultInfo r;
r.log = "Error: [glslang] Cannot mapIO:\n" + std::string(program.getInfoLog());
r.log = "Error: [glslang] Cannot mapIO:\n" + std::string(program->getInfoLog());
r.errc = -4;
return std::unexpected(r);
}
return program;
}
Result<Vector<Vector<unsigned>>> ShaderCompiler::GetSpirvBinaryFromProgram(const ProgramBinaryAttrib &attrib) {
glslang::SpvOptions spvOptions;
spvOptions.disableOptimizer = false;
Vector<Vector<unsigned>> allSpirv;
for (auto type : attrib.shaderTypes) {
Vector<unsigned> spirv;
GlslangToSpv(*program.getIntermediate(ConvertGLEnumToEShLanguage(type)), spirv, &spvOptions);
GlslangToSpv(*attrib.program.getIntermediate(ConvertGLEnumToEShLanguage(type)), spirv, &spvOptions);
allSpirv.push_back(spirv);
}
@@ -8,7 +8,8 @@ namespace MobileGL {
class ShaderCompiler {
public:
static Result<SharedPtr<glslang::TShader>> CompileShader(const ShaderAttrib& attrib);
static Result<Vector<Vector<unsigned>>> LinkProgram(const ProgramAttrib& attrib);
static Result<SharedPtr<glslang::TProgram>> LinkProgram(const ProgramAttrib& attrib);
static Result<Vector<Vector<unsigned>>> GetSpirvBinaryFromProgram(const ProgramBinaryAttrib& attrib);
static Result<String> DecompileShader(SpvcSession& session);
};
} // namespace ShaderTranspiler
@@ -24,6 +24,11 @@ namespace MobileGL {
Vector<SharedPtr<glslang::TShader>> shaders;
};
struct ProgramBinaryAttrib {
Vector<GLenum> shaderTypes;
const glslang::TProgram& program;
};
struct ResultInfo {
Int errc = 0;
String log;