[Mesa-dev] [PATCH 14/18] gallium/u_blitter: generate VS POSITION output from VERTEXID if possible

Marek Olšák maraeo at gmail.com
Thu Aug 17 18:31:35 UTC 2017


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

---
 src/gallium/auxiliary/util/u_blitter.c        | 118 +++++++++++++++++++-------
 src/gallium/drivers/radeon/r600_pipe_common.c |  37 +++-----
 2 files changed, 96 insertions(+), 59 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 54d3009..6827da8 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -55,20 +55,21 @@
    ((clear_buffers) / PIPE_CLEAR_COLOR0)
 
 #define NUM_RESOLVE_FRAG_SHADERS 5 /* MSAA 2x, 4x, 8x, 16x, 32x */
 #define GET_MSAA_RESOLVE_FS_IDX(nr_samples) (util_logbase2(nr_samples)-1)
 
 struct blitter_context_priv
 {
    struct blitter_context base;
 
    float vertices[4][2][4];   /**< {pos, color} or {pos, texcoord} */
+   float vertices_nopos[4][4];     /**< {color} or {texcoord} only */
 
    /* Templates for various state objects. */
 
    /* Constant state objects. */
    /* Vertex shaders. */
    void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/
    void *vs_pos_only[4]; /**< Vertex shader which passes pos to the output.*/
    void *vs_layered; /**< Vertex shader which sets LAYER = INSTANCEID. */
 
    /* Fragment shaders. */
@@ -124,20 +125,21 @@ struct blitter_context_priv
    void *rs_state, *rs_state_scissor, *rs_discard_state;
 
    boolean has_geometry_shader;
    boolean has_tessellation;
    boolean has_layered;
    boolean has_stream_out;
    boolean has_stencil_export;
    boolean has_texture_multisample;
    boolean has_tex_lz;
    boolean has_txf;
+   boolean has_vertex_id;
    boolean cube_as_2darray;
    boolean cached_all_shaders;
 
    /* The Draw module overrides these functions.
     * Always create the blitter before Draw. */
    void   (*bind_fs_state)(struct pipe_context *, void *);
    void   (*delete_fs_state)(struct pipe_context *, void *);
 };
 
 struct blitter_context *util_blitter_create(struct pipe_context *pipe)
@@ -189,20 +191,21 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
          pipe->screen->get_param(pipe->screen,
                                  PIPE_CAP_SHADER_STENCIL_EXPORT);
 
    ctx->has_texture_multisample =
       pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_MULTISAMPLE);
 
    ctx->has_tex_lz = pipe->screen->get_param(pipe->screen,
                                              PIPE_CAP_TGSI_TEX_TXF_LZ);
    ctx->has_txf = pipe->screen->get_param(pipe->screen,
                                           PIPE_CAP_GLSL_FEATURE_LEVEL) > 130;
