diff options
author | Nanley Chery <nanley.g.chery@intel.com> | 2018-09-04 14:26:45 -0700 |
---|---|---|
committer | Nanley Chery <nanleychery@gmail.com> | 2019-06-27 16:10:44 +0000 |
commit | 9a53fde65c9f20b4d7a63dce0b41f730be32da32 (patch) | |
tree | b52bc4270614d082b3b4ba36f0eb99778f172752 | |
parent | 4c702e67423fe2b0514df67531c5e35192f9d739 (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.h | 6 | ||||
-rw-r--r-- | src/intel/blorp/blorp_blit.c | 156 | ||||
-rw-r--r-- | src/intel/blorp/blorp_priv.h | 1 |
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, ¶ms, &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), + ¶ms->wm_prog_kernel, ¶ms->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), + ¶ms->wm_prog_kernel, ¶ms->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(¶ms); + + /* Create uncompressed views of the surfaces */ + brw_blorp_surface_info_init(batch->blorp, ¶ms.src, src_surf, level, + layer, ISL_FORMAT_UNSUPPORTED, false); + brw_blorp_surface_info_init(batch->blorp, ¶ms.dst, dst_surf, level, + layer, ISL_FORMAT_UNSUPPORTED, true); + blorp_surf_convert_to_uncompressed(batch->blorp->isl_dev, ¶ms.src, + NULL, NULL, NULL, NULL); + blorp_surf_convert_to_uncompressed(batch->blorp->isl_dev, ¶ms.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, ¶ms)) + 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, ¶ms); +} + 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 |