[Feat] (MG_Backend|MG_State/ProgramState): Add default fragment shader if missing for backends requiring FS.

This commit is contained in:
BZLZHH
2025-12-31 21:09:19 +08:00
parent c902721683
commit 58b620dee3
6 changed files with 53 additions and 9 deletions
+1 -1
View File
@@ -38,7 +38,7 @@
#define MOBILEGL_BACKEND_TYPE_DIRECT_GLES 3
// ====================== MobileGL configurations ======================= //
#define MOBILEGL_LOG_ACTIVE_LEVEL MOBILEGL_LOG_LEVEL_FATAL
#define MOBILEGL_LOG_ACTIVE_LEVEL MOBILEGL_LOG_LEVEL_INFO
#define MOBILEGL_LOG_ENABLE_CONSOLE 0
#define MOBILEGL_LOG_ENABLE_FILE 1
+4 -4
View File
@@ -24,7 +24,7 @@ namespace MobileGL {
.Extensions = {}, // OpenGL Extensions
.IsCompatibilityProfile = false // Is Compatibility Profile
},
.BackendCapability = {} // Backend Capability
.BackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
};
}
@@ -47,7 +47,7 @@ namespace MobileGL {
V_OpenGL33},
.IsCompatibilityProfile = false // Is Compatibility Profile
},
.BackendCapability = {} // Backend Capability
.BackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
};
inline RendererInfo RendererInfoMetal = {
@@ -63,7 +63,7 @@ namespace MobileGL {
V_OpenGL33},
.IsCompatibilityProfile = false // Is Compatibility Profile
},
.BackendCapability = {} // Backend Capability
.BackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
};
} // namespace Diligent
@@ -81,7 +81,7 @@ namespace MobileGL {
V_OpenGL33, E_GL_ARB_draw_buffers_blend},
.IsCompatibilityProfile = false // Is Compatibility Profile
},
.BackendCapability = {} // Backend Capability
.BackendCapability = {.AllowVSOnlyPrograms = false} // Backend Capability
};
} // namespace DirectGLES
@@ -6,6 +6,7 @@
// End of Source File Header
#include "GL_Program.h"
#include "Config.h"
#include "MG_Util/Converters/GLToStr/GLEnumConverter.h"
#include <MG_State/GLState/Core.h>
#include <MG_Util/Converters/GLToMG/ProgramEnumConverter.h>
@@ -475,7 +476,7 @@ namespace MobileGL {
auto programObject = TryToGetProgramObject(program);
if (!programObject) return;
MGLOG_D("%s: linking program %d", __func__, program);
programObject->Link();
programObject->Link(!MG_Config::RendererInfoPtr->BackendCapability.AllowVSOnlyPrograms);
}
void ShaderSource_State(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) {
@@ -12,6 +12,11 @@
#include <MG_Util/Converters/MGToGL/ProgramEnumConverter.h>
#include <MG_Util/Converters/SPIRVCrossToGL/SpvcTypeConverter.h>
const char* kDefaultFragmentShaderSource = R"(#version 460 core
layout(location = 0) out vec4 FragColor;
void main() {}
)";
namespace MobileGL {
namespace MG_State {
namespace GLState {
@@ -58,7 +63,38 @@ namespace MobileGL {
return count;
}
void ProgramObject::Link() {
void ProgramObject::AddDefaultFragmentShaderIfMissing() {
Bool needsDefaultFS = false;
for (const auto& shader : m_shaders) {
auto stage = shader->GetShaderStage();
if (stage == ShaderStage::Vertex) {
needsDefaultFS = true;
continue;
}
if (stage == ShaderStage::Fragment) {
needsDefaultFS = false;
return;
}
}
if (!needsDefaultFS) return;
MGLOG_D("ProgramObject %u: No fragment shader attached, adding default fragment shader.",
m_externalIndex);
SharedPtr<ShaderObject> defaultFS = MakeShared<ShaderObject>(ShaderStage::Fragment, 0);
defaultFS->SetShaderSource(kDefaultFragmentShaderSource);
defaultFS->Compile(); // TODO: use a global default FS object.
auto status = defaultFS->GetCompileStatus();
if (!status) {
MGLOG_E("ProgramObject %u: Failed to compile default fragment shader. InfoLog:\n%s",
m_externalIndex, defaultFS->GetInfoLog().c_str());
return;
}
m_shaders.push_back(defaultFS);
MGLOG_D("ProgramObject %u: Default fragment shader added.", m_externalIndex);
}
void ProgramObject::Link(Bool addDefaultFSIfMissingForRenderingPipelineProgram) {
MGLOG_D("ProgramObject %u: Link start, shaders to link: %zu", m_externalIndex, m_shaders.size());
// Remove detached shaders first
for (const auto& detachedShader : m_detachedShaders) {
@@ -69,6 +105,10 @@ namespace MobileGL {
Vector<GLenum> shaderTypes(m_shaders.size());
Vector<SharedPtr<glslang::TShader>> shaders(m_shaders.size());
if (addDefaultFSIfMissingForRenderingPipelineProgram) {
AddDefaultFragmentShaderIfMissing();
}
for (SizeT i = 0; i < m_shaders.size(); i++) {
shaderTypes[i] = MG_Util::ConvertShaderStageToGLEnum(m_shaders[i]->GetShaderStage());
MGLOG_D("ProgramObject %u: Preparing shader[%zu] stage %s at %p", m_externalIndex, i,
@@ -21,7 +21,7 @@ namespace MobileGL {
bool AttachShader(SharedPtr<ShaderObject> shader);
SizeT DetachShader(SharedPtr<ShaderObject> shader);
SizeT RemoveShader(SharedPtr<ShaderObject> shader);
void Link();
void Link(Bool addDefaultFSIfMissingForRenderingPipelineProgram = false);
void MarkAsDeleted();
void SetExplicitVertexInLocation(Uint index, const char* name);
@@ -120,6 +120,7 @@ namespace MobileGL {
void DoReflection();
void GenerateBinary();
void WaitUntilGenerationCompleted();
void AddDefaultFragmentShaderIfMissing();
const Uint m_externalIndex = 0;
Vector<SharedPtr<ShaderObject>> m_shaders;
+3 -1
View File
@@ -248,7 +248,9 @@ namespace MobileGL {
}
};
struct BackendCap {};
struct BackendCap {
Bool AllowVSOnlyPrograms = false;
};
struct GLInfo {
Version TargetGLVersion;