mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
Merge branch 'dev' of github.com:MobileGL-Dev/MobileGL into dev
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user