[Mesa-dev] [PATCH 5/9] intel/blorp_blit: Add blorp_copy_astc_wa

Nanley Chery nanleychery at gmail.com
Wed Sep 26 23:31:07 UTC 2018


Add a function which copies blocks from one ASTC surface to another,
patching them up as necessary.
---
 src/intel/blorp/blorp.h      |   6 ++
 src/intel/blorp/blorp_blit.c | 153 +++++++++++++++++++++++++++++++++++
 src/intel/blorp/blorp_priv.h |   1 +
 3 files changed, 160 insertions(+)

diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h
index ee343a4a6bb..67df3ff26b0 100644
--- a/src/intel/blorp/blorp.h
+++ b/src/intel/blorp/blorp.h
@@ -152,6 +152,12 @@ blorp_copy(struct blorp_batch *batch,
            uint32_t dst_x, uint32_t dst_y,
            uint32_t src_width, uint32_t src_height);
 
+void
+blorp_copy_astc_wa(struct blorp_batch *batch,
+                   const struct blorp_surf *src_surf,
+                   const struct blorp_surf *dst_surf,
+                   unsigned src_level, unsigned src_layer);
+
 void
 blorp_buffer_copy(struct blorp_batch *batch,
                   struct blorp_address src,
diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c
index 7c4e569e44c..442f7227c0a 100644
--- a/src/intel/blorp/blorp_blit.c
+++ b/src/intel/blorp/blorp_blit.c
@@ -2658,6 +2658,159 @@ blorp_copy(struct blorp_batch *batch,
    do_blorp_blit(batch, &params, &wm_prog_key, &coords);
 }
 
+/* Try to add a pixel shader kernel for the ASTC WA to params. */
+static bool
+get_copy_astc_wa_kernel(struct blorp_context *blorp,
+                        struct blorp_params *params)
+{
+   /* Use the shader in our cache if it already exists. */
+   enum blorp_shader_type astc_wa_key = BLORP_SHADER_TYPE_ASTC_VOID_EXTENT_WA;
+   if (blorp->lookup_shader(blorp, &astc_wa_key, sizeof(astc_wa_key),
+                            &params->wm_prog_kernel, &params->wm_prog_data))
+      return true;
+
+   /* Otherwise, build the kernel now. */
+   void *mem_ctx = ralloc_context(NULL);
+
+   const unsigned *program;
+   struct brw_wm_prog_data prog_data;
+
+   nir_builder b;
+   nir_builder_init_simple_shader(&b, mem_ctx, MESA_SHADER_FRAGMENT, NULL);
+   b.shader->info.name =
+      ralloc_strdup(b.shader, "BLORP-ASTC-void-extent-wa-copy");
+
+   /* Input: Perform a texelfetch on the 2D RGBA32UI texture */
+   nir_ssa_def *frag_coord_u = nir_f2i32(&b, blorp_nir_frag_coord(&b));
+   nir_ssa_def *pos = nir_vec2(&b, nir_channel(&b, frag_coord_u, 0),
+                                   nir_channel(&b, frag_coord_u, 1));
+   nir_tex_instr *tex = nir_tex_instr_create(b.shader, 2);
+   nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL);
+
+   tex->texture_index = 0;
+   tex->sampler_index = 0;
+
+   tex->op = nir_texop_txf;
+   tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
+   tex->dest_type = nir_type_uint;
+   tex->src[0].src_type = nir_tex_src_coord;
+   tex->src[0].src = nir_src_for_ssa(pos);
+   tex->coord_components = 2;
+   tex->src[1].src_type = nir_tex_src_lod;
+   tex->src[1].src = nir_src_for_ssa(nir_imm_int(&b, 0));
+
+   nir_builder_instr_insert(&b, &tex->instr);
+
+   /* Output: Declare the fragment color */
+   nir_variable *frag_color =
+      nir_variable_create(b.shader, nir_var_shader_out,
+                          glsl_uvec4_type(), "gl_FragColor");
+   frag_color->data.location = FRAG_RESULT_COLOR;
+
+   /* Main: Patch up the fetched block as needed.
+    *
+    * An ASTC block is stored in little endian mode. The byte that contains
+    * bits 0..7 is stored at the lower address in memory.
+    *
+    * The low 12 bits contain the header which can indicate an LDR void-extent
+    * block.
+    *
+    * If this is such a block, the high 64 bits contain 4 UNORM16s which must
+    * be set to 0 if their values are less than 4.
+    *
+    * The PRMs describe formats as being stored in little-endian pixel order.
+    * Since we're viewing this texture as an RGBA32_UINT, this means R will
+    * contain bits 31:0 of the ASTC block, G will contain 63:32, and so on.
+    */
+
+   /* Check if the header indicates an LDR void-extent block */
+   nir_ssa_def *header = nir_iand(&b, nir_channel(&b, &tex->dest.ssa, 0),
+                                      nir_imm_int(&b, 0xFFF));
+   nir_ssa_def *ve_header = nir_imm_int(&b, 0xDFC);
+   nir_if *if_stmt = nir_if_create(b.shader);
+   if_stmt->condition = nir_src_for_ssa(nir_ieq(&b, header, ve_header));
+   nir_cf_node_insert(b.cursor, &if_stmt->cf_node);
+   b.cursor = nir_after_cf_list(&if_stmt->then_list);
+   
+   /* Go from AB32 to ABGR16 */
+   nir_ssa_def *AB32 = nir_vec2(&b, nir_channel(&b, &tex->dest.ssa, 3),
+                                    nir_channel(&b, &tex->dest.ssa, 2));
+   nir_ssa_def *ABGR16 = nir_format_bitcast_uvec_unmasked(&b, AB32, 32, 16);
+
+
+   /* Set the channels to 0 if less than 4. */
+   nir_ssa_def *chan_ge_4 = nir_ige(&b, ABGR16, nir_imm_ivec4(&b, 4, 4, 4, 4));
+   nir_ssa_def *ABGR16_mod = nir_iand(&b, ABGR16, chan_ge_4);
+
+
+   /* Store the modified block */
+   nir_ssa_def *AB32_mod =
+      nir_format_bitcast_uvec_unmasked(&b, ABGR16_mod, 16, 32);
+   nir_ssa_def *color = nir_vec4(&b, nir_channel(&b, &tex->dest.ssa, 0),
+                                     nir_channel(&b, &tex->dest.ssa, 1),
+                                     nir_channel(&b, AB32_mod, 1),
+                                     nir_channel(&b, AB32_mod, 0));
+   nir_store_var(&b, frag_color, color, 0xf);
+
+   b.cursor = nir_after_cf_list(&if_stmt->else_list);
+
+   nir_store_var(&b, frag_color, &tex->dest.ssa, 0xf);
+
+   b.cursor = nir_after_cf_node(&if_stmt->cf_node);
+
+   /* Compile the kernel */
+   struct brw_wm_prog_key wm_key;
+   brw_blorp_init_wm_prog_key(&wm_key);
+   program = blorp_compile_fs(blorp, mem_ctx, b.shader, &wm_key, false,
+                              &prog_data);
+
+   /* Upload the kernel to our cache and write it to params. */
+   bool result =
+      blorp->upload_shader(blorp, &wm_key, sizeof(wm_key),
+                           program, prog_data.base.program_size,
+                           &prog_data.base, sizeof(prog_data),
+                           &params->wm_prog_kernel, &params->wm_prog_data);
+
+   ralloc_free(mem_ctx);
+   return result;
+}
+
+void
+blorp_copy_astc_wa(struct blorp_batch *batch,
+                   const struct blorp_surf *src_surf,
+                   const struct blorp_surf *dst_surf,
+                   unsigned level, unsigned layer)
+{
+   struct blorp_params params;
+   blorp_params_init(&params);
+
+   /* Create uncompressed views of the surfaces */
+   brw_blorp_surface_info_init(batch->blorp, &params.src, src_surf, level,
+                               layer, ISL_FORMAT_UNSUPPORTED, false);
+   brw_blorp_surface_info_init(batch->blorp, &params.dst, dst_surf, level,
+                               layer, ISL_FORMAT_UNSUPPORTED, true);
+   blorp_surf_convert_to_uncompressed(batch->blorp->isl_dev, &params.src,
+                                      NULL, NULL, NULL, NULL);
+   blorp_surf_convert_to_uncompressed(batch->blorp->isl_dev, &params.dst,
+                                      NULL, NULL, NULL, NULL);
+   params.dst.view.format = params.dst.surf.format;
+   params.src.view.format = params.src.surf.format;
+
+   /* Like other BLORP calls, bail if we can't get a kernel.
+    * TODO: Better error handling?
+    */
+   if (!get_copy_astc_wa_kernel(batch->blorp, &params))
+      return;
+
+   /* Set the primitive rectangle */
+   params.x0 = 0;
+   params.y0 = 0;
+   params.x1 = params.src.surf.logical_level0_px.width;
+   params.y1 = params.src.surf.logical_level0_px.height;
+
+   batch->blorp->exec(batch, &params);
+}
+
 static enum isl_format
 isl_format_for_size(unsigned size_B)
 {
diff --git a/src/intel/blorp/blorp_priv.h b/src/intel/blorp/blorp_priv.h
index a6aa2aa4151..3c43f5ec716 100644
--- a/src/intel/blorp/blorp_priv.h
+++ b/src/intel/blorp/blorp_priv.h
@@ -222,6 +222,7 @@ enum blorp_shader_type {
    BLORP_SHADER_TYPE_MCS_PARTIAL_RESOLVE,
    BLORP_SHADER_TYPE_LAYER_OFFSET_VS,
    BLORP_SHADER_TYPE_GEN4_SF,
+   BLORP_SHADER_TYPE_ASTC_VOID_EXTENT_WA,
 };
 
 struct brw_blorp_blit_prog_key
-- 
2.19.0



More information about the mesa-dev mailing list