mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
Merge remote-tracking branch 'origin/Feat/Rewriting' into Feat/Rewriting
# Conflicts: # CMakeLists.txt # MobileGL/Includes.h
This commit is contained in:
@@ -34,6 +34,8 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
|
||||
MobileGL/MG_Backend/Init.cpp
|
||||
|
||||
MobileGL/MG_Util/Pipelines/Shader/GLSLtoSPIRVPipeline.cpp
|
||||
MobileGL/MG_Util/Pipelines/ShaderCompilationPipeline.cpp
|
||||
MobileGL/MG_Util/Pipelines/ProgramLinkingPipeline.cpp
|
||||
|
||||
MobileGL/MG_State/GLState/Core.cpp
|
||||
MobileGL/MG_State/GLState/BufferState/BufferState.cpp
|
||||
|
||||
+2
-1
@@ -88,9 +88,10 @@
|
||||
|
||||
#include "MG_Impl/GLImpl/Getter/GL_Getter.h"
|
||||
|
||||
#include "MG_Util/Pipelines/Pipeline.hpp"
|
||||
#include "MG_Util/Pipelines/PipelineExecutor.hpp"
|
||||
|
||||
#include "MG_Util/Pipelines/Shader/GLSLtoSPIRVPipeline.h"
|
||||
#include "MG_Util/Pipelines/ShaderCompilationPipeline.h"
|
||||
|
||||
#include "MG_State/GLState/BufferState/BufferObject.h"
|
||||
#include "MG_State/GLState/BufferState/BufferState.h"
|
||||
|
||||
@@ -5,10 +5,12 @@ namespace MobileGL {
|
||||
MG_Util::Debug::InitFile();
|
||||
MGLOG_I("MobileGL Initializing...");
|
||||
MG_Backend::Init();
|
||||
glslang::InitializeProcess();
|
||||
}
|
||||
|
||||
void MG_Destroy() {
|
||||
MGLOG_I("MobileGL Closing...");
|
||||
glslang::FinalizeProcess();
|
||||
MG_Util::Debug::Close();
|
||||
}
|
||||
|
||||
|
||||
+15
-15
@@ -1,48 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef MG_PIPELINE_HPP
|
||||
#define MG_PIPELINE_HPP
|
||||
#ifndef MG_PIPELINEEXECUTOR_HPP
|
||||
#define MG_PIPELINEEXECUTOR_HPP
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
namespace Pipeline {
|
||||
using next_t = std::function<void()>;
|
||||
using next_ptr_t = std::shared_ptr<next_t>;
|
||||
using next_ptr_t = SharedPtr<next_t>;
|
||||
|
||||
template<typename T>
|
||||
class Stage {
|
||||
protected:
|
||||
using T_ptr = std::shared_ptr<T>;
|
||||
using T_ptr = SharedPtr<T>;
|
||||
using callback_t = std::function<void(T_ptr, next_ptr_t)>;
|
||||
public:
|
||||
virtual callback_t handler() = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class Pipeline {
|
||||
class PipelineExecutor {
|
||||
protected:
|
||||
using T_ptr = std::shared_ptr<T>;
|
||||
using T_ptr = SharedPtr<T>;
|
||||
using callback_t = std::function<void(T_ptr, next_ptr_t)>;
|
||||
using middleware_ptr_t = std::shared_ptr<Stage<T>>;
|
||||
using middleware_ptr_t = SharedPtr<Stage<T>>;
|
||||
public:
|
||||
explicit Pipeline(std::function<void(T &)> callback) :
|
||||
explicit PipelineExecutor(std::function<void(T &)> callback) :
|
||||
callback_(Move(callback)) {}
|
||||
|
||||
Pipeline &Register(callback_t middleware) {
|
||||
PipelineExecutor &Register(callback_t middleware) {
|
||||
middlewares_.emplace_back(Move(middleware));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Pipeline &Register(middleware_ptr_t middleware) {
|
||||
PipelineExecutor &Register(middleware_ptr_t middleware) {
|
||||
middleware_storage_.emplace_back(middleware);
|
||||
Register(middleware->handler());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Process(T_ptr payload) {
|
||||
auto it_ptr = std::make_shared<typename std::vector<callback_t>::iterator>(
|
||||
auto it_ptr = MakeShared<typename Vector<callback_t>::iterator>(
|
||||
middlewares_.begin());
|
||||
auto next = std::make_shared<next_t>();
|
||||
auto next = MakeShared<next_t>();
|
||||
auto weak_next = std::weak_ptr<next_t>(next);
|
||||
|
||||
// setup next callback
|
||||
@@ -66,12 +66,12 @@ namespace MobileGL {
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<callback_t> middlewares_;
|
||||
std::vector<middleware_ptr_t> middleware_storage_;
|
||||
Vector<callback_t> middlewares_;
|
||||
Vector<middleware_ptr_t> middleware_storage_;
|
||||
std::function<void(T &)> callback_;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //MG_PIPELINE_HPP
|
||||
#endif //MG_PIPELINEEXECUTOR_HPP
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// Created by Swung 0x48 on 2025/7/16.
|
||||
//
|
||||
|
||||
#include "ProgramLinkingPipeline.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
namespace Pipeline {
|
||||
ProgramLinkingPipeline::ProgramLinkingPipeline(std::function<void(ProgramPayload &)> callback):
|
||||
executor_(Move(callback)) {
|
||||
executor_
|
||||
.Register([](SharedPtr<ProgramPayload> payload, auto next) {
|
||||
// Link TShader to TProgram
|
||||
auto& shaders = payload->shadersToLink;
|
||||
auto& program = payload->linkedProgram;
|
||||
|
||||
for (auto& shader : shaders) {
|
||||
program.addShader(shader.get());
|
||||
}
|
||||
|
||||
if (!program.link(EShMsgDefault)) {
|
||||
payload->log += "Error: [glslang] Cannot link the program:\n" + std::to_string(program.getInfoLog());
|
||||
payload->errc = -1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
(*next)();
|
||||
})
|
||||
.Register([](auto payload, auto next) {
|
||||
auto& types = payload->shaderTypes;
|
||||
auto& program = payload->linkedProgram;
|
||||
auto& programSpirv = payload->programSpirv;
|
||||
|
||||
glslang::SpvOptions spvOptions;
|
||||
spvOptions.disableOptimizer = false;
|
||||
|
||||
for (auto type : types) {
|
||||
std::vector<unsigned> spirv;
|
||||
|
||||
auto lang = GetEShLanguageByShaderType(type);
|
||||
GlslangToSpv(*program.getIntermediate(lang), spirv, &spvOptions);
|
||||
programSpirv.emplace_back(std::move(spirv));
|
||||
}
|
||||
|
||||
(*next)();
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
void ProgramLinkingPipeline::Invoke(SharedPtr<ProgramPayload> payload) {
|
||||
executor_.Process(Move(payload));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Created by Swung 0x48 on 2025/7/16.
|
||||
//
|
||||
|
||||
#ifndef MG_UTIL_PIPELINES_PROGRAMLINKINGPIPELINE_H
|
||||
#define MG_UTIL_PIPELINES_PROGRAMLINKINGPIPELINE_H
|
||||
|
||||
#include "../../Includes.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
namespace Pipeline {
|
||||
class ProgramLinkingPipeline: public IPipeline<ProgramLinkingPipeline, ProgramPayload> {
|
||||
explicit ProgramLinkingPipeline(std::function<void(ProgramPayload&)> callback);
|
||||
void Invoke(SharedPtr<ProgramPayload> payload);
|
||||
private:
|
||||
PipelineExecutor<ProgramPayload> executor_;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //MG_UTIL_PIPELINES_PROGRAMLINKINGPIPELINE_H
|
||||
@@ -1,60 +0,0 @@
|
||||
//
|
||||
// Created by Swung 0x48 on 2025-07-12.
|
||||
//
|
||||
|
||||
#include "GLSLtoSPIRVPipeline.h"
|
||||
|
||||
MobileGL::MG_Util::Pipeline::GLSLtoSPIRVPipeline::GLSLtoSPIRVPipeline(std::function<void(GLSLtoSPIRVPayload &)> callback):
|
||||
pipeline_(Move(callback)) {
|
||||
pipeline_
|
||||
.Register([this](SharedPtr<GLSLtoSPIRVPayload> payload, auto next) {
|
||||
// source -> glslang TShader
|
||||
auto& shaderType = payload->shaderType;
|
||||
auto& sourceStr = payload->sourceStr;
|
||||
|
||||
glslang::InitializeProcess();
|
||||
auto lang = GetEShLanguageByShaderType(shaderType);
|
||||
if (lang == EShLanguage::EShLangCount) {
|
||||
payload->log += "Error: [Preprocess] Unsupported shader type: " +
|
||||
ConvertGLEnumToString(shaderType);
|
||||
payload->errc = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
auto& tshader = payload->TShader;
|
||||
tshader = MakeUnique<glslang::TShader>(lang);
|
||||
const char* src[] = { sourceStr.c_str() };
|
||||
tshader->setStrings(src, 1);
|
||||
tshader->setInvertY(true);
|
||||
tshader->setEnvInput(glslang::EShSourceGlsl, lang, glslang::EShClientOpenGL, 150);
|
||||
tshader->setEnvClient(glslang::EShClientOpenGL, glslang::EShTargetOpenGL_450);
|
||||
tshader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_6);
|
||||
tshader->setAutoMapLocations(true);
|
||||
tshader->setAutoMapBindings(true);
|
||||
tshader->setEnvInputVulkanRulesRelaxed(); // using EXT_vulkan_glsl_relaxed for gl_VertexID and gl_InstanceID?
|
||||
|
||||
if (!tshader->parse(&GetTBuiltInResourceInstance(), 450, ECoreProfile,
|
||||
/*forceDefaultVersionAndProfile: */false,
|
||||
/*forwardCompatible: */true, EShMsgDefault)) {
|
||||
payload->log += "Error: [glslang] Cannot compile " + ConvertGLEnumToString(shaderType) + ":\n"
|
||||
+ std::to_string(tshader->getInfoLog());
|
||||
payload->errc = -2;
|
||||
return;
|
||||
}
|
||||
|
||||
(*next)();
|
||||
|
||||
glslang::FinalizeProcess();
|
||||
})
|
||||
.Register([this](auto payload, auto next) {
|
||||
UniformTraverser uniformTraverser(payload->uniforms);
|
||||
auto root = payload->TShader->getIntermediate()->getTreeRoot();
|
||||
root->traverse(&uniformTraverser);
|
||||
(*next)();
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
void MobileGL::MG_Util::Pipeline::GLSLtoSPIRVPipeline::Invoke(SharedPtr<GLSLtoSPIRVPayload> payload) {
|
||||
pipeline_.Process(Move(payload));
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
//
|
||||
// Created by Swung 0x48 on 2025-07-12.
|
||||
//
|
||||
|
||||
#ifndef MG_GLSLTOSPIRVPIPELINE_H
|
||||
#define MG_GLSLTOSPIRVPIPELINE_H
|
||||
|
||||
#include "../../../Includes.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
namespace Pipeline {
|
||||
struct TUniform {
|
||||
String name;
|
||||
bool isSampler = false;
|
||||
|
||||
// For isSampler == false
|
||||
glslang::TStorageQualifier storageQualifier;
|
||||
Uint layoutLocation = 0;
|
||||
Uint layoutBinding = 0;
|
||||
glslang::TLayoutPacking layoutPacking;
|
||||
|
||||
// For isSampler == true
|
||||
glslang::TSampler sampler;
|
||||
};
|
||||
|
||||
struct GLSLtoSPIRVPayload {
|
||||
GLenum shaderType;
|
||||
String sourceStr;
|
||||
UniquePtr<glslang::TShader> TShader;
|
||||
Vector<TUniform> uniforms;
|
||||
Int errc = 0;
|
||||
String log;
|
||||
};
|
||||
|
||||
class UniformTraverser : public glslang::TIntermTraverser {
|
||||
public:
|
||||
UniformTraverser(Vector<TUniform>& u): uniforms(u) {}
|
||||
|
||||
void visitSymbol(glslang::TIntermSymbol* symbol) override {
|
||||
const auto& type = symbol->getType();
|
||||
if (symbol->getQualifier().isUniform()) {
|
||||
auto name = symbol->getName();
|
||||
auto qualifier = symbol->getQualifier();
|
||||
|
||||
auto& uniform = uniforms.emplace_back();
|
||||
uniform.isSampler = false;
|
||||
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 = uniforms.emplace_back();
|
||||
uniform.name = symbol->getName();
|
||||
uniform.isSampler = true;
|
||||
uniform.sampler = type.getSampler();
|
||||
}
|
||||
}
|
||||
|
||||
Vector<TUniform>& uniforms;
|
||||
};
|
||||
|
||||
class GLSLtoSPIRVPipeline {
|
||||
explicit GLSLtoSPIRVPipeline(std::function<void(GLSLtoSPIRVPayload &)> callback);
|
||||
void Invoke(SharedPtr<GLSLtoSPIRVPayload> payload);
|
||||
|
||||
inline static EShLanguage GetEShLanguageByShaderType(GLenum shaderType) {
|
||||
switch (shaderType) {
|
||||
case GL_VERTEX_SHADER:
|
||||
return EShLanguage::EShLangVertex;
|
||||
case GL_FRAGMENT_SHADER:
|
||||
return EShLanguage::EShLangFragment;
|
||||
case GL_COMPUTE_SHADER:
|
||||
return EShLanguage::EShLangCompute;
|
||||
case GL_TESS_CONTROL_SHADER:
|
||||
return EShLanguage::EShLangTessControl;
|
||||
case GL_TESS_EVALUATION_SHADER:
|
||||
return EShLanguage::EShLangTessEvaluation;
|
||||
case GL_GEOMETRY_SHADER:
|
||||
return EShLanguage::EShLangGeometry;
|
||||
default:
|
||||
return EShLanguage::EShLangCount;
|
||||
}
|
||||
}
|
||||
|
||||
static inline TBuiltInResource& GetTBuiltInResourceInstance() {
|
||||
static TBuiltInResource Resources{};
|
||||
Resources.maxLights = 32;
|
||||
Resources.maxClipPlanes = 6;
|
||||
Resources.maxTextureUnits = 32;
|
||||
Resources.maxTextureCoords = 32;
|
||||
Resources.maxVertexAttribs = 64;
|
||||
Resources.maxVertexUniformComponents = 4096;
|
||||
Resources.maxVaryingFloats = 64;
|
||||
Resources.maxVertexTextureImageUnits = 32;
|
||||
Resources.maxCombinedTextureImageUnits = 80;
|
||||
Resources.maxTextureImageUnits = 32;
|
||||
Resources.maxFragmentUniformComponents = 4096;
|
||||
Resources.maxDrawBuffers = 32;
|
||||
Resources.maxVertexUniformVectors = 128;
|
||||
Resources.maxVaryingVectors = 8;
|
||||
Resources.maxFragmentUniformVectors = 16;
|
||||
Resources.maxVertexOutputVectors = 16;
|
||||
Resources.maxFragmentInputVectors = 15;
|
||||
Resources.minProgramTexelOffset = -8;
|
||||
Resources.maxProgramTexelOffset = 7;
|
||||
Resources.maxClipDistances = 8;
|
||||
Resources.maxComputeWorkGroupCountX = 65535;
|
||||
Resources.maxComputeWorkGroupCountY = 65535;
|
||||
Resources.maxComputeWorkGroupCountZ = 65535;
|
||||
Resources.maxComputeWorkGroupSizeX = 1024;
|
||||
Resources.maxComputeWorkGroupSizeY = 1024;
|
||||
Resources.maxComputeWorkGroupSizeZ = 64;
|
||||
Resources.maxComputeUniformComponents = 1024;
|
||||
Resources.maxComputeTextureImageUnits = 16;
|
||||
Resources.maxComputeImageUniforms = 8;
|
||||
Resources.maxComputeAtomicCounters = 8;
|
||||
Resources.maxComputeAtomicCounterBuffers = 1;
|
||||
Resources.maxVaryingComponents = 60;
|
||||
Resources.maxVertexOutputComponents = 64;
|
||||
Resources.maxGeometryInputComponents = 64;
|
||||
Resources.maxGeometryOutputComponents = 128;
|
||||
Resources.maxFragmentInputComponents = 128;
|
||||
Resources.maxImageUnits = 8;
|
||||
Resources.maxCombinedImageUnitsAndFragmentOutputs = 8;
|
||||
Resources.maxCombinedShaderOutputResources = 8;
|
||||
Resources.maxImageSamples = 0;
|
||||
Resources.maxVertexImageUniforms = 0;
|
||||
Resources.maxTessControlImageUniforms = 0;
|
||||
Resources.maxTessEvaluationImageUniforms = 0;
|
||||
Resources.maxGeometryImageUniforms = 0;
|
||||
Resources.maxFragmentImageUniforms = 8;
|
||||
Resources.maxCombinedImageUniforms = 8;
|
||||
Resources.maxGeometryTextureImageUnits = 16;
|
||||
Resources.maxGeometryOutputVertices = 256;
|
||||
Resources.maxGeometryTotalOutputComponents = 1024;
|
||||
Resources.maxGeometryUniformComponents = 1024;
|
||||
Resources.maxGeometryVaryingComponents = 64;
|
||||
Resources.maxTessControlInputComponents = 128;
|
||||
Resources.maxTessControlOutputComponents = 128;
|
||||
Resources.maxTessControlTextureImageUnits = 16;
|
||||
Resources.maxTessControlUniformComponents = 1024;
|
||||
Resources.maxTessControlTotalOutputComponents = 4096;
|
||||
Resources.maxTessEvaluationInputComponents = 128;
|
||||
Resources.maxTessEvaluationOutputComponents = 128;
|
||||
Resources.maxTessEvaluationTextureImageUnits = 16;
|
||||
Resources.maxTessEvaluationUniformComponents = 1024;
|
||||
Resources.maxTessPatchComponents = 120;
|
||||
Resources.maxPatchVertices = 32;
|
||||
Resources.maxTessGenLevel = 64;
|
||||
Resources.maxViewports = 16;
|
||||
Resources.maxVertexAtomicCounters = 0;
|
||||
Resources.maxTessControlAtomicCounters = 0;
|
||||
Resources.maxTessEvaluationAtomicCounters = 0;
|
||||
Resources.maxGeometryAtomicCounters = 0;
|
||||
Resources.maxFragmentAtomicCounters = 8;
|
||||
Resources.maxCombinedAtomicCounters = 8;
|
||||
Resources.maxAtomicCounterBindings = 1;
|
||||
Resources.maxVertexAtomicCounterBuffers = 0;
|
||||
Resources.maxTessControlAtomicCounterBuffers = 0;
|
||||
Resources.maxTessEvaluationAtomicCounterBuffers = 0;
|
||||
Resources.maxGeometryAtomicCounterBuffers = 0;
|
||||
Resources.maxFragmentAtomicCounterBuffers = 1;
|
||||
Resources.maxCombinedAtomicCounterBuffers = 1;
|
||||
Resources.maxAtomicCounterBufferSize = 16384;
|
||||
Resources.maxTransformFeedbackBuffers = 4;
|
||||
Resources.maxTransformFeedbackInterleavedComponents = 64;
|
||||
Resources.maxCullDistances = 8;
|
||||
Resources.maxCombinedClipAndCullDistances = 8;
|
||||
Resources.maxSamples = 4;
|
||||
Resources.maxMeshOutputVerticesNV = 256;
|
||||
Resources.maxMeshOutputPrimitivesNV = 512;
|
||||
Resources.maxMeshWorkGroupSizeX_NV = 32;
|
||||
Resources.maxMeshWorkGroupSizeY_NV = 1;
|
||||
Resources.maxMeshWorkGroupSizeZ_NV = 1;
|
||||
Resources.maxTaskWorkGroupSizeX_NV = 32;
|
||||
Resources.maxTaskWorkGroupSizeY_NV = 1;
|
||||
Resources.maxTaskWorkGroupSizeZ_NV = 1;
|
||||
Resources.maxMeshViewCountNV = 4;
|
||||
|
||||
Resources.limits.nonInductiveForLoops = true;
|
||||
Resources.limits.whileLoops = true;
|
||||
Resources.limits.doWhileLoops = true;
|
||||
Resources.limits.generalUniformIndexing = true;
|
||||
Resources.limits.generalAttributeMatrixVectorIndexing = true;
|
||||
Resources.limits.generalVaryingIndexing = true;
|
||||
Resources.limits.generalSamplerIndexing = true;
|
||||
Resources.limits.generalVariableIndexing = true;
|
||||
Resources.limits.generalConstantMatrixVectorIndexing = true;
|
||||
|
||||
return Resources;
|
||||
}
|
||||
private:
|
||||
Pipeline<GLSLtoSPIRVPayload> pipeline_;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //MG_GLSLTOSPIRVPIPELINE_H
|
||||
@@ -0,0 +1,172 @@
|
||||
//
|
||||
// Created by Swung 0x48 on 2025-07-12.
|
||||
//
|
||||
|
||||
#include "ShaderCompilationPipeline.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
namespace Pipeline {
|
||||
TBuiltInResource& ShaderCompilationPipeline::GetTBuiltInResourceInstance()
|
||||
{
|
||||
static TBuiltInResource Resources{};
|
||||
Resources.maxLights = 32;
|
||||
Resources.maxClipPlanes = 6;
|
||||
Resources.maxTextureUnits = 32;
|
||||
Resources.maxTextureCoords = 32;
|
||||
Resources.maxVertexAttribs = 64;
|
||||
Resources.maxVertexUniformComponents = 4096;
|
||||
Resources.maxVaryingFloats = 64;
|
||||
Resources.maxVertexTextureImageUnits = 32;
|
||||
Resources.maxCombinedTextureImageUnits = 80;
|
||||
Resources.maxTextureImageUnits = 32;
|
||||
Resources.maxFragmentUniformComponents = 4096;
|
||||
Resources.maxDrawBuffers = 32;
|
||||
Resources.maxVertexUniformVectors = 128;
|
||||
Resources.maxVaryingVectors = 8;
|
||||
Resources.maxFragmentUniformVectors = 16;
|
||||
Resources.maxVertexOutputVectors = 16;
|
||||
Resources.maxFragmentInputVectors = 15;
|
||||
Resources.minProgramTexelOffset = -8;
|
||||
Resources.maxProgramTexelOffset = 7;
|
||||
Resources.maxClipDistances = 8;
|
||||
Resources.maxComputeWorkGroupCountX = 65535;
|
||||
Resources.maxComputeWorkGroupCountY = 65535;
|
||||
Resources.maxComputeWorkGroupCountZ = 65535;
|
||||
Resources.maxComputeWorkGroupSizeX = 1024;
|
||||
Resources.maxComputeWorkGroupSizeY = 1024;
|
||||
Resources.maxComputeWorkGroupSizeZ = 64;
|
||||
Resources.maxComputeUniformComponents = 1024;
|
||||
Resources.maxComputeTextureImageUnits = 16;
|
||||
Resources.maxComputeImageUniforms = 8;
|
||||
Resources.maxComputeAtomicCounters = 8;
|
||||
Resources.maxComputeAtomicCounterBuffers = 1;
|
||||
Resources.maxVaryingComponents = 60;
|
||||
Resources.maxVertexOutputComponents = 64;
|
||||
Resources.maxGeometryInputComponents = 64;
|
||||
Resources.maxGeometryOutputComponents = 128;
|
||||
Resources.maxFragmentInputComponents = 128;
|
||||
Resources.maxImageUnits = 8;
|
||||
Resources.maxCombinedImageUnitsAndFragmentOutputs = 8;
|
||||
Resources.maxCombinedShaderOutputResources = 8;
|
||||
Resources.maxImageSamples = 0;
|
||||
Resources.maxVertexImageUniforms = 0;
|
||||
Resources.maxTessControlImageUniforms = 0;
|
||||
Resources.maxTessEvaluationImageUniforms = 0;
|
||||
Resources.maxGeometryImageUniforms = 0;
|
||||
Resources.maxFragmentImageUniforms = 8;
|
||||
Resources.maxCombinedImageUniforms = 8;
|
||||
Resources.maxGeometryTextureImageUnits = 16;
|
||||
Resources.maxGeometryOutputVertices = 256;
|
||||
Resources.maxGeometryTotalOutputComponents = 1024;
|
||||
Resources.maxGeometryUniformComponents = 1024;
|
||||
Resources.maxGeometryVaryingComponents = 64;
|
||||
Resources.maxTessControlInputComponents = 128;
|
||||
Resources.maxTessControlOutputComponents = 128;
|
||||
Resources.maxTessControlTextureImageUnits = 16;
|
||||
Resources.maxTessControlUniformComponents = 1024;
|
||||
Resources.maxTessControlTotalOutputComponents = 4096;
|
||||
Resources.maxTessEvaluationInputComponents = 128;
|
||||
Resources.maxTessEvaluationOutputComponents = 128;
|
||||
Resources.maxTessEvaluationTextureImageUnits = 16;
|
||||
Resources.maxTessEvaluationUniformComponents = 1024;
|
||||
Resources.maxTessPatchComponents = 120;
|
||||
Resources.maxPatchVertices = 32;
|
||||
Resources.maxTessGenLevel = 64;
|
||||
Resources.maxViewports = 16;
|
||||
Resources.maxVertexAtomicCounters = 0;
|
||||
Resources.maxTessControlAtomicCounters = 0;
|
||||
Resources.maxTessEvaluationAtomicCounters = 0;
|
||||
Resources.maxGeometryAtomicCounters = 0;
|
||||
Resources.maxFragmentAtomicCounters = 8;
|
||||
Resources.maxCombinedAtomicCounters = 8;
|
||||
Resources.maxAtomicCounterBindings = 1;
|
||||
Resources.maxVertexAtomicCounterBuffers = 0;
|
||||
Resources.maxTessControlAtomicCounterBuffers = 0;
|
||||
Resources.maxTessEvaluationAtomicCounterBuffers = 0;
|
||||
Resources.maxGeometryAtomicCounterBuffers = 0;
|
||||
Resources.maxFragmentAtomicCounterBuffers = 1;
|
||||
Resources.maxCombinedAtomicCounterBuffers = 1;
|
||||
Resources.maxAtomicCounterBufferSize = 16384;
|
||||
Resources.maxTransformFeedbackBuffers = 4;
|
||||
Resources.maxTransformFeedbackInterleavedComponents = 64;
|
||||
Resources.maxCullDistances = 8;
|
||||
Resources.maxCombinedClipAndCullDistances = 8;
|
||||
Resources.maxSamples = 4;
|
||||
Resources.maxMeshOutputVerticesNV = 256;
|
||||
Resources.maxMeshOutputPrimitivesNV = 512;
|
||||
Resources.maxMeshWorkGroupSizeX_NV = 32;
|
||||
Resources.maxMeshWorkGroupSizeY_NV = 1;
|
||||
Resources.maxMeshWorkGroupSizeZ_NV = 1;
|
||||
Resources.maxTaskWorkGroupSizeX_NV = 32;
|
||||
Resources.maxTaskWorkGroupSizeY_NV = 1;
|
||||
Resources.maxTaskWorkGroupSizeZ_NV = 1;
|
||||
Resources.maxMeshViewCountNV = 4;
|
||||
|
||||
Resources.limits.nonInductiveForLoops = true;
|
||||
Resources.limits.whileLoops = true;
|
||||
Resources.limits.doWhileLoops = true;
|
||||
Resources.limits.generalUniformIndexing = true;
|
||||
Resources.limits.generalAttributeMatrixVectorIndexing = true;
|
||||
Resources.limits.generalVaryingIndexing = true;
|
||||
Resources.limits.generalSamplerIndexing = true;
|
||||
Resources.limits.generalVariableIndexing = true;
|
||||
Resources.limits.generalConstantMatrixVectorIndexing = true;
|
||||
|
||||
return Resources;
|
||||
}
|
||||
|
||||
ShaderCompilationPipeline::ShaderCompilationPipeline(std::function<void(ShaderPayload &)> callback):
|
||||
executor_(Move(callback)) {
|
||||
executor_
|
||||
.Register([this](SharedPtr<ShaderPayload> payload, auto next) {
|
||||
// source -> glslang TShader
|
||||
auto& shaderType = payload->shaderType;
|
||||
auto& sourceStr = payload->sourceStr;
|
||||
|
||||
auto lang = GetEShLanguageByShaderType(shaderType);
|
||||
if (lang == EShLanguage::EShLangCount) {
|
||||
payload->log += "Error: [Preprocess] Unsupported shader type: " +
|
||||
ConvertGLEnumToString(shaderType);
|
||||
payload->errc = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
auto& tshader = payload->TShader;
|
||||
tshader = MakeUnique<glslang::TShader>(lang);
|
||||
const char* src[] = { sourceStr.c_str() };
|
||||
tshader->setStrings(src, 1);
|
||||
tshader->setInvertY(true);
|
||||
tshader->setEnvInput(glslang::EShSourceGlsl, lang, glslang::EShClientOpenGL, 150);
|
||||
tshader->setEnvClient(glslang::EShClientOpenGL, glslang::EShTargetOpenGL_450);
|
||||
tshader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_6);
|
||||
tshader->setAutoMapLocations(true);
|
||||
tshader->setAutoMapBindings(true);
|
||||
tshader->setEnvInputVulkanRulesRelaxed(); // using EXT_vulkan_glsl_relaxed for gl_VertexID and gl_InstanceID?
|
||||
|
||||
if (!tshader->parse(&GetTBuiltInResourceInstance(), 450, ECoreProfile,
|
||||
/*forceDefaultVersionAndProfile: */false,
|
||||
/*forwardCompatible: */true, EShMsgDefault)) {
|
||||
payload->log += "Error: [glslang] Cannot compile " + ConvertGLEnumToString(shaderType) + ":\n"
|
||||
+ std::to_string(tshader->getInfoLog());
|
||||
payload->errc = -2;
|
||||
return;
|
||||
}
|
||||
|
||||
(*next)();
|
||||
})
|
||||
.Register([this](auto payload, auto next) {
|
||||
UniformTraverser uniformTraverser(payload->uniforms, payload->samplers);
|
||||
auto root = payload->TShader->getIntermediate()->getTreeRoot();
|
||||
root->traverse(&uniformTraverser);
|
||||
(*next)();
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
void ShaderCompilationPipeline::Invoke(SharedPtr<ShaderPayload> payload) {
|
||||
executor_.Process(Move(payload));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// Created by Swung 0x48 on 2025-07-12.
|
||||
//
|
||||
|
||||
#ifndef MG_UTIL_PIPELINES_SHADERCOMPILATIONPIPELINE_H
|
||||
#define MG_UTIL_PIPELINES_SHADERCOMPILATIONPIPELINE_H
|
||||
|
||||
#include "../../Includes.h"
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
namespace Pipeline {
|
||||
class UniformTraverser : public glslang::TIntermTraverser {
|
||||
public:
|
||||
UniformTraverser(Vector<TUniform<TUniformType::Uniform>>& u, Vector<TUniform<TUniformType::Sampler>>& s): uniforms(u), samplers(s) {}
|
||||
|
||||
void visitSymbol(glslang::TIntermSymbol* symbol) override {
|
||||
const auto& type = symbol->getType();
|
||||
if (symbol->getQualifier().isUniform()) {
|
||||
auto name = symbol->getName();
|
||||
auto qualifier = symbol->getQualifier();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
Vector<TUniform<TUniformType::Uniform>>& uniforms;
|
||||
Vector<TUniform<TUniformType::Sampler>>& samplers;
|
||||
};
|
||||
|
||||
class ShaderCompilationPipeline: public IPipeline<ShaderCompilationPipeline, ShaderPayload> {
|
||||
explicit ShaderCompilationPipeline(std::function<void(ShaderPayload &)> callback);
|
||||
void Invoke(SharedPtr<ShaderPayload> payload);
|
||||
|
||||
static TBuiltInResource& GetTBuiltInResourceInstance();
|
||||
private:
|
||||
PipelineExecutor<ShaderPayload> executor_;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //MG_UTIL_PIPELINES_SHADERCOMPILATIONPIPELINE_H
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// Created by Swung 0x48 on 2025/7/16.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#ifndef MG_UTIL_PIPELINES_TYPES_H
|
||||
#define MG_UTIL_PIPELINES_TYPES_H
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
namespace Pipeline {
|
||||
template <class DerivedPipeline, typename Payload>
|
||||
class IPipeline {
|
||||
void Invoke(SharedPtr<Payload> payload) {
|
||||
static_cast<DerivedPipeline>(this)->Invoke(payload);
|
||||
}
|
||||
};
|
||||
|
||||
enum class TUniformType {
|
||||
Uniform,
|
||||
Sampler
|
||||
};
|
||||
|
||||
template <TUniformType T>
|
||||
struct TUniform {
|
||||
static_assert(false, "TUniform<T> does not accept this enum");
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TUniform<TUniformType::Uniform> {
|
||||
String name;
|
||||
|
||||
glslang::TStorageQualifier storageQualifier;
|
||||
Uint layoutLocation = 0;
|
||||
Uint layoutBinding = 0;
|
||||
glslang::TLayoutPacking layoutPacking;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct TUniform<TUniformType::Sampler> {
|
||||
String name;
|
||||
|
||||
glslang::TSampler sampler;
|
||||
};
|
||||
|
||||
struct ShaderPayload {
|
||||
// In
|
||||
GLenum shaderType;
|
||||
String sourceStr;
|
||||
|
||||
// Out
|
||||
UniquePtr<glslang::TShader> TShader;
|
||||
Vector<TUniform<TUniformType::Uniform>> uniforms;
|
||||
Vector<TUniform<TUniformType::Sampler>> samplers;
|
||||
Int errc = 0;
|
||||
String log;
|
||||
};
|
||||
|
||||
struct ProgramPayload {
|
||||
// In
|
||||
Vector<GLenum> shaderTypes;
|
||||
Vector<UniquePtr<glslang::TShader>> shadersToLink;
|
||||
|
||||
// Out
|
||||
glslang::TProgram linkedProgram;
|
||||
Vector<Vector<Uint>> programSpirv;
|
||||
Int errc = 0;
|
||||
String log;
|
||||
};
|
||||
|
||||
inline static EShLanguage GetEShLanguageByShaderType(GLenum shaderType) {
|
||||
switch (shaderType) {
|
||||
case GL_VERTEX_SHADER:
|
||||
return EShLanguage::EShLangVertex;
|
||||
case GL_FRAGMENT_SHADER:
|
||||
return EShLanguage::EShLangFragment;
|
||||
case GL_COMPUTE_SHADER:
|
||||
return EShLanguage::EShLangCompute;
|
||||
case GL_TESS_CONTROL_SHADER:
|
||||
return EShLanguage::EShLangTessControl;
|
||||
case GL_TESS_EVALUATION_SHADER:
|
||||
return EShLanguage::EShLangTessEvaluation;
|
||||
case GL_GEOMETRY_SHADER:
|
||||
return EShLanguage::EShLangGeometry;
|
||||
default:
|
||||
return EShLanguage::EShLangCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //MG_UTIL_PIPELINES_TYPES_H
|
||||
@@ -125,4 +125,6 @@ namespace MobileGL {
|
||||
GLInfo RendererGLInfo;
|
||||
BackendCap BackendCapability;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#include "Pipelines/Types.h"
|
||||
Reference in New Issue
Block a user