[Mesa-dev,12/18] glsl: Can't emit vertices to non-zero streams with output != GL_POINTS.

Submitted by Iago Toral Quiroga on June 11, 2014, 7:49 a.m.

Details

Message ID 1402472981-22428-13-git-send-email-itoral@igalia.com
State Superseded
Headers show

Not browsing as part of any series.

Commit Message

Iago Toral Quiroga June 11, 2014, 7:49 a.m.
From the ARB_gpu_shader5 spec:

  "Multiple vertex streams are supported only if the output primitive
   type is declared to be "points".  A program will fail to link if it
   contains a geometry shader calling EmitStreamVertex() or
   EndStreamPrimitive() if its output primitive type is not "points".

However, since EmitVertex() == EmitStreamVertex(0) and
EndPrimitive() == EmitEndPrimitive(0), we only fail to link if these
functions are called with a non-zero stream. This is also what Nvidia does.
---
 src/glsl/linker.cpp | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

Patch hide | download patch | download mbox

diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 7ff7694..0c42823 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -554,6 +554,35 @@  validate_geometry_shader_executable(struct gl_shader_program *prog,
    find_end_primitive_visitor end_primitive;
    end_primitive.run(shader->ir);
    prog->Geom.UsesEndPrimitive = end_primitive.end_primitive_found();
+
+   /* From the ARB_gpu_shader5 spec:
+    *
+    *   "Multiple vertex streams are supported only if the output primitive
+    *    type is declared to be "points".  A program will fail to link if it
+    *    contains a geometry shader calling EmitStreamVertex() or
+    *    EndStreamPrimitive() if its output primitive type is not "points".
+    *
+    * However, in the same spec:
+    *
+    *   "The function EmitVertex() is equivalent to calling EmitStreamVertex()
+    *    with <stream> set to zero."
+    *
+    * And:
+    *
+    *   "The function EndPrimitive() is equivalent to calling
+    *    EndStreamPrimitive() with <stream> set to zero."
+    *
+    * Since we can call EmitVertex() and EndPrimitive() when we output
+    * primitives other than points, calling EmitStreamVertex(0) or
+    * EmitEndPrimitive(0) should not produce errors. This it also what Nvidia
+    * does. Currently we only set prog->Geom.UsesStreams to TRUE when
+    * EmitStreamVertex() or EmitEndPrimitive() are called with a non-zero
+    * stream.
+    */
+   if (prog->Geom.UsesStreams && prog->Geom.OutputType != GL_POINTS) {
+      linker_error(prog,  "EmitStreamVertex(n) and EndStreamPrimitive(n) "
+                   "with n>0 requires point output");
+   }
 }