st/mesa: add a fallback for clear_with_quad when no vs_layer
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>
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c
index 0eeb7d9..edb3037 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.c
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -130,6 +130,76 @@
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:
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h
index 2ba3f2a..dd282e0 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.h
+++ b/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -62,6 +62,12 @@
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,
unsigned interp_mode,
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index 3a359f3..45dea59 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -88,6 +88,14 @@
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 @@
}
cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
+ cso_set_geometry_shader_handle(st->cso_context, NULL);
}
@@ -136,18 +145,25 @@
{
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 @@
}
set_fragment_shader(st);
- cso_set_geometry_shader_handle(st->cso_context, NULL);
if (num_layers > 1)
set_vertex_shader_layered(st);
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 58f14f9..15f9df4 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -181,6 +181,7 @@
void *vs;
void *fs;
void *vs_layered;
+ void *gs_layered;
} clear;
/** used for anything using util_draw_vertex_buffer */