diff options
author | Ilia Mirkin <[email protected]> | 2014-11-15 13:29:25 -0500 |
---|---|---|
committer | Ilia Mirkin <[email protected]> | 2014-11-17 22:17:49 -0500 |
commit | 68db29c434e144891e5990b032b44495de52f6eb (patch) | |
tree | 1aeda9293c643f2dc47a3194199b3d877e512866 | |
parent | 7b8e04b3f0b66bda84cb1ab4f89239f357d9cb64 (diff) |
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 <[email protected]>
Reviewed-by: Marek Olšák <[email protected]>
Cc: "10.4 10.3" <[email protected]>
-rw-r--r-- | src/gallium/auxiliary/util/u_simple_shaders.c | 70 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_simple_shaders.h | 6 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_clear.c | 25 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_context.h | 1 |
4 files changed, 97 insertions, 5 deletions
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index 0eeb7d99173..edb30379b31 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -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: diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h index 2ba3f2a9ab3..dd282e02a13 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.h +++ b/src/gallium/auxiliary/util/u_simple_shaders.h @@ -62,6 +62,12 @@ 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, unsigned interp_mode, diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 3a359f31885..45dea594ee7 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -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); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 58f14f954dc..15f9df492db 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -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 */ |