+   ctx->has_vertex_id = ctx->has_txf;
    ctx->cube_as_2darray = pipe->screen->get_param(pipe->screen,
                                                   PIPE_CAP_SAMPLER_VIEW_TARGET);
 
    /* blend state objects */
    memset(&blend, 0, sizeof(blend));
 
    for (i = 0; i <= PIPE_MASK_RGBA; i++) {
       for (j = 0; j < 2; j++) {
          memset(&blend.rt[0], 0, sizeof(blend.rt[0]));
          blend.rt[0].colormask = i;
@@ -277,27 +280,30 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
    if (ctx->has_stream_out) {
       rs_state.scissor = 0;
       rs_state.rasterizer_discard = 1;
       ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state);
    }
 
    ctx->base.cb_slot = 0; /* 0 for now */
    ctx->base.vb_slot = 0; /* 0 for now */
 
    /* vertex elements states */
-   memset(&velem[0], 0, sizeof(velem[0]) * 2);
-   for (i = 0; i < 2; i++) {
+   unsigned num_attribs = ctx->has_vertex_id ? 1 : 2;
+
+   memset(&velem[0], 0, sizeof(velem[0]) * num_attribs);
+   for (i = 0; i < num_attribs; i++) {
       velem[i].src_offset = i * 4 * sizeof(float);
       velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
       velem[i].vertex_buffer_index = ctx->base.vb_slot;
    }
-   ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
+   ctx->velem_state = pipe->create_vertex_elements_state(pipe, num_attribs,
+                                                         &velem[0]);
 
    if (ctx->has_stream_out) {
       static enum pipe_format formats[4] = {
          PIPE_FORMAT_R32_UINT,
          PIPE_FORMAT_R32G32_UINT,
          PIPE_FORMAT_R32G32B32_UINT,
          PIPE_FORMAT_R32G32B32A32_UINT
       };
 
       for (i = 0; i < 4; i++) {
@@ -345,35 +351,38 @@ static void bind_vs_pos_only(struct blitter_context_priv *ctx,
 }
 
 static void bind_vs_passthrough(struct blitter_context_priv *ctx)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
    if (!ctx->vs) {
       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
                                       TGSI_SEMANTIC_GENERIC };
       const uint semantic_indices[] = { 0, 0 };
+      unsigned offset = ctx->has_vertex_id ? 1 : 0;
+
       ctx->vs =
-         util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
-                                             semantic_indices, FALSE);
+         util_make_vertex_passthrough_shader(pipe, 2 - offset,
+                                             semantic_names + offset,
+                                             semantic_indices + offset, FALSE);
    }
 
    pipe->bind_vs_state(pipe, ctx->vs);
 }
 
 static void bind_vs_layered(struct blitter_context_priv *ctx)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
    if (!ctx->vs_layered) {
       ctx->vs_layered =
-         util_make_layered_clear_vertex_shader(pipe, true);
+         util_make_layered_clear_vertex_shader(pipe, !ctx->has_vertex_id);
    }
 
    pipe->bind_vs_state(pipe, ctx->vs_layered);
 }
 
 static void bind_fs_empty(struct blitter_context_priv *ctx)
 {
    struct pipe_context *pipe = ctx->base.pipe;
 
    if (!ctx->fs_empty) {
@@ -702,54 +711,66 @@ void util_blitter_restore_constant_buffer_state(struct blitter_context *blitter)
 }
 
 static void blitter_set_rectangle(struct blitter_context_priv *ctx,
                                   int x1, int y1, int x2, int y2,
                                   float depth)
 {
    int width = x2 - x1;
    int height = y2 - y1;
 
    /* set vertex positions */
-   ctx->vertices[0][0][0] = -1; /*v0.x*/
-   ctx->vertices[0][0][1] = -1; /*v0.y*/
+   if (!ctx->has_vertex_id) {
+      ctx->vertices[0][0][0] = -1; /*v0.x*/
+      ctx->vertices[0][0][1] = -1; /*v0.y*/
 
-   ctx->vertices[1][0][0] = 1;  /*v1.x*/
-   ctx->vertices[1][0][1] = -1; /*v1.y*/
+      ctx->vertices[1][0][0] = 1;  /*v1.x*/
+      ctx->vertices[1][0][1] = -1; /*v1.y*/
 
-   ctx->vertices[2][0][0] = 1;  /*v2.x*/
-   ctx->vertices[2][0][1] = 1;  /*v2.y*/
+      ctx->vertices[2][0][0] = 1;  /*v2.x*/
+      ctx->vertices[2][0][1] = 1;  /*v2.y*/
 
-   ctx->vertices[3][0][0] = -1; /*v3.x*/
-   ctx->vertices[3][0][1] = 1;  /*v3.y*/
+      ctx->vertices[3][0][0] = -1; /*v3.x*/
+      ctx->vertices[3][0][1] = 1;  /*v3.y*/
+   }
 
    /* viewport */
    struct pipe_viewport_state viewport;
    viewport.scale[0] = width / 2.0;
    viewport.scale[1] = height / 2.0;
    viewport.scale[2] = 0;
    viewport.translate[0] = width / 2.0 + x1;
    viewport.translate[1] = height / 2.0 + y1;
    viewport.translate[2] = depth;
    ctx->base.pipe->set_viewport_states(ctx->base.pipe, 0, 1, &viewport);
 }
 
 static void blitter_set_clear_color(struct blitter_context_priv *ctx,
                                     const uint32_t color[4])
 {
    int i;
 
-   if (color) {
-      for (i = 0; i < 4; i++)
-         memcpy(&ctx->vertices[i][1][0], color, sizeof(uint32_t) * 4);
+   if (ctx->has_vertex_id) {
+      if (color) {
+         for (i = 0; i < 4; i++)
+            memcpy(&ctx->vertices_nopos[i][0], color, sizeof(uint32_t) * 4);
+      } else {
+         for (i = 0; i < 4; i++)
+            memset(&ctx->vertices_nopos[i][0], 0, sizeof(uint32_t) * 4);
+      }
    } else {
-      for (i = 0; i < 4; i++)
-         memset(&ctx->vertices[i][1][0], 0, sizeof(uint32_t) * 4);
+      if (color) {
+         for (i = 0; i < 4; i++)
+            memcpy(&ctx->vertices[i][1][0], color, sizeof(uint32_t) * 4);
+      } else {
+         for (i = 0; i < 4; i++)
+            memset(&ctx->vertices[i][1][0], 0, sizeof(uint32_t) * 4);
+      }
    }
 }
 
 static void get_texcoords(struct pipe_sampler_view *src,
                           unsigned src_width0, unsigned src_height0,
                           int x1, int y1, int x2, int y2,
                           float layer, unsigned sample,
                           bool uses_txf, union blitter_attrib *out)
 {
    unsigned level = src->u.tex.first_level;
@@ -1202,24 +1223,34 @@ static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx,
 
 static void blitter_draw(struct blitter_context_priv *ctx,
                          int x1, int y1, int x2, int y2, float depth,
                          unsigned num_instances)
 {
    struct pipe_context *pipe = ctx->base.pipe;
    struct pipe_vertex_buffer vb = {0};
 
    blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);
 
-   vb.stride = 8 * sizeof(float);
+   if (ctx->has_vertex_id) {
+      vb.stride = 4 * sizeof(float);
 
-   u_upload_data(pipe->stream_uploader, 0, sizeof(ctx->vertices), 4, ctx->vertices,
-                 &vb.buffer_offset, &vb.buffer.resource);
+      /* Align vertices to a cache line. */
+      u_upload_data(pipe->stream_uploader, 0, sizeof(ctx->vertices_nopos), 64,
+                    ctx->vertices_nopos, &vb.buffer_offset,
+                    &vb.buffer.resource);
+   } else {
+      vb.stride = 8 * sizeof(float);
+
+      /* Align vertices to a cache line. */
+      u_upload_data(pipe->stream_uploader, 0, sizeof(ctx->vertices), 64,
+                    ctx->vertices, &vb.buffer_offset, &vb.buffer.resource);
+   }
    if (!vb.buffer.resource)
       return;
    u_upload_unmap(pipe->stream_uploader);
 
    pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb);
    util_draw_arrays_instanced(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, 4,
                               0, num_instances);
    pipe_resource_reference(&vb.buffer.resource, NULL);
 }
 
@@ -1231,27 +1262,37 @@ void util_blitter_draw_rectangle(struct blitter_context *blitter,
 {
    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
    unsigned i;
 
    switch (type) {
       case UTIL_BLITTER_ATTRIB_COLOR:
          blitter_set_clear_color(ctx, (uint32_t*)attrib->color);
          break;
 
       case UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW:
-         for (i = 0; i < 4; i++) {
-            ctx->vertices[i][1][2] = attrib->texcoord.z;
-            ctx->vertices[i][1][3] = attrib->texcoord.w;
+         if (ctx->has_vertex_id) {
+            for (i = 0; i < 4; i++) {
+               ctx->vertices_nopos[i][2] = attrib->texcoord.z;
+               ctx->vertices_nopos[i][3] = attrib->texcoord.w;
+            }
+         } else {
+            for (i = 0; i < 4; i++) {
+               ctx->vertices[i][1][2] = attrib->texcoord.z;
+               ctx->vertices[i][1][3] = attrib->texcoord.w;
+            }
          }
          /* fall through */
       case UTIL_BLITTER_ATTRIB_TEXCOORD_XY:
-         set_texcoords_in_vertices(attrib, &ctx->vertices[0][1][0], 8);
+         if (ctx->has_vertex_id)
+            set_texcoords_in_vertices(attrib, &ctx->vertices_nopos[0][0], 4);
+         else
+            set_texcoords_in_vertices(attrib, &ctx->vertices[0][1][0], 8);
          break;
 
       default:;
    }
 
    blitter_draw(ctx, x1, y1, x2, y2, depth, num_instances);
 }
 
 static void *get_clear_blend_state(struct blitter_context_priv *ctx,
                                    unsigned clear_buffers)
@@ -1571,27 +1612,38 @@ blitter_draw_tex(struct blitter_context_priv *ctx,
 
    get_texcoords(src, src_width0, src_height0,
                  src_x1, src_y1, src_x2, src_y2, layer, sample,
                  uses_txf, &coord);
 
    if (src->target == PIPE_TEXTURE_CUBE ||
        src->target == PIPE_TEXTURE_CUBE_ARRAY) {
       float face_coord[4][2];
 
       set_texcoords_in_vertices(&coord, &face_coord[0][0], 2);
-      util_map_texcoords2d_onto_cubemap((unsigned)layer % 6,
-                                        /* pointer, stride in floats */
-                                        &face_coord[0][0], 2,
-                                        &ctx->vertices[0][1][0], 8,
-                                        FALSE);
-      for (unsigned i = 0; i < 4; i++)
-         ctx->vertices[i][1][3] = coord.texcoord.w;
+
+      if (ctx->has_vertex_id) {
+         util_map_texcoords2d_onto_cubemap((unsigned)layer % 6,
+                                           /* pointer, stride in floats */
+                                           &face_coord[0][0], 2,
+                                           &ctx->vertices_nopos[0][0], 4,
+                                           FALSE);
+         for (unsigned i = 0; i < 4; i++)
+            ctx->vertices_nopos[i][3] = coord.texcoord.w;
+      } else {
+         util_map_texcoords2d_onto_cubemap((unsigned)layer % 6,
+                                           /* pointer, stride in floats */
+                                           &face_coord[0][0], 2,
+                                           &ctx->vertices[0][1][0], 8,
+                                           FALSE);
+         for (unsigned i = 0; i < 4; i++)
+            ctx->vertices[i][1][3] = coord.texcoord.w;
+      }
 
       /* Cubemaps don't use draw_rectangle. */
       blitter_draw(ctx, dst_x1, dst_y1, dst_x2, dst_y2, 0, 1);
    } else {
       ctx->base.draw_rectangle(&ctx->base, dst_x1, dst_y1, dst_x2, dst_y2, 0,
                                1, type, &coord);
    }
 }
 
 static void do_blits(struct blitter_context_priv *ctx,
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
index 5b54906..3539803 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -229,66 +229,51 @@ void r600_draw_rectangle(struct blitter_context *blitter,
 	viewport.scale[1] = height / 2.0;
 	viewport.scale[2] = 0;
 	viewport.translate[0] = width / 2.0 + x1;
 	viewport.translate[1] = height / 2.0 + y1;
 	viewport.translate[2] = depth;
 	rctx->b.set_viewport_states(&rctx->b, 0, 1, &viewport);
 
 	/* Upload vertices. The hw rectangle has only 3 vertices,
 	 * The 4th one is derived from the first 3.
 	 * The vertex specification should match u_blitter's vertex element state. */
-	u_upload_alloc(rctx->b.stream_uploader, 0, sizeof(float) * 24,
+	u_upload_alloc(rctx->b.stream_uploader, 0, sizeof(float) * 12,
 		       rctx->screen->info.tcc_cache_line_size,
                        &offset, &buf, (void**)&vb);
 	if (!buf)
 		return;
 
-	vb[0] = -1;
-	vb[1] = -1;
-	vb[2] = 0;
-	vb[3] = 1;
-
-	vb[8] = -1;
-	vb[9] = 1;
-	vb[10] = 0;
-	vb[11] = 1;
-
-	vb[16] = 1;
-	vb[17] = 1;
-	vb[18] = 0;
-	vb[19] = 1;
-
 	switch (type) {
 	case UTIL_BLITTER_ATTRIB_COLOR:
+		memcpy(vb, attrib->color, sizeof(float)*4);
 		memcpy(vb+4, attrib->color, sizeof(float)*4);
-		memcpy(vb+12, attrib->color, sizeof(float)*4);
-		memcpy(vb+20, attrib->color, sizeof(float)*4);
+		memcpy(vb+8, attrib->color, sizeof(float)*4);
 		break;
 	case UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW:
-		vb[6] = vb[14] = vb[22] = attrib->texcoord.z;
-		vb[7] = vb[15] = vb[23] = attrib->texcoord.w;
+		vb[2] = vb[6] = vb[10] = attrib->texcoord.z;
+		vb[3] = vb[7] = vb[11] = attrib->texcoord.w;
 		/* fall through */
 	case UTIL_BLITTER_ATTRIB_TEXCOORD_XY:
-		vb[4] = attrib->texcoord.x1;
+		vb[0] = attrib->texcoord.x1;
+		vb[1] = attrib->texcoord.y1;
+		vb[4] = attrib->texcoord.x2;
 		vb[5] = attrib->texcoord.y1;
-		vb[12] = attrib->texcoord.x1;
-		vb[13] = attrib->texcoord.y2;
-		vb[20] = attrib->texcoord.x2;
-		vb[21] = attrib->texcoord.y2;
+		vb[8] = attrib->texcoord.x2;
+		vb[9] = attrib->texcoord.y2;
 		break;
 	default:; /* Nothing to do. */
 	}
 
 	/* draw */
 	struct pipe_vertex_buffer vbuffer = {};
 	vbuffer.buffer.resource = buf;
-	vbuffer.stride = 2 * 4 * sizeof(float); /* vertex size */
+	vbuffer.stride = 4 * sizeof(float); /* vertex size */
 	vbuffer.buffer_offset = offset;
 
 	rctx->b.set_vertex_buffers(&rctx->b, blitter->vb_slot, 1, &vbuffer);
 	util_draw_arrays_instanced(&rctx->b, R600_PRIM_RECTANGLE_LIST, 0, 3,
 				   0, num_instances);
 	pipe_resource_reference(&buf, NULL);
 }
 
 static void r600_dma_emit_wait_idle(struct r600_common_context *rctx)
 {
-- 
2.7.4



More information about the mesa-dev mailing list