mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 13:48:30 +09:00
[Fix] (ProgramLink): fail the link when a tessellation control stage declares more output vertices than GL_MAX_PATCH_VERTICES
This commit is contained in:
@@ -686,6 +686,38 @@ namespace MobileGL::MG_State::GLState {
|
||||
}
|
||||
}
|
||||
|
||||
// GL_TESS_CONTROL_OUTPUT_VERTICES, i.e. the `layout(vertices = N) out` the control stage
|
||||
// declared, and the limit that goes with it.
|
||||
//
|
||||
// GL 4.6 core 11.2.1.1: the LINK fails when N is greater than MAX_PATCH_VERTICES. Nothing
|
||||
// enforced it - glslang's layout handling only rejects N <= 0 (ParseHelper.cpp "must be
|
||||
// greater than 0") and carries maxPatchVertices in TBuiltInResource purely so
|
||||
// gl_MaxPatchVertices can expand from it, exactly the gap ValidateImageUniformLimits
|
||||
// documents for image uniforms. Checked at LINK rather than at compile on purpose: the CTS
|
||||
// requires the offending shader to COMPILE ("Compilation passed as allowed") and only the
|
||||
// link to fail, and turning it into a parse error would newly break an application that
|
||||
// compiles such a shader and never links it.
|
||||
//
|
||||
// The limit is the one glGetIntegerv answers (GL_Getter.cpp reads the same
|
||||
// DynamicBackendParameters field), so the advertised number and the enforced number cannot
|
||||
// drift apart.
|
||||
artifacts.tcsOutputVertices = 0;
|
||||
if (const glslang::TIntermediate* tcs = artifacts.program->getIntermediate(EShLangTessControl)) {
|
||||
artifacts.tcsOutputVertices = static_cast<Int>(tcs->getVertices());
|
||||
if (artifacts.tcsOutputVertices > env.params.MaxPatchVertices) {
|
||||
artifacts.linkStatus = false;
|
||||
// Same invariant as the compute local-size gate above: a rejected link leaves no
|
||||
// TProgram behind for a query surface to find.
|
||||
artifacts.program.reset();
|
||||
artifacts.infoLog = std::format(
|
||||
"Tessellation control shader declares an output patch of {} vertices, more than the {} "
|
||||
"GL_MAX_PATCH_VERTICES allows.",
|
||||
artifacts.tcsOutputVertices, env.params.MaxPatchVertices);
|
||||
DeferLog(std::format("ProgramObject {}: Link failed - {}", in.externalIndex, artifacts.infoLog));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- everything below this line up to GenerateSpirv() is the GL query surface ----
|
||||
//
|
||||
// ORDERING NOTE (rewritten 2026-08-10; the constraint it records was RETESTED, not
|
||||
|
||||
@@ -1317,6 +1317,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
Vector<Uint32> gsStripTriangles;
|
||||
Bool gsStripCaptureFixup = false;
|
||||
GLenum gsInputPrimitive = GL_NONE;
|
||||
// GL_TESS_CONTROL_OUTPUT_VERTICES: the `layout(vertices = N) out` of the linked
|
||||
// tessellation control stage, or 0 when the program has none. Checked against
|
||||
// GL_MAX_PATCH_VERTICES at link (GL 4.6 core 11.2.1.1).
|
||||
Int tcsOutputVertices = 0;
|
||||
GLenum xfbBufferMode = GL_INTERLEAVED_ATTRIBS;
|
||||
Int xfbVaryingNameMaxLength = 0;
|
||||
Bool xfbNeedsScatteredCapture = false;
|
||||
@@ -1501,6 +1505,10 @@ namespace MobileGL::MG_State::GLState {
|
||||
// GL_LINES_ADJACENCY, GL_TRIANGLES or GL_TRIANGLES_ADJACENCY), or GL_NONE when the
|
||||
// program has no geometry stage. Draws must present a compatible primitive type.
|
||||
GLenum GetGeometryInputType() const { return Artifacts().gsInputPrimitive; }
|
||||
// GL_TESS_CONTROL_OUTPUT_VERTICES of the linked tessellation control stage, or 0 when
|
||||
// the program has no such stage. Never greater than GL_MAX_PATCH_VERTICES: a program
|
||||
// that declared more does not link at all (GL 4.6 core 11.2.1.1).
|
||||
Int GetTessControlOutputVertices() const { return Artifacts().tcsOutputVertices; }
|
||||
|
||||
Uint GetExternalIndex() const { return m_externalIndex; }
|
||||
// Globally-unique, never-reused id for this program object's lifetime. Unlike the GL
|
||||
|
||||
Reference in New Issue
Block a user