mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (GL): answer one for the name-length program queries of a program linked from SPIR-V
This commit is contained in:
@@ -893,8 +893,11 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
*params = programObject->GetActiveAttributesCount();
|
||||
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
|
||||
break;
|
||||
// GL 4.6 core 7.13: "If no name reflection information is available, one is returned" -
|
||||
// the case for every program linked from SPIR-V (see ProgramObject::GetLinkedFromSpirv),
|
||||
// for this and the three other name-length queries below.
|
||||
case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
|
||||
*params = programObject->GetActiveAttributesMaxLength() + 1;
|
||||
*params = programObject->GetLinkedFromSpirv() ? 1 : programObject->GetActiveAttributesMaxLength() + 1;
|
||||
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
|
||||
break;
|
||||
case GL_ACTIVE_UNIFORMS:
|
||||
@@ -902,7 +905,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
|
||||
break;
|
||||
case GL_ACTIVE_UNIFORM_MAX_LENGTH:
|
||||
*params = programObject->GetUniformMaxLength() + 1;
|
||||
*params = programObject->GetLinkedFromSpirv() ? 1 : programObject->GetUniformMaxLength() + 1;
|
||||
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
|
||||
break;
|
||||
case GL_ACTIVE_UNIFORM_BLOCKS: // GL >= 3.1
|
||||
@@ -912,7 +915,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
|
||||
break;
|
||||
case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: // ditto.
|
||||
*params = programObject->GetActiveUniformBlocksMaxNameLength() + 1;
|
||||
*params =
|
||||
programObject->GetLinkedFromSpirv() ? 1 : programObject->GetActiveUniformBlocksMaxNameLength() + 1;
|
||||
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
|
||||
break;
|
||||
case GL_TRANSFORM_FEEDBACK_VARYINGS:
|
||||
@@ -924,7 +928,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
|
||||
break;
|
||||
case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
|
||||
*params = programObject->GetTransformFeedbackVaryingMaxLength();
|
||||
*params = programObject->GetLinkedFromSpirv() ? 1 : programObject->GetTransformFeedbackVaryingMaxLength();
|
||||
MGLOG_D("%s: %s = %d", __func__, MG_Util::ConvertGLEnumToString(pname).c_str(), *params);
|
||||
break;
|
||||
case GL_COMPUTE_WORK_GROUP_SIZE: { // GL >= 4.3
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "ProgramObject.h"
|
||||
#include "ProgramLinkTask.h"
|
||||
#include "ProgramSpirvTask.h"
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <MG_Util/Async/ShaderCompilePool.h>
|
||||
@@ -587,6 +588,8 @@ namespace MobileGL::MG_State::GLState {
|
||||
RemoveShader(detachedShader);
|
||||
}
|
||||
m_detachedShaders.clear();
|
||||
m_linkedFromSpirv = std::any_of(m_shaders.begin(), m_shaders.end(),
|
||||
[](const SharedPtr<ShaderObject>& shader) { return shader->HasSpirvBinary(); });
|
||||
|
||||
if (addDefaultFSIfMissingForRenderingPipelineProgram) {
|
||||
AddDefaultFragmentShaderIfMissing();
|
||||
|
||||
@@ -913,6 +913,11 @@ namespace MobileGL::MG_State::GLState {
|
||||
// assert. The live flag stays available as GetSeparable() for glGetProgramiv's sibling
|
||||
// state and for the next link to latch.
|
||||
Bool GetLinkedSeparable() const { return m_linkedSeparable; }
|
||||
// Whether the last link consumed SPIR-V modules (ARB_gl_spirv; mixing them with GLSL
|
||||
// shaders fails the link). Such a program carries no name reflection - OpName is
|
||||
// optional debug information, and the names the translation invents are not the
|
||||
// application's - so GL 4.6 core 7.13's name-length queries answer one for it.
|
||||
Bool GetLinkedFromSpirv() const { return m_linkedFromSpirv; }
|
||||
void SetSeparable(Bool separable) {
|
||||
m_separable = separable;
|
||||
// ---- arming the uniform-write tracking latch ----
|
||||
@@ -1438,6 +1443,8 @@ namespace MobileGL::MG_State::GLState {
|
||||
// not a result the worker computes - and because a FAILED link still latches it, exactly
|
||||
// as a successful one does.
|
||||
Bool m_linkedSeparable = false;
|
||||
// See GetLinkedFromSpirv; latched by Link() alongside m_linkedSeparable.
|
||||
Bool m_linkedFromSpirv = false;
|
||||
// Monotone "this program may ever be a pipeline stage" latch; see SetSeparable for why
|
||||
// it is a latch and not just m_separable. Outside LinkArtifacts on purpose: a relink
|
||||
// clears the write SET, but a program that was separable is still separable after it.
|
||||
|
||||
@@ -5077,6 +5077,54 @@ TEST_F(ProgramTest, ShaderSourceClearsTheSpecializedLatch) {
|
||||
DrainProgramTestErrors();
|
||||
}
|
||||
|
||||
// GL 4.6 core 7.13: a program with no name reflection - every program linked from SPIR-V - answers
|
||||
// the four name-length queries with one (KHR-GL46.gl_spirv.spirv_modules_state_queries_test), while
|
||||
// the same interface linked from GLSL keeps reporting its real longest name.
|
||||
TEST_F(ProgramTest, ASpirvProgramReportsNoNameReflection) {
|
||||
DrainProgramTestErrors();
|
||||
|
||||
const auto linkWith = [](GLuint shader) {
|
||||
const GLuint program = CreateProgram();
|
||||
AttachShader(program, shader);
|
||||
LinkProgram(program);
|
||||
GLint linked = GL_FALSE;
|
||||
GetProgramiv(program, GL_LINK_STATUS, &linked);
|
||||
EXPECT_EQ(linked, GL_TRUE);
|
||||
return program;
|
||||
};
|
||||
|
||||
const GLuint spirvShader = CreateShader(GL_VERTEX_SHADER);
|
||||
ShaderBinary(1, &spirvShader, GL_SHADER_BINARY_FORMAT_SPIR_V, kVertexModule, sizeof(kVertexModule));
|
||||
SpecializeShader(spirvShader, "main", 0, nullptr, nullptr);
|
||||
ASSERT_EQ(GetError(), GL_NO_ERROR);
|
||||
const GLuint spirvProgram = linkWith(spirvShader);
|
||||
|
||||
const GLuint glslShader = CreateShader(GL_VERTEX_SHADER);
|
||||
const char* source = "#version 450 core\nlayout(location = 0) in vec2 aPos;\n"
|
||||
"void main() { gl_Position = vec4(aPos, 0.0, 1.0); }\n";
|
||||
ShaderSource(glslShader, 1, &source, nullptr);
|
||||
CompileShader(glslShader);
|
||||
const GLuint glslProgram = linkWith(glslShader);
|
||||
ASSERT_EQ(GetError(), GL_NO_ERROR);
|
||||
|
||||
for (const GLenum pname : {GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, GL_ACTIVE_UNIFORM_MAX_LENGTH,
|
||||
GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH}) {
|
||||
GLint length = -1;
|
||||
GetProgramiv(spirvProgram, pname, &length);
|
||||
EXPECT_EQ(GetError(), GL_NO_ERROR);
|
||||
EXPECT_EQ(length, 1) << "pname 0x" << std::hex << pname;
|
||||
}
|
||||
GLint glslLength = -1;
|
||||
GetProgramiv(glslProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &glslLength);
|
||||
EXPECT_EQ(glslLength, static_cast<GLint>(sizeof("aPos")));
|
||||
|
||||
DeleteProgram(spirvProgram);
|
||||
DeleteProgram(glslProgram);
|
||||
DeleteShader(spirvShader);
|
||||
DeleteShader(glslShader);
|
||||
DrainProgramTestErrors();
|
||||
}
|
||||
|
||||
// A shader that came from glShaderBinary has never had glShaderSource called on it, so GL 4.6
|
||||
// core 7.1 makes its source the empty string - including AFTER glSpecializeShader, when the
|
||||
// object internally holds the GLSL the module was translated into. That text is MobileGL's, not
|
||||
|
||||
Reference in New Issue
Block a user