[Mesa-dev] [PATCH 2/5] gallium/util: add _LZ and TXF options to simple shaders

Marek Olšák maraeo at gmail.com
Tue May 30 22:46:44 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

---
 src/gallium/auxiliary/util/u_blit.c           |  2 +-
 src/gallium/auxiliary/util/u_blitter.c        | 13 +++--
 src/gallium/auxiliary/util/u_simple_shaders.c | 70 +++++++++++++++++++--------
 src/gallium/auxiliary/util/u_simple_shaders.h | 20 ++++++--
 src/gallium/auxiliary/util/u_tests.c          |  2 +-
 src/gallium/tests/trivial/quad-tex.c          |  3 +-
 6 files changed, 77 insertions(+), 33 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index 6d8178e..3e49667 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -179,21 +179,21 @@ set_fragment_shader(struct blit_state *ctx, uint writemask,
 
    if (!ctx->fs[pipe_tex][writemask][idx]) {
       unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
 
       /* OpenGL does not allow blits from signed to unsigned integer
        * or vice versa. */
       ctx->fs[pipe_tex][writemask][idx] =
          util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex,
                                                  TGSI_INTERPOLATE_LINEAR,
                                                  writemask,
-                                                 stype, stype);
+                                                 stype, stype, false, false);
    }
 
    cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask][idx]);
 }
 
 
 /**
  * Helper function to set the vertex shader.
  */
 static inline void
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 13fa965..1aef013 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -945,21 +945,22 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
 
       return *shader;
    } else {
       void **shader = &ctx->fs_texfetch_col[type][target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
          assert(!ctx->cached_all_shaders);
          *shader = util_make_fragment_tex_shader(pipe, tgsi_tex,
                                                  TGSI_INTERPOLATE_LINEAR,
-                                                 stype, dtype);
+                                                 stype, dtype,
+                                                 false, false);
       }
 
       return *shader;
    }
 }
 
 static inline
 void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
                                     enum pipe_texture_target target,
                                     unsigned nr_samples)
@@ -983,21 +984,22 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
    } else {
       void **shader = &ctx->fs_texfetch_depth[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
          unsigned tgsi_tex;
          assert(!ctx->cached_all_shaders);
          tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
          *shader =
             util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
-                                                     TGSI_INTERPOLATE_LINEAR);
+                                                     TGSI_INTERPOLATE_LINEAR,
+                                                     false, false);
       }
 
       return *shader;
    }
 }
 
 static inline
 void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
                                            enum pipe_texture_target target,
                                            unsigned nr_samples)
@@ -1021,21 +1023,23 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
    } else {
       void **shader = &ctx->fs_texfetch_depthstencil[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
          unsigned tgsi_tex;
          assert(!ctx->cached_all_shaders);
          tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
          *shader =
             util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex,
-                                                     TGSI_INTERPOLATE_LINEAR);
+                                                            TGSI_INTERPOLATE_LINEAR,
+                                                            false,
+                                                            false);
       }
 
       return *shader;
    }
 }
 
 static inline
 void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
                                       enum pipe_texture_target target,
                                       unsigned nr_samples)
