[Mesa-dev] [PATCH 5/9] st/mesa: implement PBO upload for multiple layers

Nicolai Hähnle nhaehnle at gmail.com
Mon Jan 18 14:22:41 PST 2016


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

Use instancing to generate two triangles for each destination layer and use
a geometry shader to route the layer index.
---
 src/mesa/state_tracker/st_cb_texture.c | 145 +++++++++++++++++++++++++++------
 src/mesa/state_tracker/st_context.h    |   2 +
 2 files changed, 122 insertions(+), 25 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index c3aadb5..7804786 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -698,17 +698,9 @@ st_init_pbo_upload(struct st_context *st)
 
    st->pbo_upload.rgba_only =
       screen->get_param(screen, PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY);
-
-   /* Create the vertex shader */
-   {
-      unsigned semantic_names[] = { TGSI_SEMANTIC_POSITION };
-      unsigned semantic_indexes[] = { 0 };
-
-      st->pbo_upload.vs = util_make_vertex_passthrough_shader(pipe, 1,
-                                                              semantic_names,
-                                                              semantic_indexes,
-                                                              FALSE);
-   }
+   st->pbo_upload.upload_layers =
+      screen->get_param(screen, PIPE_CAP_TGSI_INSTANCEID) &&
+      screen->get_param(screen, PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES) >= 3;
 
    /* Blend state */
    memset(&st->pbo_upload.blend, 0, sizeof(struct pipe_blend_state));
@@ -1113,7 +1105,82 @@ reinterpret_formats(enum pipe_format *src_format, enum pipe_format *dst_format)
 }
 
 static void *
-create_pbo_upload_shader(struct pipe_context *pipe)
+create_pbo_upload_vs(struct st_context *st)
+{
+   struct ureg_program *ureg;
+   struct ureg_src in_pos;
+   struct ureg_src in_instanceid;
+   struct ureg_dst out_pos;
+
+   ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
+
+   in_pos = ureg_DECL_vs_input(ureg, TGSI_SEMANTIC_POSITION);
+
+   if (st->pbo_upload.upload_layers)
+      in_instanceid = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_INSTANCEID, 0);
+
+   out_pos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+
+   /* out_pos = in_pos */
+   ureg_MOV(ureg, out_pos, in_pos);
+
+   if (st->pbo_upload.upload_layers) {
+      /* out_pos.z = i2f(gl_InstanceID) */
+      ureg_I2F(ureg, ureg_writemask(out_pos, TGSI_WRITEMASK_Z),
+                     ureg_scalar(in_instanceid, TGSI_SWIZZLE_X));
+   }
+
+   ureg_END(ureg);
+
+   return ureg_create_shader_and_destroy(ureg, st->pipe);
+}
+
+static void *
+create_pbo_upload_gs(struct st_context *st)
+{
+   static const int zero = 0;
+   struct ureg_program *ureg;
+   struct ureg_dst out_pos;
+   struct ureg_dst out_layer;
+   struct ureg_src in_pos;
+   struct ureg_src imm;
+   unsigned i;
+
+   ureg = ureg_create(TGSI_PROCESSOR_GEOMETRY);
+   if (!ureg)
+      return NULL;
+
+   ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_TRIANGLES);
+   ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_TRIANGLE_STRIP);
+   ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 3);
+
+   out_pos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+   out_layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0);
+
+   in_pos = ureg_DECL_input(ureg, TGSI_SEMANTIC_POSITION, 0, 0, 1);
+
+   imm = ureg_DECL_immediate_int(ureg, &zero, 1);
+
+   for (i = 0; i < 3; ++i) {
+      struct ureg_src in_pos_vertex = ureg_src_dimension(in_pos, i);
+
+      /* out_pos = in_pos[i] */
+      ureg_MOV(ureg, out_pos, in_pos_vertex);
+
+      /* out_layer.x = f2i(in_pos[i].z) */
+      ureg_F2I(ureg, ureg_writemask(out_layer, TGSI_WRITEMASK_X),
+                     ureg_scalar(in_pos_vertex, TGSI_SWIZZLE_Z));
+
+      ureg_EMIT(ureg, ureg_scalar(imm, TGSI_SWIZZLE_X));
+   }
+
+   ureg_END(ureg);
+
+   return ureg_create_shader_and_destroy(ureg, st->pipe);
+}
+
+static void *
+create_pbo_upload_fs(struct st_context *st)
 {
    struct ureg_program *ureg;
    struct ureg_dst out;
@@ -1122,7 +1189,10 @@ create_pbo_upload_shader(struct pipe_context *pipe)
    struct ureg_src const0;
    struct ureg_dst temp0;
 
-   ureg    = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!ureg)
+      return NULL;
+
    out     = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
    sampler = ureg_DECL_sampler(ureg, 0);
    pos     = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0,
@@ -1130,15 +1200,15 @@ create_pbo_upload_shader(struct pipe_context *pipe)
    const0  = ureg_DECL_constant(ureg, 0);
    temp0   = ureg_DECL_temporary(ureg);
 
