mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 04:38:30 +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();
|
||||
allowVSOnlyPrograms = (Int)rendererInfo.StaticBackendCapability.AllowVSOnlyPrograms;
|
||||
}
|
||||
const auto& activeBackendObject = MG_Backend::pActiveBackendObject;
|
||||
if (activeBackendObject) {
|
||||
programObject->SetMaxFragmentOutputColorNumber(activeBackendObject->GetDynamicParameters().MaxDrawBuffers);
|
||||
}
|
||||
programObject->Link(!allowVSOnlyPrograms);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,11 @@ void main() {}
|
||||
)";
|
||||
|
||||
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) {
|
||||
switch (glType) {
|
||||
case GL_FLOAT_MAT2:
|
||||
@@ -225,6 +230,9 @@ namespace MobileGL::MG_State::GLState {
|
||||
MGLOG_D("ProgramObject %u: Starting reflection", m_externalIndex);
|
||||
DoReflection();
|
||||
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);
|
||||
GenerateBinary();
|
||||
@@ -590,6 +598,43 @@ namespace MobileGL::MG_State::GLState {
|
||||
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) {
|
||||
if (!m_program || !name) return -1;
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace MobileGL::MG_State::GLState {
|
||||
|
||||
void SetExplicitVertexInLocation(Uint index, const char* name);
|
||||
void SetExplicitFragmentOutLocation(Uint index, const char* name);
|
||||
void SetMaxFragmentOutputColorNumber(Int maxDrawBuffers) {
|
||||
m_maxFragmentOutputColorNumber = maxDrawBuffers;
|
||||
}
|
||||
Int GetFragmentDataLocation(const char* name);
|
||||
|
||||
Vector<SharedPtr<ShaderObject>>& GetAttachedShaders();
|
||||
@@ -241,6 +244,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
void GenerateBinary();
|
||||
void WaitUntilGenerationCompleted() const;
|
||||
void AddDefaultFragmentShaderIfMissing();
|
||||
Bool ValidateFragmentOutputLocations();
|
||||
|
||||
const Uint m_externalIndex = 0;
|
||||
Vector<SharedPtr<ShaderObject>> m_shaders;
|
||||
@@ -258,6 +262,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
// FragData (Frag out)
|
||||
UnorderedMap<String, Uint> m_explicitFragDataLocation;
|
||||
UnorderedMap<String, Uint> m_linkedFragDataLocation;
|
||||
Int m_maxFragmentOutputColorNumber = 8;
|
||||
|
||||
// Uniforms
|
||||
UnorderedMap<String, Uint> m_uniformLocations;
|
||||
|
||||
Reference in New Issue
Block a user