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, ¶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_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), + ¶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_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), + ¶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->blorp, ¶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 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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev