gallium: refactor pipe_shader_state to support multiple IR's
authorRob Clark <robdclark@gmail.com>
Sat, 17 Oct 2015 17:34:24 +0000 (13:34 -0400)
committerRob Clark <robclark@freedesktop.org>
Wed, 11 May 2016 16:20:11 +0000 (12:20 -0400)
The goal is to allow the pipe driver to request something other than
TGSI, but detect whether what is getting is TGSI vs what it requested.
The pipe drivers will always have to support TGSI (and convert that into
whatever it is that they prefer), but in some cases we should be able to
skip the TGSI intermediate step (such as glsl->nir vs glsl->tgsi->nir).

I think pipe_compute_state should get similar treatment.  Currently,
afaict, it has one user and one consumer, which has allowed it to be
sloppy wrt. supporting alternative IR's.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/auxiliary/hud/hud_context.c
src/gallium/auxiliary/postprocess/pp_run.c
src/gallium/auxiliary/tgsi/tgsi_ureg.c
src/gallium/auxiliary/util/u_simple_shaders.c
src/gallium/auxiliary/util/u_tests.c
src/gallium/include/pipe/p_defines.h
src/gallium/include/pipe/p_state.h

index 146c7ccd5e360832153be80fc251d81c41614f66..7870da5464a33ad245d1deae392239d2f2a4cce8 100644 (file)
@@ -1202,7 +1202,7 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso)
       };
 
       struct tgsi_token tokens[1000];
-      struct pipe_shader_state state = {tokens};
+      struct pipe_shader_state state;
 
       if (!tgsi_text_translate(fragment_shader_text, tokens, ARRAY_SIZE(tokens))) {
          assert(0);
@@ -1211,7 +1211,7 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso)
          FREE(hud);
          return NULL;
       }
-
+      pipe_shader_state_from_tgsi(&state, tokens);
       hud->fs_text = pipe->create_fs_state(pipe, &state);
    }
 
@@ -1249,8 +1249,7 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso)
       };
 
       struct tgsi_token tokens[1000];
-      struct pipe_shader_state state = {tokens};
-
+      struct pipe_shader_state state;
       if (!tgsi_text_translate(vertex_shader_text, tokens, ARRAY_SIZE(tokens))) {
          assert(0);
          pipe_resource_reference(&hud->font.texture, NULL);
@@ -1258,7 +1257,7 @@ hud_create(struct pipe_context *pipe, struct cso_context *cso)
          FREE(hud);
          return NULL;
       }
-
+      pipe_shader_state_from_tgsi(&state, tokens);
       hud->vs = pipe->create_vs_state(pipe, &state);
    }
 
index bc79c5aab6e2ba838b731ab389060f3053e445b6..41fa7ed69e693c4cf8a68f9cd83afd339dfc0ac3 100644 (file)
@@ -255,8 +255,7 @@ pp_tgsi_to_state(struct pipe_context *pipe, const char *text, bool isvs,
       return NULL;
    }
 
-   state.tokens = tokens;
-   memset(&state.stream_output, 0, sizeof(state.stream_output));
+   pipe_shader_state_from_tgsi(&state, tokens);
 
    if (isvs) {
       ret_state = pipe->create_vs_state(pipe, &state);
index 43b8bb10f1cf39e83d5bcc8f10023f2804aac040..b67c383eb3811838b2fb77592e32a119740ee6e0 100644 (file)
@@ -2019,14 +2019,12 @@ void *ureg_create_shader( struct ureg_program *ureg,
 {
    struct pipe_shader_state state;
 
-   state.tokens = ureg_finalize(ureg);
+   pipe_shader_state_from_tgsi(&state, ureg_finalize(ureg));
    if(!state.tokens)
       return NULL;
 
    if (so)
       state.stream_output = *so;
-   else
-      memset(&state.stream_output, 0, sizeof(state.stream_output));
 
    switch (ureg->processor) {
    case PIPE_SHADER_VERTEX:
index 5b5c8512470af0fe5ec33f76d4b2f0933001899e..1220e187eac861850dc63034c2a3eb47d8828758 100644 (file)
@@ -121,12 +121,13 @@ void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe)
          "MOV OUT[2], SV[0]\n"
          "END\n";
    struct tgsi_token tokens[1000];
-   struct pipe_shader_state state = {tokens};
+   struct pipe_shader_state state;
 
    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
       assert(0);
       return NULL;
    }
+   pipe_shader_state_from_tgsi(&state, tokens);
    return pipe->create_vs_state(pipe, &state);
 }
 
@@ -149,12 +150,13 @@ void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe)
          "MOV OUT[2].x, SV[0].xxxx\n"
          "END\n";
    struct tgsi_token tokens[1000];
-   struct pipe_shader_state state = {tokens};
+   struct pipe_shader_state state;
 
    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
       assert(0);
       return NULL;
    }
+   pipe_shader_state_from_tgsi(&state, tokens);
    return pipe->create_vs_state(pipe, &state);
 }
 
@@ -192,12 +194,13 @@ void *util_make_layered_clear_geometry_shader(struct pipe_context *pipe)
       "EMIT IMM[0].xxxx\n"
       "END\n";
    struct tgsi_token tokens[1000];
-   struct pipe_shader_state state = {tokens};
+   struct pipe_shader_state state;
 
    if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
       assert(0);
       return NULL;
    }