-   /* Note: const0 = [ -xoffset, -yoffset, stride, 0 ] */
+   /* Note: const0 = [ -xoffset, -yoffset, stride, stride * image_height ] */
 
    ureg_MOV(ureg, temp0, pos);
 
-   /* temp0.xy = f2i(temp0.xy) */
-   ureg_F2I(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY),
+   /* temp0.xyz = f2i(temp0.xyz) */
+   ureg_F2I(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XYZ),
                   ureg_swizzle(ureg_src(temp0),
                                TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y,
-                               TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y));
+                               TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z));
 
    /* temp0.xy = temp0.xy + const0.xy */
    ureg_UADD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY),
@@ -1155,6 +1225,14 @@ create_pbo_upload_shader(struct pipe_context *pipe)
                    ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_Y),
                    ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X));
 
+   if (st->pbo_upload.upload_layers) {
+      /* temp0.x = const0.w * temp0.z + temp0.x */
+      ureg_UMAD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_X),
+                      ureg_scalar(const0, TGSI_SWIZZLE_W),
+                      ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_Z),
+                      ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X));
+   }
+
    /* out = txf(sampler, temp0.x) */
    ureg_TXF(ureg, out, TGSI_TEXTURE_BUFFER,
                   ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X),
@@ -1164,7 +1242,7 @@ create_pbo_upload_shader(struct pipe_context *pipe)
 
    ureg_END(ureg);
 
-   return ureg_create_shader_and_destroy(ureg, pipe);
+   return ureg_create_shader_and_destroy(ureg, st->pipe);
 }
 
 static bool
@@ -1189,8 +1267,20 @@ try_pbo_upload_common(struct gl_context *ctx,
       return false;
 
    /* Create the shaders */
+   if (!st->pbo_upload.vs) {
+      st->pbo_upload.vs = create_pbo_upload_vs(st);
+      if (!st->pbo_upload.vs)
+         return false;
+   }
+
+   if (depth != 1 && !st->pbo_upload.gs) {
+      st->pbo_upload.gs = create_pbo_upload_gs(st);
+      if (!st->pbo_upload.gs)
+         return false;
+   }
+
    if (!st->pbo_upload.fs) {
-      st->pbo_upload.fs = create_pbo_upload_shader(pipe);
+      st->pbo_upload.fs = create_pbo_upload_fs(st);
       if (!st->pbo_upload.fs)
          return false;
    }
@@ -1315,13 +1405,13 @@ try_pbo_upload_common(struct gl_context *ctx,
          int32_t xoffset;
          int32_t yoffset;
          int32_t stride;
-         int32_t pad;
+         int32_t image_size;
       } constants;
 
       constants.xoffset = -xoffset;
       constants.yoffset = -yoffset;
       constants.stride = stride;
-      constants.pad = 0;
+      constants.image_size = stride * image_height;
 
       if (st->constbuf_uploader) {
          cb.buffer = NULL;
@@ -1346,7 +1436,8 @@ try_pbo_upload_common(struct gl_context *ctx,
    cso_set_vertex_shader_handle(st->cso_context, st->pbo_upload.vs);
 
    cso_save_geometry_shader(st->cso_context);
-   cso_set_geometry_shader_handle(st->cso_context, NULL);
+   cso_set_geometry_shader_handle(st->cso_context,
+                                  depth != 1 ? st->pbo_upload.gs : NULL);
 
    cso_save_tessctrl_shader(st->cso_context);
    cso_set_tessctrl_shader_handle(st->cso_context, NULL);
@@ -1361,7 +1452,12 @@ try_pbo_upload_common(struct gl_context *ctx,
    cso_save_stream_outputs(st->cso_context);
    cso_set_stream_outputs(st->cso_context, 0, NULL, 0);
 
-   cso_draw_arrays(st->cso_context, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
+   if (depth == 1) {
+      cso_draw_arrays(st->cso_context, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
+   } else {
+      cso_draw_arrays_instanced(st->cso_context, PIPE_PRIM_TRIANGLE_STRIP,
+                                0, 4, 0, depth);
+   }
 
    cso_restore_fragment_sampler_views(st->cso_context);
    cso_restore_framebuffer(st->cso_context);
@@ -1422,8 +1518,7 @@ try_pbo_upload(struct gl_context *ctx, GLuint dims,
       image_height = unpack->ImageHeight > 0 ? unpack->ImageHeight : height;
    }
 
-   /* XXX We only support updating a single layer */
-   if (depth != 1)
+   if (depth != 1 && !st->pbo_upload.upload_layers)
       return false;
 
    /* Choose the source format. Initially, we do so without checking driver
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 4baa707..c73c206 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -207,8 +207,10 @@ struct st_context
       struct pipe_rasterizer_state raster;
       struct pipe_blend_state blend;
       void *vs;
+      void *gs;
       void *fs;
       bool rgba_only;
+      bool upload_layers;
    } pbo_upload;
 
    /** used for anything using util_draw_vertex_buffer */
-- 
2.5.0



More information about the mesa-dev mailing list