@@ -1059,21 +1063,22 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
    } else {
       void **shader = &ctx->fs_texfetch_stencil[target];
 
       /* Create the fragment shader on-demand. */
       if (!*shader) {
          unsigned tgsi_tex;
          assert(!ctx->cached_all_shaders);
          tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
          *shader =
             util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex,
-                                                       TGSI_INTERPOLATE_LINEAR);
+                                                       TGSI_INTERPOLATE_LINEAR,
+                                                       false, false);
       }
 
       return *shader;
    }
 }
 
 
 /**
  * Generate and save all fragment shaders that we will ever need for
  * blitting.  Drivers which use the 'draw' fallbacks will typically use
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c
index 613ec4a..5874d0e 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.c
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -198,40 +198,64 @@ void *util_make_layered_clear_geometry_shader(struct pipe_context *pipe)
    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);
 }
 
+static void
+ureg_load_tex(struct ureg_program *ureg, struct ureg_dst out,
+              struct ureg_src coord, struct ureg_src sampler,
+              unsigned tex_target, bool load_level_zero, bool use_txf)
+{
+   if (use_txf) {
+      struct ureg_dst temp = ureg_DECL_temporary(ureg);
+
+      ureg_F2I(ureg, temp, coord);
+
+      if (load_level_zero)
+         ureg_TXF_LZ(ureg, out, tex_target, ureg_src(temp), sampler);
+      else
+         ureg_TXF(ureg, out, tex_target, ureg_src(temp), sampler);
+   } else {
+      if (load_level_zero)
+         ureg_TEX_LZ(ureg, out, tex_target, coord, sampler);
+      else
+         ureg_TEX(ureg, out, tex_target, coord, sampler);
+   }
+}
+
 /**
  * Make simple fragment texture shader:
  *  IMM {0,0,0,1}                         // (if writemask != 0xf)
  *  MOV TEMP[0], IMM[0]                   // (if writemask != 0xf)
  *  TEX TEMP[0].writemask, IN[0], SAMP[0], 2D;
  *   .. optional SINT <-> UINT clamping ..
  *  MOV OUT[0], TEMP[0]
  *  END;
  *
  * \param tex_target  one of PIPE_TEXTURE_x
  * \parma interp_mode  either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
  * \param writemask  mask of TGSI_WRITEMASK_x
  */
 void *
 util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
                                         unsigned tex_target,
                                         unsigned interp_mode,
                                         unsigned writemask,
                                         enum tgsi_return_type stype,
-                                        enum tgsi_return_type dtype)
+                                        enum tgsi_return_type dtype,
+                                        bool load_level_zero,
+                                        bool use_txf)
 {
    struct ureg_program *ureg;
    struct ureg_src sampler;
    struct ureg_src tex;
    struct ureg_dst temp;
    struct ureg_dst out;
 
    assert((stype == TGSI_RETURN_TYPE_FLOAT) == (dtype == TGSI_RETURN_TYPE_FLOAT));
    assert(interp_mode == TGSI_INTERPOLATE_LINEAR ||
           interp_mode == TGSI_INTERPOLATE_PERSPECTIVE);
@@ -258,23 +282,22 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
       struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
 
       ureg_MOV( ureg, out, imm );
    }
 
    if (tex_target == TGSI_TEXTURE_BUFFER)
       ureg_TXF(ureg,
                ureg_writemask(temp, writemask),
                tex_target, tex, sampler);
    else
-      ureg_TEX(ureg,
-               ureg_writemask(temp, writemask),
-               tex_target, tex, sampler);
+      ureg_load_tex(ureg, ureg_writemask(temp, writemask), tex, sampler,
+                    tex_target, load_level_zero, use_txf);
 
    if (stype != dtype) {
       if (stype == TGSI_RETURN_TYPE_SINT) {
          assert(dtype == TGSI_RETURN_TYPE_UINT);
 
          ureg_IMAX(ureg, temp, ureg_src(temp), ureg_imm1i(ureg, 0));
       } else {
          assert(stype == TGSI_RETURN_TYPE_UINT);
          assert(dtype == TGSI_RETURN_TYPE_SINT);
 
@@ -292,38 +315,43 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
 
 /**
  * Make a simple fragment shader that sets the output color to a color
  * taken from a texture.
  * \param tex_target  one of PIPE_TEXTURE_x
  */
 void *
 util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
                               unsigned interp_mode,
                               enum tgsi_return_type stype,
-                              enum tgsi_return_type dtype)
+                              enum tgsi_return_type dtype,
+                              bool load_level_zero,
+                              bool use_txf)
 {
    return util_make_fragment_tex_shader_writemask( pipe,
                                                    tex_target,
                                                    interp_mode,
                                                    TGSI_WRITEMASK_XYZW,
-                                                   stype, dtype );
+                                                   stype, dtype, load_level_zero,
+                                                   use_txf);
 }
 
 
 /**
  * Make a simple fragment texture shader which reads an X component from
  * a texture and writes it as depth.
  */
 void *
 util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
                                          unsigned tex_target,
