st/mesa: add a fallback for clear_with_quad when no vs_layer
authorIlia Mirkin <imirkin@alum.mit.edu>
Sat, 15 Nov 2014 18:29:25 +0000 (13:29 -0500)
committerIlia Mirkin <imirkin@alum.mit.edu>
Tue, 18 Nov 2014 03:17:49 +0000 (22:17 -0500)
Not all drivers can set gl_Layer from VS. Add a fallback that passes the
instance id from VS to GS, and then uses the GS to set the layer.

Tested by adding

  quad_buffers |= clear_buffers;
  clear_buffers = 0;

to the st_Clear logic, and forcing set_vertex_shader_layered in all
cases. No piglit regressions (on piglits with 'clear' in the name).

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Cc: "10.4 10.3" <mesa-stable@lists.freedesktop.org>
src/gallium/auxiliary/util/u_simple_shaders.c
src/gallium/auxiliary/util/u_simple_shaders.h
src/mesa/state_tracker/st_cb_clear.c
src/mesa/state_tracker/st_context.h

index 0eeb7d9917356783f3288c19daf8c66ce2673739..edb30379b31a7823a2e1cf2a441a0de5855344c3 100644 (file)
@@ -130,6 +130,76 @@ void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe)
    return pipe->create_vs_state(pipe, &state);
 }
 
+/**
+ * Takes position and color, and outputs position, color, and instance id.
+ */
+void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe)
+{
+   static const char text[] =
+         "VERT\n"
+         "DCL IN[0]\n"
+         "DCL IN[1]\n"
+         "DCL SV[0], INSTANCEID\n"
+         "DCL OUT[0], POSITION\n"
+         "DCL OUT[1], GENERIC[0]\n"
+         "DCL OUT[2], GENERIC[1]\n"
+
+         "MOV OUT[0], IN[0]\n"
+         "MOV OUT[1], IN[1]\n"
+         "MOV OUT[2].x, SV[0].xxxx\n"
+         "END\n";
+   struct tgsi_token tokens[1000];
+   struct pipe_shader_state state = {tokens};
+
+   if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
+      assert(0);
+      return NULL;
+   }
+   return pipe->create_vs_state(pipe, &state);
+}
+
+/**
+ * Takes position, color, and target layer, and emits vertices on that target
+ * layer, with the specified color.
+ */
+void *util_make_layered_clear_geometry_shader(struct pipe_context *pipe)
+{
+   static const char text[] =
+      "GEOM\n"
+      "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n"
+      "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n"
+      "PROPERTY GS_MAX_OUTPUT_VERTICES 3\n"
+      "PROPERTY GS_INVOCATIONS 1\n"
+      "DCL IN[][0], POSITION\n" /* position */
+      "DCL IN[][1], GENERIC[0]\n" /* color */
+      "DCL IN[][2], GENERIC[1]\n" /* vs invocation */
+      "DCL OUT[0], POSITION\n"
+      "DCL OUT[1], GENERIC[0]\n"
+      "DCL OUT[2], LAYER\n"
+      "IMM[0] INT32 {0, 0, 0, 0}\n"
+
+      "MOV OUT[0], IN[0][0]\n"
+      "MOV OUT[1], IN[0][1]\n"
+      "MOV OUT[2].x, IN[0][2].xxxx\n"
+      "EMIT IMM[0].xxxx\n"
+      "MOV OUT[0], IN[1][0]\n"
+      "MOV OUT[1], IN[1][1]\n"
+      "MOV OUT[2].x, IN[1][2].xxxx\n"
+      "EMIT IMM[0].xxxx\n"
+      "MOV OUT[0], IN[2][0]\n"
+      "MOV OUT[1], IN[2][1]\n"
+      "MOV OUT[2].x, IN[2][2].xxxx\n"
+      "EMIT IMM[0].xxxx\n"
+      "END\n";
+   struct tgsi_token tokens[1000];
+   struct pipe_shader_state state = {tokens};
+
+   if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
+      assert(0);
+      return NULL;
+   }
+   return pipe->create_gs_state(pipe, &state);
+}
 
 /**
  * Make simple fragment texture shader:
index 2ba3f2a9ab394d634309dba66ef23b956514a6e4..dd282e02a13fa3fe1f16a9b0b28b3d45d299fc73 100644 (file)
@@ -61,6 +61,12 @@ util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
 extern void *
 util_make_layered_clear_vertex_shader(struct pipe_context *pipe);
 
+extern void *
+util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe);
+
+extern void *
+util_make_layered_clear_geometry_shader(struct pipe_context *pipe);
+
 extern void *
 util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, 
                                         unsigned tex_target,
index 3a359f318855befb5c6c7e04d0930415b03b2f5e..45dea594ee7b47a9b04d7be10348ce7718f63544 100644 (file)
@@ -88,6 +88,14 @@ st_destroy_clear(struct st_context *st)
       cso_delete_vertex_shader(st->cso_context, st->clear.vs);
       st->clear.vs = NULL;
    }
+   if (st->clear.vs_layered) {
+      cso_delete_vertex_shader(st->cso_context, st->clear.vs_layered);
+      st->clear.vs_layered = NULL;
+   }
+   if (st->clear.gs_layered) {
+      cso_delete_geometry_shader(st->cso_context, st->clear.gs_layered);
+      st->clear.gs_layered = NULL;
+   }
 }
 
 
@@ -128,6 +136,7 @@ set_vertex_shader(struct st_context *st)
    }
 
    cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
+   cso_set_geometry_shader_handle(st->cso_context, NULL);
 }
 
 
@@ -136,18 +145,25 @@ set_vertex_shader_layered(struct st_context *st)
 {
    struct pipe_context *pipe = st->pipe;
 
-   if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID) ||
-       !pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT)) {
-      assert(!"Got layered clear, but the VS layer output is unsupported");
+   if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID)) {
+      assert(!"Got layered clear, but VS instancing is unsupported");
       set_vertex_shader(st);
       return;
    }
 
    if (!st->clear.vs_layered) {
-      st->clear.vs_layered = util_make_layered_clear_vertex_shader(pipe);
+      bool vs_layer =
+         pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT);
+      if (vs_layer) {
+         st->clear.vs_layered = util_make_layered_clear_vertex_shader(pipe);
+      } else {
+         st->clear.vs_layered = util_make_layered_clear_helper_vertex_shader(pipe);
+         st->clear.gs_layered = util_make_layered_clear_geometry_shader(pipe);
+      }
    }
 
    cso_set_vertex_shader_handle(st->cso_context, st->clear.vs_layered);
+   cso_set_geometry_shader_handle(st->cso_context, st->clear.gs_layered);
 }
 
 
@@ -331,7 +347,6 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
    }
 
    set_fragment_shader(st);
-   cso_set_geometry_shader_handle(st->cso_context, NULL);
 
    if (num_layers > 1)
       set_vertex_shader_layered(st);
index 58f14f954dccc937b55c23c5e78fc8489ec1e0ee..15f9df492db71b5732a8d6ac02dbbd1bbddac204 100644 (file)
@@ -181,6 +181,7 @@ struct st_context
       void *vs;
       void *fs;
       void *vs_layered;
+      void *gs_layered;
    } clear;
 
    /** used for anything using util_draw_vertex_buffer */