mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (GL): leave the injected default fragment stage out of program pipeline validation
This commit is contained in:
@@ -124,6 +124,17 @@ namespace MobileGL::MG_State::GLState {
|
||||
return ref.shader && ref.shader->GetShaderStage() == stage;
|
||||
});
|
||||
}
|
||||
// HasLinkedShaderStage without the default fragment shader Link() adds to a vertex-only
|
||||
// program on a backend that cannot run one (AddDefaultFragmentShaderIfMissing; its shader
|
||||
// object has no name). That stage is MobileGL's, not the application's, so it is not one
|
||||
// the GL rules about "the stages present when the program was linked" may count.
|
||||
Bool HasApplicationLinkedShaderStage(ShaderStage stage) const {
|
||||
return std::any_of(m_linkedShaderSnapshot.begin(), m_linkedShaderSnapshot.end(),
|
||||
[stage](const LinkedShaderRef& ref) {
|
||||
return ref.shader && ref.shader->GetShaderStage() == stage &&
|
||||
ref.shader->GetExternalIndex() != 0;
|
||||
});
|
||||
}
|
||||
// The stage of each module of GetGeneratedSpirv(), at the SAME index and with the same
|
||||
// size: phase B emits exactly one module per entry of the snapshot above, in that order
|
||||
// (Link() fills ProgramLinkTask::in.shaders from the snapshot loop, phase A copies the
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace MobileGL {
|
||||
// "A program object is active for at least one, but not all of the shader
|
||||
// stages that were present when the program was linked."
|
||||
for (SizeT other = 0; other < kStageCount; ++other) {
|
||||
if (program->HasLinkedShaderStage(static_cast<ShaderStage>(other)) &&
|
||||
if (program->HasApplicationLinkedShaderStage(static_cast<ShaderStage>(other)) &&
|
||||
m_stagePrograms[other] != program) {
|
||||
return std::format("A program is active for stage {} but not for its linked stage {}.",
|
||||
stage, other);
|
||||
|
||||
@@ -673,6 +673,47 @@ void main() { gl_Position = vec4(0.0); }
|
||||
}
|
||||
}
|
||||
|
||||
// KHR-GL4x.geometry_shader.api.program_pipeline_vs_gs_capture: a vertex-only separable program
|
||||
// and a geometry-only one. Link() gives the vertex-only program MobileGL's default fragment shader
|
||||
// (neither backend runs a vertex-only program), and the "active for some but not all of its linked
|
||||
// stages" rule must not count that stage, or every such pipeline fails validation and its draws.
|
||||
TEST_F(ProgramPipelineCompositeTest, AVertexOnlyStageProgramValidatesWithoutAFragmentStage) {
|
||||
const char* kVs = R"(#version 430 core
|
||||
out gl_PerVertex { vec4 gl_Position; };
|
||||
flat out int vertexID;
|
||||
void main() { vertexID = gl_VertexID; gl_Position = vec4(0.0); }
|
||||
)";
|
||||
const char* kGs = R"(#version 430 core
|
||||
in gl_PerVertex { vec4 gl_Position; } gl_in[];
|
||||
out gl_PerVertex { vec4 gl_Position; };
|
||||
layout(points) in;
|
||||
layout(points, max_vertices = 1) out;
|
||||
flat in int vertexID[];
|
||||
out vec4 color;
|
||||
void main() { color = vec4(vertexID[0]); gl_Position = vec4(0.0); EmitVertex(); }
|
||||
)";
|
||||
const GLuint vs = MakeSeparableProgram(GL_VERTEX_SHADER, kVs);
|
||||
const GLuint gs = MakeSeparableProgram(GL_GEOMETRY_SHADER, kGs);
|
||||
|
||||
GLuint pipeline = 0;
|
||||
GenProgramPipelines(1, &pipeline);
|
||||
UseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vs);
|
||||
UseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT, gs);
|
||||
BindProgramPipeline(pipeline);
|
||||
ValidateProgramPipeline(pipeline);
|
||||
GLint status = -1;
|
||||
GetProgramPipelineiv(pipeline, GL_VALIDATE_STATUS, &status);
|
||||
EXPECT_EQ(status, GL_TRUE);
|
||||
ASSERT_EQ(GetError(), GL_NO_ERROR);
|
||||
DrawArrays(GL_POINTS, 0, 1);
|
||||
EXPECT_EQ(GetError(), GL_NO_ERROR) << "a draw through the valid pipeline";
|
||||
|
||||
BindProgramPipeline(0);
|
||||
DeleteProgramPipelines(1, &pipeline);
|
||||
for (Int drained = 0; drained < 16 && GetError() != GL_NO_ERROR; ++drained) {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
// The composite's transform-feedback capture list.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user