summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanley Chery <nanley.g.chery@intel.com>2018-09-04 14:26:45 -0700
committerNanley Chery <nanleychery@gmail.com>2019-06-27 16:10:44 +0000
commit9a53fde65c9f20b4d7a63dce0b41f730be32da32 (patch)
treeb52bc4270614d082b3b4ba36f0eb99778f172752
parent4c702e67423fe2b0514df67531c5e35192f9d739 (diff)
intel/blorp_blit: Add blorp_copy_astc_wa()
Add a function which copies blocks from one ASTC surface to another, patching them up as necessary.
-rw-r--r--src/intel/blorp/blorp.h6
-rw-r--r--src/intel/blorp/blorp_blit.c156
-rw-r--r--src/intel/blorp/blorp_priv.h1
3 files changed, 163 insertions, 0 deletions
diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h
index df48e91cecc..dd6ce8f2fcd 100644
--- a/src/intel/blorp/blorp.h
+++ b/src/intel/blorp/blorp.h
@@ -155,6 +155,12 @@ blorp_copy(struct blorp_batch *batch,
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,
struct blorp_address dst,
diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c
index c0b2b5e6533..7f6d4f7b959 100644
--- a/src/intel/blorp/blorp_blit.c
+++ b/src/intel/blorp/blorp_blit.c
@@ -2717,6 +2717,162 @@ 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_batch *batch,
+ struct blorp_params *params)
+{
+ struct blorp_context *blorp = batch->blorp;
+
+ /* 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(batch, &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_ige32(&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(batch, &astc_wa_key, sizeof(astc_wa_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, &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 02c33c6bac5..ade31b5a8b0 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