+   pipe_shader_state_from_tgsi(&state, tokens);
    return pipe->create_gs_state(pipe, &state);
 }
 
@@ -471,7 +474,7 @@ util_make_fragment_passthrough_shader(struct pipe_context *pipe,
 
    char text[sizeof(shader_templ)+100];
    struct tgsi_token tokens[1000];
-   struct pipe_shader_state state = {tokens};
+   struct pipe_shader_state state;
 
    sprintf(text, shader_templ,
            write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
@@ -482,6 +485,7 @@ util_make_fragment_passthrough_shader(struct pipe_context *pipe,
       assert(0);
       return NULL;
    }
+   pipe_shader_state_from_tgsi(&state, tokens);
 #if 0
    tgsi_dump(state.tokens, 0);
 #endif
@@ -558,7 +562,7 @@ util_make_fs_blit_msaa_gen(struct pipe_context *pipe,
    const char *type = tgsi_texture_names[tgsi_tex];
    char text[sizeof(shader_templ)+100];
    struct tgsi_token tokens[1000];
-   struct pipe_shader_state state = {tokens};
+   struct pipe_shader_state state;
 
    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
@@ -571,6 +575,7 @@ util_make_fs_blit_msaa_gen(struct pipe_context *pipe,
       assert(0);
       return NULL;
    }
+   pipe_shader_state_from_tgsi(&state, tokens);
 #if 0
    tgsi_dump(state.tokens, 0);
 #endif
@@ -659,7 +664,7 @@ util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
    const char *type = tgsi_texture_names[tgsi_tex];
    char text[sizeof(shader_templ)+100];
    struct tgsi_token tokens[1000];
-   struct pipe_shader_state state = {tokens};
+   struct pipe_shader_state state;
 
    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
@@ -670,6 +675,7 @@ util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
       assert(0);
       return NULL;
    }
+   pipe_shader_state_from_tgsi(&state, tokens);
 #if 0
    tgsi_dump(state.tokens, 0);
 #endif
index 52102900cdaf0800870b703d98885c420b2c0961..f22ffceb6bc53232f491f5c904e0744d7a8f6cf6 100644 (file)
@@ -422,13 +422,14 @@ null_constant_buffer(struct pipe_context *ctx)
             "MOV OUT[0], CONST[0]\n"
             "END\n";
       struct tgsi_token tokens[1000];
-      struct pipe_shader_state state = {tokens};
+      struct pipe_shader_state state;
 
       if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
          puts("Can't compile a fragment shader.");
          util_report_result(FAIL);
          return;
       }
+      pipe_shader_state_from_tgsi(&state, tokens);
       fs = ctx->create_fs_state(ctx, &state);
       cso_set_fragment_shader_handle(cso, fs);
    }
index bd02a79f19cf38e61069b69218ff07ef6ec6adef..2f481091858dd13f9fc43e980025d9f8bee0c512 100644 (file)
@@ -799,12 +799,20 @@ enum pipe_shader_cap
 
 /**
  * Shader intermediate representation.
+ *
+ * Note that if the driver requests something other than TGSI, it must
+ * always be prepared to receive TGSI in addition to its preferred IR.
+ * If the driver requests TGSI as its preferred IR, it will *always*
+ * get TGSI.
+ *
+ * Note that PIPE_SHADER_IR_TGSI should be zero for backwards compat with
+ * state trackers that only understand TGSI.
  */
 enum pipe_shader_ir
 {
-   PIPE_SHADER_IR_TGSI,
+   PIPE_SHADER_IR_TGSI = 0,
    PIPE_SHADER_IR_LLVM,
-   PIPE_SHADER_IR_NATIVE
+   PIPE_SHADER_IR_NATIVE,
 };
 
 /**
index 9e466cefd8ceb0e18f93e90e69ed27176676cece..3f14e41dff1a0e961fd1ff915c42ba621916f4f0 100644 (file)
@@ -211,13 +211,37 @@ struct pipe_stream_output_info
    } output[PIPE_MAX_SO_OUTPUTS];
 };
 
-
+/**
+ * The 'type' parameter identifies whether the shader state contains TGSI
+ * tokens, etc.  If the driver returns 'PIPE_SHADER_IR_TGSI' for the
+ * 'PIPE_SHADER_CAP_PREFERRED_IR' shader param, the ir will *always* be
+ * 'PIPE_SHADER_IR_TGSI' and the tokens ptr will be valid.  If the driver
+ * requests a different 'pipe_shader_ir' type, then it must check the 'type'
+ * enum to see if it is getting TGSI tokens or its preferred IR.
+ *
+ * TODO pipe_compute_state should probably get similar treatment to handle
+ * multiple IR's in a cleaner way..
+ */
 struct pipe_shader_state
 {
+   enum pipe_shader_ir type;
+   /* TODO move tokens into union. */
    const struct tgsi_token *tokens;
+   union {
+      void *llvm;
+      void *native;
+   } ir;
    struct pipe_stream_output_info stream_output;
 };
 
+static inline void
+pipe_shader_state_from_tgsi(struct pipe_shader_state *state,
+                            const struct tgsi_token *tokens)
+{
+   state->type = PIPE_SHADER_IR_TGSI;
+   state->tokens = tokens;
+   memset(&state->stream_output, 0, sizeof(state->stream_output));
+}
 
 struct pipe_depth_state
 {