-                                         unsigned interp_mode)
+                                         unsigned interp_mode,
+                                         bool load_level_zero,
+                                         bool use_txf)
 {
    struct ureg_program *ureg;
    struct ureg_src sampler;
    struct ureg_src tex;
    struct ureg_dst out, depth;
    struct ureg_src imm;
 
    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
    if (!ureg)
       return NULL;
@@ -345,37 +373,38 @@ util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
                            0 );
 
    depth = ureg_DECL_output( ureg,
                              TGSI_SEMANTIC_POSITION,
                              0 );
 
    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
 
    ureg_MOV( ureg, out, imm );
 
-   ureg_TEX( ureg,
-             ureg_writemask(depth, TGSI_WRITEMASK_Z),
-             tex_target, tex, sampler );
+   ureg_load_tex(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Z), tex, sampler,
+                 tex_target, load_level_zero, use_txf);
    ureg_END( ureg );
 
    return ureg_create_shader_and_destroy( ureg, pipe );
 }
 
 
 /**
  * Make a simple fragment texture shader which reads the texture unit 0 and 1
  * and writes it as depth and stencil, respectively.
  */
 void *
 util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
                                                 unsigned tex_target,
-                                                unsigned interp_mode)
+                                                unsigned interp_mode,
+                                                bool load_level_zero,
+                                                bool use_txf)
 {
    struct ureg_program *ureg;
    struct ureg_src depth_sampler, stencil_sampler;
    struct ureg_src tex;
    struct ureg_dst out, depth, stencil;
    struct ureg_src imm;
 
    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
    if (!ureg)
       return NULL;
@@ -406,40 +435,40 @@ util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
                              0 );
 
    stencil = ureg_DECL_output( ureg,
                              TGSI_SEMANTIC_STENCIL,
                              0 );
 
    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
 
    ureg_MOV( ureg, out, imm );
 
-   ureg_TEX( ureg,
-             ureg_writemask(depth, TGSI_WRITEMASK_Z),
-             tex_target, tex, depth_sampler );
-   ureg_TEX( ureg,
-             ureg_writemask(stencil, TGSI_WRITEMASK_Y),
-             tex_target, tex, stencil_sampler );
+   ureg_load_tex(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Z), tex,
+                 depth_sampler, tex_target, load_level_zero, use_txf);
+   ureg_load_tex(ureg, ureg_writemask(stencil, TGSI_WRITEMASK_Y), tex,
+                 stencil_sampler, tex_target, load_level_zero, use_txf);
    ureg_END( ureg );
 
    return ureg_create_shader_and_destroy( ureg, pipe );
 }
 
 
 /**
  * Make a simple fragment texture shader which reads a texture and writes it
  * as stencil.
  */
 void *
 util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
                                            unsigned tex_target,
-                                           unsigned interp_mode)
+                                           unsigned interp_mode,
+                                           bool load_level_zero,
+                                           bool use_txf)
 {
    struct ureg_program *ureg;
    struct ureg_src stencil_sampler;
    struct ureg_src tex;
    struct ureg_dst out, stencil;
    struct ureg_src imm;
 
    ureg = ureg_create( PIPE_SHADER_FRAGMENT );
    if (!ureg)
       return NULL;
@@ -461,23 +490,22 @@ util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
                            0 );
 
    stencil = ureg_DECL_output( ureg,
                              TGSI_SEMANTIC_STENCIL,
                              0 );
 
    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
 
    ureg_MOV( ureg, out, imm );
 
-   ureg_TEX( ureg,
-             ureg_writemask(stencil, TGSI_WRITEMASK_Y),
-             tex_target, tex, stencil_sampler );
+   ureg_load_tex(ureg, ureg_writemask(stencil, TGSI_WRITEMASK_Y), tex,
+                 stencil_sampler, tex_target, load_level_zero, use_txf);
    ureg_END( ureg );
 
    return ureg_create_shader_and_destroy( ureg, pipe );
 }
 
 
 /**
  * Make simple fragment color pass-through shader that replicates OUT[0]
  * to all bound colorbuffers.
  */
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h
index 0481098..de05aad 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.h
+++ b/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -67,44 +67,54 @@ 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,
                                         unsigned writemask,
                                         enum tgsi_return_type stype,
-                                        enum tgsi_return_type dtype);
+                                        enum tgsi_return_type dtype,
+                                        bool load_level_zero,
+                                        bool use_txf);
 
 extern void *
 util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
                               unsigned interp_mode,
                               enum tgsi_return_type stype,
-                              enum tgsi_return_type dtype);
+                              enum tgsi_return_type dtype,
+                              bool load_level_zero,
+                              bool use_txf);
 
 extern void *
 util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
                                          unsigned tex_target,
-                                         unsigned interp_mode);
+                                         unsigned interp_mode,
+                                         bool load_level_zero,
+                                         bool use_txf);
 
 
 extern void *
 util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
                                                 unsigned tex_target,
-                                                unsigned interp_mode);
+                                                unsigned interp_mode,
+                                                bool load_level_zero,
+                                                bool use_txf);
 
 
 extern void *
 util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
                                            unsigned tex_target,
-                                           unsigned interp_mode);
+                                           unsigned interp_mode,
+                                           bool load_level_zero,
+                                           bool use_txf);
 
 
 extern void *
 util_make_fragment_passthrough_shader(struct pipe_context *pipe,
                                       int input_semantic,
                                       int input_interpolate,
                                       boolean write_all_cbufs);
 
 
 extern void *
diff --git a/src/gallium/auxiliary/util/u_tests.c b/src/gallium/auxiliary/util/u_tests.c
index 30eb589..7ec8eef 100644
--- a/src/gallium/auxiliary/util/u_tests.c
+++ b/src/gallium/auxiliary/util/u_tests.c
@@ -368,21 +368,21 @@ null_sampler_view(struct pipe_context *ctx, unsigned tgsi_tex_target)
    cb = util_create_texture2d(ctx->screen, 256, 256,
                               PIPE_FORMAT_R8G8B8A8_UNORM);
    util_set_common_states_and_clear(cso, ctx, cb);
 
    ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, NULL);
 
    /* Fragment shader. */
    fs = util_make_fragment_tex_shader(ctx, tgsi_tex_target,
                                       TGSI_INTERPOLATE_LINEAR,
                                       TGSI_RETURN_TYPE_FLOAT,
-                                      TGSI_RETURN_TYPE_FLOAT);
+                                      TGSI_RETURN_TYPE_FLOAT, false, false);
    cso_set_fragment_shader_handle(cso, fs);
 
    /* Vertex shader. */
    vs = util_set_passthrough_vertex_shader(cso, ctx, false);
    util_draw_fullscreen_quad(cso);
 
    /* Probe pixels. */
    pass = pass && util_probe_rect_rgba_multi(ctx, cb, 0, 0,
                                   cb->width0, cb->height0, expected,
                                   num_expected);
diff --git a/src/gallium/tests/trivial/quad-tex.c b/src/gallium/tests/trivial/quad-tex.c
index 6e9957a..2ee544a 100644
--- a/src/gallium/tests/trivial/quad-tex.c
+++ b/src/gallium/tests/trivial/quad-tex.c
@@ -266,21 +266,22 @@ static void init_prog(struct program *p)
 		const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
 		                                TGSI_SEMANTIC_GENERIC };
 		const uint semantic_indexes[] = { 0, 0 };
 		p->vs = util_make_vertex_passthrough_shader(p->pipe, 2, semantic_names, semantic_indexes, FALSE);
 	}
 
 	/* fragment shader */
 	p->fs = util_make_fragment_tex_shader(p->pipe, TGSI_TEXTURE_2D,
 	                                      TGSI_INTERPOLATE_LINEAR,
 	                                      TGSI_RETURN_TYPE_FLOAT,
-	                                      TGSI_RETURN_TYPE_FLOAT);
+	                                      TGSI_RETURN_TYPE_FLOAT, false,
+                                              false);
 }
 
 static void close_prog(struct program *p)
 {
 	cso_destroy_context(p->cso);
 
 	p->pipe->delete_vs_state(p->pipe, p->vs);
 	p->pipe->delete_fs_state(p->pipe, p->fs);
 
 	pipe_surface_reference(&p->framebuffer.cbufs[0], NULL);
-- 
2.7.4



More information about the mesa-dev mailing list