[Mesa-dev] [PATCH 11/14] st/mesa: create PBO download fragment shaders

Nicolai Hähnle nhaehnle at gmail.com
Wed May 18 15:25:41 UTC 2016


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

---
 src/mesa/state_tracker/st_pbo.c | 83 +++++++++++++++++++++++++++++++++++++----
 src/mesa/state_tracker/st_pbo.h |  3 ++
 2 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/src/mesa/state_tracker/st_pbo.c b/src/mesa/state_tracker/st_pbo.c
index 57ff9b0..c7735f7 100644
--- a/src/mesa/state_tracker/st_pbo.c
+++ b/src/mesa/state_tracker/st_pbo.c
@@ -358,12 +358,13 @@ st_pbo_create_gs(struct st_context *st)
    return ureg_create_shader_and_destroy(ureg, st->pipe);
 }
 
-void *
-st_pbo_create_upload_fs(struct st_context *st)
+static void *
+create_fs(struct st_context *st, bool download, enum pipe_texture_target target)
 {
    struct pipe_context *pipe = st->pipe;
    struct pipe_screen *screen = pipe->screen;
    struct ureg_program *ureg;
+   bool have_layer;
    struct ureg_dst out;
    struct ureg_src sampler;
    struct ureg_src pos;
@@ -371,11 +372,29 @@ st_pbo_create_upload_fs(struct st_context *st)
    struct ureg_src const0;
    struct ureg_dst temp0;
 
+   have_layer =
+      st->pbo.layers &&
+      (!download || target == PIPE_TEXTURE_1D_ARRAY
+                 || target == PIPE_TEXTURE_2D_ARRAY
+                 || target == PIPE_TEXTURE_3D
+                 || target == PIPE_TEXTURE_CUBE
+                 || target == PIPE_TEXTURE_CUBE_ARRAY);
+
    ureg = ureg_create(PIPE_SHADER_FRAGMENT);
    if (!ureg)
       return NULL;
 
-   out     = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+   if (!download) {
+      out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+   } else {
+      struct ureg_src image;
+
+      /* writeonly images do not require an explicitly given format. */
+      image = ureg_DECL_image(ureg, 0, TGSI_TEXTURE_BUFFER, PIPE_FORMAT_NONE,
+                                    true, false);
+      out = ureg_dst(image);
+   }
+
    sampler = ureg_DECL_sampler(ureg, 0);
    if (screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL)) {
       pos = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_POSITION, 0);
@@ -383,7 +402,7 @@ st_pbo_create_upload_fs(struct st_context *st)
       pos = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0,
                                TGSI_INTERPOLATE_LINEAR);
    }
-   if (st->pbo.layers) {
+   if (have_layer) {
       layer = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_LAYER, 0,
                                        TGSI_INTERPOLATE_CONSTANT);
    }
@@ -413,7 +432,7 @@ st_pbo_create_upload_fs(struct st_context *st)
                    ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_Y),
                    ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X));
 
-   if (st->pbo.layers) {
+   if (have_layer) {
       /* temp0.x = const0.w * layer + temp0.x */
       ureg_UMAD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_X),
                       ureg_scalar(const0, TGSI_SWIZZLE_W),
@@ -424,8 +443,41 @@ st_pbo_create_upload_fs(struct st_context *st)
    /* temp0.w = 0 */
    ureg_MOV(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_W), ureg_imm1u(ureg, 0));
 
-   /* out = txf(sampler, temp0.x) */
-   ureg_TXF(ureg, out, TGSI_TEXTURE_BUFFER, ureg_src(temp0), sampler);
+   if (download) {
+      struct ureg_dst temp1;
+      struct ureg_src op[2];
+
+      temp1 = ureg_DECL_temporary(ureg);
+
+      /* temp1.xy = pos.xy */
+      ureg_F2I(ureg, ureg_writemask(temp1, TGSI_WRITEMASK_XY), pos);
+
+      /* temp1.zw = 0 */
+      ureg_MOV(ureg, ureg_writemask(temp1, TGSI_WRITEMASK_ZW), ureg_imm1u(ureg, 0));
+
+      if (have_layer) {
+         /* temp1.y/z = layer */
+         ureg_MOV(ureg, ureg_writemask(temp1,
+                                       target == PIPE_TEXTURE_1D_ARRAY ? TGSI_WRITEMASK_Y
+                                                                       : TGSI_WRITEMASK_Z),
+                        ureg_scalar(layer, TGSI_SWIZZLE_X));
+      }
+
+      /* temp1 = txf(sampler, temp1) */
+      ureg_TXF(ureg, temp1, util_pipe_tex_to_tgsi_tex(target, 1),
+                     ureg_src(temp1), sampler);
+
+      /* store(out, temp0, temp1) */
+      op[0] = ureg_src(temp0);
+      op[1] = ureg_src(temp1);
+      ureg_memory_insn(ureg, TGSI_OPCODE_STORE, &out, 1, op, 2, 0,
+                             TGSI_TEXTURE_BUFFER, PIPE_FORMAT_NONE);
+
+      ureg_release_temporary(ureg, temp1);
+   } else {
+      /* out = txf(sampler, temp0.x) */
+      ureg_TXF(ureg, out, TGSI_TEXTURE_BUFFER, ureg_src(temp0), sampler);
+   }
 
    ureg_release_temporary(ureg, temp0);
 
@@ -434,6 +486,23 @@ st_pbo_create_upload_fs(struct st_context *st)
    return ureg_create_shader_and_destroy(ureg, pipe);
 }
 
+void *
+st_pbo_create_upload_fs(struct st_context *st)
+{
+   return create_fs(st, false, 0);
+}
+
+void *
+st_pbo_get_download_fs(struct st_context *st, enum pipe_texture_target target)
+{
+   assert(target < PIPE_MAX_TEXTURE_TYPES);
+
+   if (!st->pbo.download_fs[target])
+      st->pbo.download_fs[target] = create_fs(st, true, target);
+
+   return st->pbo.download_fs[target];
+}
+
 void
 st_init_pbo_helpers(struct st_context *st)
 {
diff --git a/src/mesa/state_tracker/st_pbo.h b/src/mesa/state_tracker/st_pbo.h
index fb1b737..c17ac17 100644
--- a/src/mesa/state_tracker/st_pbo.h
+++ b/src/mesa/state_tracker/st_pbo.h
@@ -82,6 +82,9 @@ st_pbo_create_gs(struct st_context *st);
 void *
 st_pbo_create_upload_fs(struct st_context *st);
 
+void *
+st_pbo_get_download_fs(struct st_context *st, enum pipe_texture_target target);
+
 extern void
 st_init_pbo_helpers(struct st_context *st);
 
-- 
2.7.4



More information about the mesa-dev mailing list