mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Fix] (MG_Impl/GLImpl, MG_State/GLState): validate frag data link locations [skip ci]
This commit is contained in:
@@ -589,6 +589,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
const auto& rendererInfo = activeBackendObject->GetRendererInfo();
|
const auto& rendererInfo = activeBackendObject->GetRendererInfo();
|
||||||
allowVSOnlyPrograms = (Int)rendererInfo.StaticBackendCapability.AllowVSOnlyPrograms;
|
allowVSOnlyPrograms = (Int)rendererInfo.StaticBackendCapability.AllowVSOnlyPrograms;
|
||||||
}
|
}
|
||||||
|
const auto& activeBackendObject = MG_Backend::pActiveBackendObject;
|
||||||
|
if (activeBackendObject) {
|
||||||
|
programObject->SetMaxFragmentOutputColorNumber(activeBackendObject->GetDynamicParameters().MaxDrawBuffers);
|
||||||
|
}
|
||||||
programObject->Link(!allowVSOnlyPrograms);
|
programObject->Link(!allowVSOnlyPrograms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ void main() {}
|
|||||||
)";
|
)";
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
static MobileGL::String StripArrayElementSuffix(const MobileGL::String& name) {
|
||||||
|
const MobileGL::SizeT bracket = name.find('[');
|
||||||
|
return bracket == MobileGL::String::npos ? name : name.substr(0, bracket);
|
||||||
|
}
|
||||||
|
|
||||||
static int GetVertexInputLocationSpan(GLenum glType) {
|
static int GetVertexInputLocationSpan(GLenum glType) {
|
||||||
switch (glType) {
|
switch (glType) {
|
||||||
case GL_FLOAT_MAT2:
|
case GL_FLOAT_MAT2:
|
||||||
@@ -225,6 +230,9 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
MGLOG_D("ProgramObject %u: Starting reflection", m_externalIndex);
|
MGLOG_D("ProgramObject %u: Starting reflection", m_externalIndex);
|
||||||
DoReflection();
|
DoReflection();
|
||||||
MGLOG_D("ProgramObject %u: Reflection done (linkStatus=%d)", m_externalIndex, (int)m_linkStatus);
|
MGLOG_D("ProgramObject %u: Reflection done (linkStatus=%d)", m_externalIndex, (int)m_linkStatus);
|
||||||
|
if (!ValidateFragmentOutputLocations()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MGLOG_D("ProgramObject %u: Starting binary generation", m_externalIndex);
|
MGLOG_D("ProgramObject %u: Starting binary generation", m_externalIndex);
|
||||||
GenerateBinary();
|
GenerateBinary();
|
||||||
@@ -590,6 +598,43 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
m_externalIndex, name, index);
|
m_externalIndex, name, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool ProgramObject::ValidateFragmentOutputLocations() {
|
||||||
|
if (!m_program) return false;
|
||||||
|
|
||||||
|
UnorderedMap<Int, String> colorNumberOwners;
|
||||||
|
const Int outputCount = m_program->getNumPipeOutputs();
|
||||||
|
for (Int index = 0; index < outputCount; ++index) {
|
||||||
|
const auto& output = m_program->getPipeOutput(index);
|
||||||
|
const String outputName = StripArrayElementSuffix(output.name);
|
||||||
|
const auto explicitLocation = m_explicitFragDataLocation.find(outputName);
|
||||||
|
const Int location = explicitLocation != m_explicitFragDataLocation.end()
|
||||||
|
? static_cast<Int>(explicitLocation->second)
|
||||||
|
: static_cast<Int>(output.layoutLocation());
|
||||||
|
const Int span = std::max<Int>(output.size, 1);
|
||||||
|
|
||||||
|
if (location < 0 || location + span > m_maxFragmentOutputColorNumber) {
|
||||||
|
m_infoLog = std::format("Fragment output '{}' location range [{}, {}) exceeds GL_MAX_DRAW_BUFFERS {}.",
|
||||||
|
outputName, location, location + span, m_maxFragmentOutputColorNumber);
|
||||||
|
MGLOG_E("ProgramObject %u: Link failed - %s", m_externalIndex, m_infoLog.c_str());
|
||||||
|
ResetLinkArtifacts();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Int colorNumber = location; colorNumber < location + span; ++colorNumber) {
|
||||||
|
auto [owner, inserted] = colorNumberOwners.emplace(colorNumber, outputName);
|
||||||
|
if (!inserted) {
|
||||||
|
m_infoLog = std::format("Fragment outputs '{}' and '{}' alias color number {}.",
|
||||||
|
owner->second, outputName, colorNumber);
|
||||||
|
MGLOG_E("ProgramObject %u: Link failed - %s", m_externalIndex, m_infoLog.c_str());
|
||||||
|
ResetLinkArtifacts();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Int ProgramObject::GetFragmentDataLocation(const char* name) {
|
Int ProgramObject::GetFragmentDataLocation(const char* name) {
|
||||||
if (!m_program || !name) return -1;
|
if (!m_program || !name) return -1;
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
|
|
||||||
void SetExplicitVertexInLocation(Uint index, const char* name);
|
void SetExplicitVertexInLocation(Uint index, const char* name);
|
||||||
void SetExplicitFragmentOutLocation(Uint index, const char* name);
|
void SetExplicitFragmentOutLocation(Uint index, const char* name);
|
||||||
|
void SetMaxFragmentOutputColorNumber(Int maxDrawBuffers) {
|
||||||
|
m_maxFragmentOutputColorNumber = maxDrawBuffers;
|
||||||
|
}
|
||||||
Int GetFragmentDataLocation(const char* name);
|
Int GetFragmentDataLocation(const char* name);
|
||||||
|
|
||||||
Vector<SharedPtr<ShaderObject>>& GetAttachedShaders();
|
Vector<SharedPtr<ShaderObject>>& GetAttachedShaders();
|
||||||
@@ -241,6 +244,7 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
void GenerateBinary();
|
void GenerateBinary();
|
||||||
void WaitUntilGenerationCompleted() const;
|
void WaitUntilGenerationCompleted() const;
|
||||||
void AddDefaultFragmentShaderIfMissing();
|
void AddDefaultFragmentShaderIfMissing();
|
||||||
|
Bool ValidateFragmentOutputLocations();
|
||||||
|
|
||||||
const Uint m_externalIndex = 0;
|
const Uint m_externalIndex = 0;
|
||||||
Vector<SharedPtr<ShaderObject>> m_shaders;
|
Vector<SharedPtr<ShaderObject>> m_shaders;
|
||||||
@@ -258,6 +262,7 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
// FragData (Frag out)
|
// FragData (Frag out)
|
||||||
UnorderedMap<String, Uint> m_explicitFragDataLocation;
|
UnorderedMap<String, Uint> m_explicitFragDataLocation;
|
||||||
UnorderedMap<String, Uint> m_linkedFragDataLocation;
|
UnorderedMap<String, Uint> m_linkedFragDataLocation;
|
||||||
|
Int m_maxFragmentOutputColorNumber = 8;
|
||||||
|
|
||||||
// Uniforms
|
// Uniforms
|
||||||
UnorderedMap<String, Uint> m_uniformLocations;
|
UnorderedMap<String, Uint> m_uniformLocations;
|
||||||
|
|||||||
Reference in New Issue
Block a user