On Sat, Nov 15, 2014 at 1:38 PM, Ilia Mirkin <imir...@alum.mit.edu> wrote: > 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 <imir...@alum.mit.edu> > Cc: "10.3 10.4" <mesa-sta...@lists.freedesktop.org> > --- > > No explicit piglit test hits this path without the above hacks, so it went > under the radar for a long time. I tested this on nvc0 with the above hacks, > and double-checked that without them, things still worked.
Fun fact -- llvmpipe also needs this. > > src/gallium/auxiliary/util/u_simple_shaders.c | 70 > +++++++++++++++++++++++++++ > src/gallium/auxiliary/util/u_simple_shaders.h | 6 +++ > src/mesa/state_tracker/st_cb_clear.c | 25 ++++++++-- > 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 adf4887..2cf528b 100644 > --- a/src/gallium/auxiliary/util/u_simple_shaders.c > +++ b/src/gallium/auxiliary/util/u_simple_shaders.c > @@ -124,6 +124,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 c1d14aa..b467b9f5 100644 > --- a/src/gallium/auxiliary/util/u_simple_shaders.h > +++ b/src/gallium/auxiliary/util/u_simple_shaders.h > @@ -60,6 +60,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 2c1414e..e778556 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; > + } > } > > > @@ -127,6 +135,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); > } > > > @@ -135,18 +144,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); > } > > > @@ -332,7 +348,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 58f14f9..15f9df4 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 */ > -- > 2.0.4 > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev