1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2016 Red Hat. 3bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * based in part on anv driver which is: 6bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation 7bf215546Sopenharmony_ci * 8bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 9bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 10bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 11bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 13bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 16bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 17bf215546Sopenharmony_ci * Software. 18bf215546Sopenharmony_ci * 19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 25bf215546Sopenharmony_ci * IN THE SOFTWARE. 26bf215546Sopenharmony_ci */ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "radv_shader.h" 29bf215546Sopenharmony_ci#include "nir/nir.h" 30bf215546Sopenharmony_ci#include "nir/nir_builder.h" 31bf215546Sopenharmony_ci#include "nir/nir_xfb_info.h" 32bf215546Sopenharmony_ci#include "spirv/nir_spirv.h" 33bf215546Sopenharmony_ci#include "util/memstream.h" 34bf215546Sopenharmony_ci#include "util/mesa-sha1.h" 35bf215546Sopenharmony_ci#include "util/u_atomic.h" 36bf215546Sopenharmony_ci#include "radv_debug.h" 37bf215546Sopenharmony_ci#include "radv_meta.h" 38bf215546Sopenharmony_ci#include "radv_private.h" 39bf215546Sopenharmony_ci#include "radv_shader_args.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "util/debug.h" 42bf215546Sopenharmony_ci#include "ac_binary.h" 43bf215546Sopenharmony_ci#include "ac_nir.h" 44bf215546Sopenharmony_ci#ifndef _WIN32 45bf215546Sopenharmony_ci#include "ac_rtld.h" 46bf215546Sopenharmony_ci#endif 47bf215546Sopenharmony_ci#include "aco_interface.h" 48bf215546Sopenharmony_ci#include "sid.h" 49bf215546Sopenharmony_ci#include "vk_format.h" 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci#include "aco_shader_info.h" 52bf215546Sopenharmony_ci#include "radv_aco_shader_info.h" 53bf215546Sopenharmony_ci#ifdef LLVM_AVAILABLE 54bf215546Sopenharmony_ci#include "ac_llvm_util.h" 55bf215546Sopenharmony_ci#endif 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_cistatic void 58bf215546Sopenharmony_ciget_nir_options_for_stage(struct radv_physical_device *device, gl_shader_stage stage) 59bf215546Sopenharmony_ci{ 60bf215546Sopenharmony_ci bool split_fma = (stage <= MESA_SHADER_GEOMETRY || stage == MESA_SHADER_MESH) && 61bf215546Sopenharmony_ci device->instance->debug_flags & RADV_DEBUG_SPLIT_FMA; 62bf215546Sopenharmony_ci device->nir_options[stage] = (nir_shader_compiler_options){ 63bf215546Sopenharmony_ci .vertex_id_zero_based = true, 64bf215546Sopenharmony_ci .lower_scmp = true, 65bf215546Sopenharmony_ci .lower_flrp16 = true, 66bf215546Sopenharmony_ci .lower_flrp32 = true, 67bf215546Sopenharmony_ci .lower_flrp64 = true, 68bf215546Sopenharmony_ci .lower_device_index_to_zero = true, 69bf215546Sopenharmony_ci .lower_fdiv = true, 70bf215546Sopenharmony_ci .lower_fmod = true, 71bf215546Sopenharmony_ci .lower_ineg = true, 72bf215546Sopenharmony_ci .lower_bitfield_insert_to_bitfield_select = true, 73bf215546Sopenharmony_ci .lower_bitfield_extract = true, 74bf215546Sopenharmony_ci .lower_pack_snorm_4x8 = true, 75bf215546Sopenharmony_ci .lower_pack_unorm_4x8 = true, 76bf215546Sopenharmony_ci .lower_pack_half_2x16 = true, 77bf215546Sopenharmony_ci .lower_pack_64_2x32 = true, 78bf215546Sopenharmony_ci .lower_pack_64_4x16 = true, 79bf215546Sopenharmony_ci .lower_pack_32_2x16 = true, 80bf215546Sopenharmony_ci .lower_unpack_snorm_2x16 = true, 81bf215546Sopenharmony_ci .lower_unpack_snorm_4x8 = true, 82bf215546Sopenharmony_ci .lower_unpack_unorm_2x16 = true, 83bf215546Sopenharmony_ci .lower_unpack_unorm_4x8 = true, 84bf215546Sopenharmony_ci .lower_unpack_half_2x16 = true, 85bf215546Sopenharmony_ci .lower_ffma16 = split_fma || device->rad_info.gfx_level < GFX9, 86bf215546Sopenharmony_ci .lower_ffma32 = split_fma || device->rad_info.gfx_level < GFX10_3, 87bf215546Sopenharmony_ci .lower_ffma64 = split_fma, 88bf215546Sopenharmony_ci .lower_fpow = true, 89bf215546Sopenharmony_ci .lower_mul_2x32_64 = true, 90bf215546Sopenharmony_ci .lower_rotate = true, 91bf215546Sopenharmony_ci .lower_iadd_sat = device->rad_info.gfx_level <= GFX8, 92bf215546Sopenharmony_ci .lower_hadd = true, 93bf215546Sopenharmony_ci .lower_mul_32x16 = true, 94bf215546Sopenharmony_ci .has_fsub = true, 95bf215546Sopenharmony_ci .has_isub = true, 96bf215546Sopenharmony_ci .has_sdot_4x8 = device->rad_info.has_accelerated_dot_product, 97bf215546Sopenharmony_ci .has_udot_4x8 = device->rad_info.has_accelerated_dot_product, 98bf215546Sopenharmony_ci .has_dot_2x16 = device->rad_info.has_accelerated_dot_product, 99bf215546Sopenharmony_ci .use_scoped_barrier = true, 100bf215546Sopenharmony_ci#ifdef LLVM_AVAILABLE 101bf215546Sopenharmony_ci .has_fmulz = !device->use_llvm || LLVM_VERSION_MAJOR >= 12, 102bf215546Sopenharmony_ci#else 103bf215546Sopenharmony_ci .has_fmulz = true, 104bf215546Sopenharmony_ci#endif 105bf215546Sopenharmony_ci .max_unroll_iterations = 32, 106bf215546Sopenharmony_ci .max_unroll_iterations_aggressive = 128, 107bf215546Sopenharmony_ci .use_interpolated_input_intrinsics = true, 108bf215546Sopenharmony_ci .vectorize_vec2_16bit = true, 109bf215546Sopenharmony_ci /* nir_lower_int64() isn't actually called for the LLVM backend, 110bf215546Sopenharmony_ci * but this helps the loop unrolling heuristics. */ 111bf215546Sopenharmony_ci .lower_int64_options = nir_lower_imul64 | nir_lower_imul_high64 | nir_lower_imul_2x32_64 | 112bf215546Sopenharmony_ci nir_lower_divmod64 | nir_lower_minmax64 | nir_lower_iabs64 | 113bf215546Sopenharmony_ci nir_lower_iadd_sat64, 114bf215546Sopenharmony_ci .lower_doubles_options = nir_lower_drcp | nir_lower_dsqrt | nir_lower_drsq | nir_lower_ddiv, 115bf215546Sopenharmony_ci .divergence_analysis_options = nir_divergence_view_index_uniform, 116bf215546Sopenharmony_ci }; 117bf215546Sopenharmony_ci} 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_civoid 120bf215546Sopenharmony_ciradv_get_nir_options(struct radv_physical_device *device) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci for (gl_shader_stage stage = MESA_SHADER_VERTEX; stage < MESA_VULKAN_SHADER_STAGES; stage++) 123bf215546Sopenharmony_ci get_nir_options_for_stage(device, stage); 124bf215546Sopenharmony_ci} 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_cistatic uint8_t 127bf215546Sopenharmony_civectorize_vec2_16bit(const nir_instr *instr, const void *_) 128bf215546Sopenharmony_ci{ 129bf215546Sopenharmony_ci if (instr->type != nir_instr_type_alu) 130bf215546Sopenharmony_ci return 0; 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci const nir_alu_instr *alu = nir_instr_as_alu(instr); 133bf215546Sopenharmony_ci const unsigned bit_size = alu->dest.dest.ssa.bit_size; 134bf215546Sopenharmony_ci if (bit_size == 16) 135bf215546Sopenharmony_ci return 2; 136bf215546Sopenharmony_ci else 137bf215546Sopenharmony_ci return 1; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_cistatic bool 141bf215546Sopenharmony_ciis_meta_shader(nir_shader *nir) 142bf215546Sopenharmony_ci{ 143bf215546Sopenharmony_ci return nir && nir->info.internal; 144bf215546Sopenharmony_ci} 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_cibool 147bf215546Sopenharmony_ciradv_can_dump_shader(struct radv_device *device, nir_shader *nir, bool meta_shader) 148bf215546Sopenharmony_ci{ 149bf215546Sopenharmony_ci if (!(device->instance->debug_flags & RADV_DEBUG_DUMP_SHADERS)) 150bf215546Sopenharmony_ci return false; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci if ((is_meta_shader(nir) || meta_shader) && 153bf215546Sopenharmony_ci !(device->instance->debug_flags & RADV_DEBUG_DUMP_META_SHADERS)) 154bf215546Sopenharmony_ci return false; 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci return true; 157bf215546Sopenharmony_ci} 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_cibool 160bf215546Sopenharmony_ciradv_can_dump_shader_stats(struct radv_device *device, nir_shader *nir) 161bf215546Sopenharmony_ci{ 162bf215546Sopenharmony_ci /* Only dump non-meta shader stats. */ 163bf215546Sopenharmony_ci return device->instance->debug_flags & RADV_DEBUG_DUMP_SHADER_STATS && !is_meta_shader(nir); 164bf215546Sopenharmony_ci} 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_civoid 167bf215546Sopenharmony_ciradv_optimize_nir(struct nir_shader *shader, bool optimize_conservatively, bool allow_copies) 168bf215546Sopenharmony_ci{ 169bf215546Sopenharmony_ci bool progress; 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci do { 172bf215546Sopenharmony_ci progress = false; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_split_array_vars, nir_var_function_temp); 175bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_shrink_vec_array_vars, nir_var_function_temp); 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci if (allow_copies) { 178bf215546Sopenharmony_ci /* Only run this pass in the first call to 179bf215546Sopenharmony_ci * radv_optimize_nir. Later calls assume that we've 180bf215546Sopenharmony_ci * lowered away any copy_deref instructions and we 181bf215546Sopenharmony_ci * don't want to introduce any more. 182bf215546Sopenharmony_ci */ 183bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_find_array_copies); 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_copy_prop_vars); 187bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_dead_write_vars); 188bf215546Sopenharmony_ci NIR_PASS(_, shader, nir_lower_vars_to_ssa); 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci NIR_PASS(_, shader, nir_lower_alu_width, vectorize_vec2_16bit, NULL); 191bf215546Sopenharmony_ci NIR_PASS(_, shader, nir_lower_phis_to_scalar, true); 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_copy_prop); 194bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_remove_phis); 195bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_dce); 196bf215546Sopenharmony_ci if (nir_opt_trivial_continues(shader)) { 197bf215546Sopenharmony_ci progress = true; 198bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_copy_prop); 199bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_remove_phis); 200bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_dce); 201bf215546Sopenharmony_ci } 202bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_if, 203bf215546Sopenharmony_ci nir_opt_if_aggressive_last_continue | nir_opt_if_optimize_phi_true_false); 204bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_dead_cf); 205bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_cse); 206bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_peephole_select, 8, true, true); 207bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_constant_folding); 208bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_algebraic); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_undef); 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci if (shader->options->max_unroll_iterations) { 213bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_loop_unroll); 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci } while (progress && !optimize_conservatively); 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_shrink_vectors); 218bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_remove_dead_variables, 219bf215546Sopenharmony_ci nir_var_function_temp | nir_var_shader_in | nir_var_shader_out, NULL); 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci if (shader->info.stage == MESA_SHADER_FRAGMENT && 222bf215546Sopenharmony_ci (shader->info.fs.uses_discard || shader->info.fs.uses_demote)) { 223bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_conditional_discard); 224bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_move_discards_to_top); 225bf215546Sopenharmony_ci } 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci NIR_PASS(progress, shader, nir_opt_move, nir_move_load_ubo); 228bf215546Sopenharmony_ci} 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_civoid 231bf215546Sopenharmony_ciradv_optimize_nir_algebraic(nir_shader *nir, bool opt_offsets) 232bf215546Sopenharmony_ci{ 233bf215546Sopenharmony_ci bool more_algebraic = true; 234bf215546Sopenharmony_ci while (more_algebraic) { 235bf215546Sopenharmony_ci more_algebraic = false; 236bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_copy_prop); 237bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_dce); 238bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_constant_folding); 239bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_cse); 240bf215546Sopenharmony_ci NIR_PASS(more_algebraic, nir, nir_opt_algebraic); 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci if (opt_offsets) { 244bf215546Sopenharmony_ci static const nir_opt_offsets_options offset_options = { 245bf215546Sopenharmony_ci .uniform_max = 0, 246bf215546Sopenharmony_ci .buffer_max = ~0, 247bf215546Sopenharmony_ci .shared_max = ~0, 248bf215546Sopenharmony_ci }; 249bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_offsets, &offset_options); 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci /* Do late algebraic optimization to turn add(a, 253bf215546Sopenharmony_ci * neg(b)) back into subs, then the mandatory cleanup 254bf215546Sopenharmony_ci * after algebraic. Note that it may produce fnegs, 255bf215546Sopenharmony_ci * and if so then we need to keep running to squash 256bf215546Sopenharmony_ci * fneg(fneg(a)). 257bf215546Sopenharmony_ci */ 258bf215546Sopenharmony_ci bool more_late_algebraic = true; 259bf215546Sopenharmony_ci while (more_late_algebraic) { 260bf215546Sopenharmony_ci more_late_algebraic = false; 261bf215546Sopenharmony_ci NIR_PASS(more_late_algebraic, nir, nir_opt_algebraic_late); 262bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_constant_folding); 263bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_copy_prop); 264bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_dce); 265bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_cse); 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci} 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_cistatic void 270bf215546Sopenharmony_cishared_var_info(const struct glsl_type *type, unsigned *size, unsigned *align) 271bf215546Sopenharmony_ci{ 272bf215546Sopenharmony_ci assert(glsl_type_is_vector_or_scalar(type)); 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci uint32_t comp_size = glsl_type_is_boolean(type) ? 4 : glsl_get_bit_size(type) / 8; 275bf215546Sopenharmony_ci unsigned length = glsl_get_vector_elements(type); 276bf215546Sopenharmony_ci *size = comp_size * length, *align = comp_size; 277bf215546Sopenharmony_ci} 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_cistruct radv_shader_debug_data { 280bf215546Sopenharmony_ci struct radv_device *device; 281bf215546Sopenharmony_ci const struct vk_object_base *object; 282bf215546Sopenharmony_ci}; 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_cistatic void 285bf215546Sopenharmony_ciradv_spirv_nir_debug(void *private_data, enum nir_spirv_debug_level level, size_t spirv_offset, 286bf215546Sopenharmony_ci const char *message) 287bf215546Sopenharmony_ci{ 288bf215546Sopenharmony_ci struct radv_shader_debug_data *debug_data = private_data; 289bf215546Sopenharmony_ci struct radv_instance *instance = debug_data->device->instance; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci static const VkDebugReportFlagsEXT vk_flags[] = { 292bf215546Sopenharmony_ci [NIR_SPIRV_DEBUG_LEVEL_INFO] = VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 293bf215546Sopenharmony_ci [NIR_SPIRV_DEBUG_LEVEL_WARNING] = VK_DEBUG_REPORT_WARNING_BIT_EXT, 294bf215546Sopenharmony_ci [NIR_SPIRV_DEBUG_LEVEL_ERROR] = VK_DEBUG_REPORT_ERROR_BIT_EXT, 295bf215546Sopenharmony_ci }; 296bf215546Sopenharmony_ci char buffer[256]; 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci snprintf(buffer, sizeof(buffer), "SPIR-V offset %lu: %s", (unsigned long)spirv_offset, message); 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci vk_debug_report(&instance->vk, vk_flags[level], debug_data->object, 0, 0, "radv", buffer); 301bf215546Sopenharmony_ci} 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_cistatic void 304bf215546Sopenharmony_ciradv_compiler_debug(void *private_data, enum aco_compiler_debug_level level, const char *message) 305bf215546Sopenharmony_ci{ 306bf215546Sopenharmony_ci struct radv_shader_debug_data *debug_data = private_data; 307bf215546Sopenharmony_ci struct radv_instance *instance = debug_data->device->instance; 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci static const VkDebugReportFlagsEXT vk_flags[] = { 310bf215546Sopenharmony_ci [ACO_COMPILER_DEBUG_LEVEL_PERFWARN] = VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, 311bf215546Sopenharmony_ci [ACO_COMPILER_DEBUG_LEVEL_ERROR] = VK_DEBUG_REPORT_ERROR_BIT_EXT, 312bf215546Sopenharmony_ci }; 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci /* VK_DEBUG_REPORT_DEBUG_BIT_EXT specifies diagnostic information 315bf215546Sopenharmony_ci * from the implementation and layers. 316bf215546Sopenharmony_ci */ 317bf215546Sopenharmony_ci vk_debug_report(&instance->vk, vk_flags[level] | VK_DEBUG_REPORT_DEBUG_BIT_EXT, 318bf215546Sopenharmony_ci NULL, 0, 0, "radv", message); 319bf215546Sopenharmony_ci} 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_cistatic bool 322bf215546Sopenharmony_cilower_intrinsics(nir_shader *nir, const struct radv_pipeline_key *key) 323bf215546Sopenharmony_ci{ 324bf215546Sopenharmony_ci nir_function_impl *entry = nir_shader_get_entrypoint(nir); 325bf215546Sopenharmony_ci bool progress = false; 326bf215546Sopenharmony_ci nir_builder b; 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci nir_builder_init(&b, entry); 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci nir_foreach_block (block, entry) { 331bf215546Sopenharmony_ci nir_foreach_instr_safe (instr, block) { 332bf215546Sopenharmony_ci if (instr->type != nir_instr_type_intrinsic) 333bf215546Sopenharmony_ci continue; 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 336bf215546Sopenharmony_ci b.cursor = nir_before_instr(&intrin->instr); 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci nir_ssa_def *def = NULL; 339bf215546Sopenharmony_ci switch (intrin->intrinsic) { 340bf215546Sopenharmony_ci case nir_intrinsic_is_sparse_texels_resident: 341bf215546Sopenharmony_ci def = nir_ieq_imm(&b, intrin->src[0].ssa, 0); 342bf215546Sopenharmony_ci break; 343bf215546Sopenharmony_ci case nir_intrinsic_sparse_residency_code_and: 344bf215546Sopenharmony_ci def = nir_ior(&b, intrin->src[0].ssa, intrin->src[1].ssa); 345bf215546Sopenharmony_ci break; 346bf215546Sopenharmony_ci case nir_intrinsic_load_view_index: 347bf215546Sopenharmony_ci if (key->has_multiview_view_index) 348bf215546Sopenharmony_ci continue; 349bf215546Sopenharmony_ci def = nir_imm_zero(&b, 1, 32); 350bf215546Sopenharmony_ci break; 351bf215546Sopenharmony_ci default: 352bf215546Sopenharmony_ci continue; 353bf215546Sopenharmony_ci } 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci nir_ssa_def_rewrite_uses(&intrin->dest.ssa, def); 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci nir_instr_remove(instr); 358bf215546Sopenharmony_ci progress = true; 359bf215546Sopenharmony_ci } 360bf215546Sopenharmony_ci } 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci if (progress) 363bf215546Sopenharmony_ci nir_metadata_preserve(entry, nir_metadata_block_index | nir_metadata_dominance); 364bf215546Sopenharmony_ci else 365bf215546Sopenharmony_ci nir_metadata_preserve(entry, nir_metadata_all); 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci return progress; 368bf215546Sopenharmony_ci} 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_cistatic bool 371bf215546Sopenharmony_ciradv_lower_primitive_shading_rate(nir_shader *nir, enum amd_gfx_level gfx_level) 372bf215546Sopenharmony_ci{ 373bf215546Sopenharmony_ci nir_function_impl *impl = nir_shader_get_entrypoint(nir); 374bf215546Sopenharmony_ci bool progress = false; 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci nir_builder b; 377bf215546Sopenharmony_ci nir_builder_init(&b, impl); 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci /* Iterate in reverse order since there should be only one deref store to PRIMITIVE_SHADING_RATE 380bf215546Sopenharmony_ci * after lower_io_to_temporaries for vertex shaders. 381bf215546Sopenharmony_ci */ 382bf215546Sopenharmony_ci nir_foreach_block_reverse(block, impl) { 383bf215546Sopenharmony_ci nir_foreach_instr_reverse(instr, block) { 384bf215546Sopenharmony_ci if (instr->type != nir_instr_type_intrinsic) 385bf215546Sopenharmony_ci continue; 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); 388bf215546Sopenharmony_ci if (intr->intrinsic != nir_intrinsic_store_deref) 389bf215546Sopenharmony_ci continue; 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci nir_variable *var = nir_intrinsic_get_var(intr, 0); 392bf215546Sopenharmony_ci if (var->data.mode != nir_var_shader_out || 393bf215546Sopenharmony_ci var->data.location != VARYING_SLOT_PRIMITIVE_SHADING_RATE) 394bf215546Sopenharmony_ci continue; 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci b.cursor = nir_before_instr(instr); 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci nir_ssa_def *val = nir_ssa_for_src(&b, intr->src[1], 1); 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci /* x_rate = (shadingRate & (Horizontal2Pixels | Horizontal4Pixels)) ? 0x1 : 0x0; */ 401bf215546Sopenharmony_ci nir_ssa_def *x_rate = nir_iand_imm(&b, val, 12); 402bf215546Sopenharmony_ci x_rate = nir_b2i32(&b, nir_ine_imm(&b, x_rate, 0)); 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci /* y_rate = (shadingRate & (Vertical2Pixels | Vertical4Pixels)) ? 0x1 : 0x0; */ 405bf215546Sopenharmony_ci nir_ssa_def *y_rate = nir_iand_imm(&b, val, 3); 406bf215546Sopenharmony_ci y_rate = nir_b2i32(&b, nir_ine_imm(&b, y_rate, 0)); 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci nir_ssa_def *out = NULL; 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci /* MS: 411bf215546Sopenharmony_ci * Primitive shading rate is a per-primitive output, it is 412bf215546Sopenharmony_ci * part of the second channel of the primitive export. 413bf215546Sopenharmony_ci * Bits [28:31] = VRS rate 414bf215546Sopenharmony_ci * This will be added to the other bits of that channel in the backend. 415bf215546Sopenharmony_ci * 416bf215546Sopenharmony_ci * VS, TES, GS: 417bf215546Sopenharmony_ci * Primitive shading rate is a per-vertex output pos export. 418bf215546Sopenharmony_ci * Bits [2:5] = VRS rate 419bf215546Sopenharmony_ci * HW shading rate = (xRate << 2) | (yRate << 4) 420bf215546Sopenharmony_ci * 421bf215546Sopenharmony_ci * GFX11: 4-bit VRS_SHADING_RATE enum 422bf215546Sopenharmony_ci * GFX10: X = low 2 bits, Y = high 2 bits 423bf215546Sopenharmony_ci */ 424bf215546Sopenharmony_ci unsigned x_rate_shift = 2; 425bf215546Sopenharmony_ci unsigned y_rate_shift = 4; 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci if (gfx_level >= GFX11) { 428bf215546Sopenharmony_ci x_rate_shift = 4; 429bf215546Sopenharmony_ci y_rate_shift = 2; 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_MESH) { 432bf215546Sopenharmony_ci x_rate_shift += 26; 433bf215546Sopenharmony_ci y_rate_shift += 26; 434bf215546Sopenharmony_ci } 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci out = nir_ior(&b, nir_ishl_imm(&b, x_rate, x_rate_shift), nir_ishl_imm(&b, y_rate, y_rate_shift)); 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci nir_instr_rewrite_src(&intr->instr, &intr->src[1], nir_src_for_ssa(out)); 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci progress = true; 441bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_VERTEX) 442bf215546Sopenharmony_ci break; 443bf215546Sopenharmony_ci } 444bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_VERTEX && progress) 445bf215546Sopenharmony_ci break; 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci if (progress) 449bf215546Sopenharmony_ci nir_metadata_preserve(impl, nir_metadata_block_index | nir_metadata_dominance); 450bf215546Sopenharmony_ci else 451bf215546Sopenharmony_ci nir_metadata_preserve(impl, nir_metadata_all); 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci return progress; 454bf215546Sopenharmony_ci} 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_cibool 457bf215546Sopenharmony_ciradv_force_primitive_shading_rate(nir_shader *nir, struct radv_device *device) 458bf215546Sopenharmony_ci{ 459bf215546Sopenharmony_ci nir_function_impl *impl = nir_shader_get_entrypoint(nir); 460bf215546Sopenharmony_ci bool progress = false; 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci nir_builder b; 463bf215546Sopenharmony_ci nir_builder_init(&b, impl); 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci nir_foreach_block_reverse(block, impl) { 466bf215546Sopenharmony_ci nir_foreach_instr_reverse(instr, block) { 467bf215546Sopenharmony_ci if (instr->type != nir_instr_type_intrinsic) 468bf215546Sopenharmony_ci continue; 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); 471bf215546Sopenharmony_ci if (intr->intrinsic != nir_intrinsic_store_deref) 472bf215546Sopenharmony_ci continue; 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci nir_variable *var = nir_intrinsic_get_var(intr, 0); 475bf215546Sopenharmony_ci if (var->data.mode != nir_var_shader_out || 476bf215546Sopenharmony_ci var->data.location != VARYING_SLOT_POS) 477bf215546Sopenharmony_ci continue; 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci b.cursor = nir_after_instr(instr); 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci nir_ssa_scalar scalar_idx = nir_ssa_scalar_resolved(intr->src[1].ssa, 3); 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci /* Use coarse shading if the value of Pos.W can't be determined or if its value is != 1 484bf215546Sopenharmony_ci * (typical for non-GUI elements). 485bf215546Sopenharmony_ci */ 486bf215546Sopenharmony_ci if (!nir_ssa_scalar_is_const(scalar_idx) || 487bf215546Sopenharmony_ci nir_ssa_scalar_as_uint(scalar_idx) != 0x3f800000u) { 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci var = nir_variable_create(nir, nir_var_shader_out, glsl_int_type(), "vrs rate"); 490bf215546Sopenharmony_ci var->data.location = VARYING_SLOT_PRIMITIVE_SHADING_RATE; 491bf215546Sopenharmony_ci var->data.interpolation = INTERP_MODE_NONE; 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci nir_ssa_def *vrs_rates = nir_load_force_vrs_rates_amd(&b); 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci nir_ssa_def *pos_w = nir_channel(&b, intr->src[1].ssa, 3); 496bf215546Sopenharmony_ci nir_ssa_def *val = nir_bcsel(&b, nir_fneu(&b, pos_w, nir_imm_float(&b, 1.0f)), 497bf215546Sopenharmony_ci vrs_rates, nir_imm_int(&b, 0)); 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci nir_deref_instr *deref = nir_build_deref_var(&b, var); 500bf215546Sopenharmony_ci nir_store_deref(&b, deref, val, 0x1); 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci /* Update outputs_written to reflect that the pass added a new output. */ 503bf215546Sopenharmony_ci nir->info.outputs_written |= BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_SHADING_RATE); 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci progress = true; 506bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_VERTEX) 507bf215546Sopenharmony_ci break; 508bf215546Sopenharmony_ci } 509bf215546Sopenharmony_ci } 510bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_VERTEX && progress) 511bf215546Sopenharmony_ci break; 512bf215546Sopenharmony_ci } 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci if (progress) 515bf215546Sopenharmony_ci nir_metadata_preserve(impl, nir_metadata_block_index | nir_metadata_dominance); 516bf215546Sopenharmony_ci else 517bf215546Sopenharmony_ci nir_metadata_preserve(impl, nir_metadata_all); 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci return progress; 520bf215546Sopenharmony_ci} 521bf215546Sopenharmony_ci 522bf215546Sopenharmony_cibool 523bf215546Sopenharmony_ciradv_lower_fs_intrinsics(nir_shader *nir, const struct radv_pipeline_stage *fs_stage, 524bf215546Sopenharmony_ci const struct radv_pipeline_key *key) 525bf215546Sopenharmony_ci{ 526bf215546Sopenharmony_ci const struct radv_shader_info *info = &fs_stage->info; 527bf215546Sopenharmony_ci const struct radv_shader_args *args = &fs_stage->args; 528bf215546Sopenharmony_ci nir_function_impl *impl = nir_shader_get_entrypoint(nir); 529bf215546Sopenharmony_ci bool progress = false; 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci nir_builder b; 532bf215546Sopenharmony_ci nir_builder_init(&b, impl); 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_ci nir_foreach_block(block, impl) { 535bf215546Sopenharmony_ci nir_foreach_instr_safe(instr, block) { 536bf215546Sopenharmony_ci if (instr->type != nir_instr_type_intrinsic) 537bf215546Sopenharmony_ci continue; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 540bf215546Sopenharmony_ci b.cursor = nir_after_instr(&intrin->instr); 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci switch (intrin->intrinsic) { 543bf215546Sopenharmony_ci case nir_intrinsic_load_sample_mask_in: { 544bf215546Sopenharmony_ci uint8_t log2_ps_iter_samples; 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci if (info->ps.uses_sample_shading) { 547bf215546Sopenharmony_ci log2_ps_iter_samples = util_logbase2(key->ps.num_samples); 548bf215546Sopenharmony_ci } else { 549bf215546Sopenharmony_ci log2_ps_iter_samples = key->ps.log2_ps_iter_samples; 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci nir_ssa_def *sample_coverage = 553bf215546Sopenharmony_ci nir_load_vector_arg_amd(&b, 1, .base = args->ac.sample_coverage.arg_index); 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci nir_ssa_def *def = NULL; 556bf215546Sopenharmony_ci if (log2_ps_iter_samples) { 557bf215546Sopenharmony_ci /* gl_SampleMaskIn[0] = (SampleCoverage & (1 << gl_SampleID)). */ 558bf215546Sopenharmony_ci nir_ssa_def *sample_id = nir_load_sample_id(&b); 559bf215546Sopenharmony_ci def = nir_iand(&b, sample_coverage, nir_ishl(&b, nir_imm_int(&b, 1u), sample_id)); 560bf215546Sopenharmony_ci } else { 561bf215546Sopenharmony_ci def = sample_coverage; 562bf215546Sopenharmony_ci } 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci nir_ssa_def_rewrite_uses(&intrin->dest.ssa, def); 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci nir_instr_remove(instr); 567bf215546Sopenharmony_ci progress = true; 568bf215546Sopenharmony_ci break; 569bf215546Sopenharmony_ci } 570bf215546Sopenharmony_ci case nir_intrinsic_load_frag_coord: { 571bf215546Sopenharmony_ci if (!key->adjust_frag_coord_z) 572bf215546Sopenharmony_ci continue; 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci if (!(nir_ssa_def_components_read(&intrin->dest.ssa) & (1 << 2))) 575bf215546Sopenharmony_ci continue; 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci nir_ssa_def *frag_z = nir_channel(&b, &intrin->dest.ssa, 2); 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_ci /* adjusted_frag_z = fddx_fine(frag_z) * 0.0625 + frag_z */ 580bf215546Sopenharmony_ci nir_ssa_def *adjusted_frag_z = nir_fddx_fine(&b, frag_z); 581bf215546Sopenharmony_ci adjusted_frag_z = nir_ffma_imm1(&b, adjusted_frag_z, 0.0625f, frag_z); 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_ci /* VRS Rate X = Ancillary[2:3] */ 584bf215546Sopenharmony_ci nir_ssa_def *ancillary = 585bf215546Sopenharmony_ci nir_load_vector_arg_amd(&b, 1, .base = args->ac.ancillary.arg_index); 586bf215546Sopenharmony_ci nir_ssa_def *x_rate = nir_ubfe_imm(&b, ancillary, 2, 2); 587bf215546Sopenharmony_ci 588bf215546Sopenharmony_ci /* xRate = xRate == 0x1 ? adjusted_frag_z : frag_z. */ 589bf215546Sopenharmony_ci nir_ssa_def *cond = nir_ieq_imm(&b, x_rate, 1); 590bf215546Sopenharmony_ci frag_z = nir_bcsel(&b, cond, adjusted_frag_z, frag_z); 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ci nir_ssa_def *new_dest = nir_vector_insert_imm(&b, &intrin->dest.ssa, frag_z, 2); 593bf215546Sopenharmony_ci nir_ssa_def_rewrite_uses_after(&intrin->dest.ssa, new_dest, new_dest->parent_instr); 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci progress = true; 596bf215546Sopenharmony_ci break; 597bf215546Sopenharmony_ci } 598bf215546Sopenharmony_ci default: 599bf215546Sopenharmony_ci break; 600bf215546Sopenharmony_ci } 601bf215546Sopenharmony_ci } 602bf215546Sopenharmony_ci } 603bf215546Sopenharmony_ci 604bf215546Sopenharmony_ci if (progress) 605bf215546Sopenharmony_ci nir_metadata_preserve(impl, nir_metadata_block_index | nir_metadata_dominance); 606bf215546Sopenharmony_ci else 607bf215546Sopenharmony_ci nir_metadata_preserve(impl, nir_metadata_all); 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci return progress; 610bf215546Sopenharmony_ci} 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci/* Emulates NV_mesh_shader first_task using first_vertex. */ 613bf215546Sopenharmony_cistatic bool 614bf215546Sopenharmony_ciradv_lower_ms_workgroup_id(nir_shader *nir) 615bf215546Sopenharmony_ci{ 616bf215546Sopenharmony_ci nir_function_impl *impl = nir_shader_get_entrypoint(nir); 617bf215546Sopenharmony_ci bool progress = false; 618bf215546Sopenharmony_ci nir_builder b; 619bf215546Sopenharmony_ci nir_builder_init(&b, impl); 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_ci nir_foreach_block(block, impl) { 622bf215546Sopenharmony_ci nir_foreach_instr_safe(instr, block) { 623bf215546Sopenharmony_ci if (instr->type != nir_instr_type_intrinsic) 624bf215546Sopenharmony_ci continue; 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 627bf215546Sopenharmony_ci if (intrin->intrinsic != nir_intrinsic_load_workgroup_id) 628bf215546Sopenharmony_ci continue; 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci progress = true; 631bf215546Sopenharmony_ci b.cursor = nir_after_instr(instr); 632bf215546Sopenharmony_ci nir_ssa_def *x = nir_channel(&b, &intrin->dest.ssa, 0); 633bf215546Sopenharmony_ci nir_ssa_def *x_full = nir_iadd(&b, x, nir_load_first_vertex(&b)); 634bf215546Sopenharmony_ci nir_ssa_def *v = nir_vector_insert_imm(&b, &intrin->dest.ssa, x_full, 0); 635bf215546Sopenharmony_ci nir_ssa_def_rewrite_uses_after(&intrin->dest.ssa, v, v->parent_instr); 636bf215546Sopenharmony_ci } 637bf215546Sopenharmony_ci } 638bf215546Sopenharmony_ci 639bf215546Sopenharmony_ci nir_metadata preserved = 640bf215546Sopenharmony_ci progress ? (nir_metadata_block_index | nir_metadata_dominance) : nir_metadata_all; 641bf215546Sopenharmony_ci nir_metadata_preserve(impl, preserved); 642bf215546Sopenharmony_ci return progress; 643bf215546Sopenharmony_ci} 644bf215546Sopenharmony_ci 645bf215546Sopenharmony_cistatic bool 646bf215546Sopenharmony_ciis_sincos(const nir_instr *instr, const void *_) 647bf215546Sopenharmony_ci{ 648bf215546Sopenharmony_ci return instr->type == nir_instr_type_alu && 649bf215546Sopenharmony_ci (nir_instr_as_alu(instr)->op == nir_op_fsin || nir_instr_as_alu(instr)->op == nir_op_fcos); 650bf215546Sopenharmony_ci} 651bf215546Sopenharmony_ci 652bf215546Sopenharmony_cistatic nir_ssa_def * 653bf215546Sopenharmony_cilower_sincos(struct nir_builder *b, nir_instr *instr, void *_) 654bf215546Sopenharmony_ci{ 655bf215546Sopenharmony_ci nir_alu_instr *sincos = nir_instr_as_alu(instr); 656bf215546Sopenharmony_ci nir_ssa_def *src = nir_fmul_imm(b, nir_ssa_for_alu_src(b, sincos, 0), 0.15915493667125702); 657bf215546Sopenharmony_ci return sincos->op == nir_op_fsin ? nir_fsin_amd(b, src) : nir_fcos_amd(b, src); 658bf215546Sopenharmony_ci} 659bf215546Sopenharmony_ci 660bf215546Sopenharmony_cistatic bool 661bf215546Sopenharmony_ciis_not_xfb_output(nir_variable *var, void *data) 662bf215546Sopenharmony_ci{ 663bf215546Sopenharmony_ci if (var->data.mode != nir_var_shader_out) 664bf215546Sopenharmony_ci return true; 665bf215546Sopenharmony_ci 666bf215546Sopenharmony_ci return !var->data.explicit_xfb_buffer && 667bf215546Sopenharmony_ci !var->data.explicit_xfb_stride; 668bf215546Sopenharmony_ci} 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_cinir_shader * 671bf215546Sopenharmony_ciradv_shader_spirv_to_nir(struct radv_device *device, const struct radv_pipeline_stage *stage, 672bf215546Sopenharmony_ci const struct radv_pipeline_key *key) 673bf215546Sopenharmony_ci{ 674bf215546Sopenharmony_ci unsigned subgroup_size = 64, ballot_bit_size = 64; 675bf215546Sopenharmony_ci if (key->cs.compute_subgroup_size) { 676bf215546Sopenharmony_ci /* Only compute shaders currently support requiring a 677bf215546Sopenharmony_ci * specific subgroup size. 678bf215546Sopenharmony_ci */ 679bf215546Sopenharmony_ci assert(stage->stage == MESA_SHADER_COMPUTE); 680bf215546Sopenharmony_ci subgroup_size = key->cs.compute_subgroup_size; 681bf215546Sopenharmony_ci ballot_bit_size = key->cs.compute_subgroup_size; 682bf215546Sopenharmony_ci } 683bf215546Sopenharmony_ci 684bf215546Sopenharmony_ci nir_shader *nir; 685bf215546Sopenharmony_ci 686bf215546Sopenharmony_ci if (stage->internal_nir) { 687bf215546Sopenharmony_ci /* Some things such as our meta clear/blit code will give us a NIR 688bf215546Sopenharmony_ci * shader directly. In that case, we just ignore the SPIR-V entirely 689bf215546Sopenharmony_ci * and just use the NIR shader. We don't want to alter meta and RT 690bf215546Sopenharmony_ci * shaders IR directly, so clone it first. */ 691bf215546Sopenharmony_ci nir = nir_shader_clone(NULL, stage->internal_nir); 692bf215546Sopenharmony_ci nir_validate_shader(nir, "in internal shader"); 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_ci assert(exec_list_length(&nir->functions) == 1); 695bf215546Sopenharmony_ci } else { 696bf215546Sopenharmony_ci uint32_t *spirv = (uint32_t *)stage->spirv.data; 697bf215546Sopenharmony_ci assert(stage->spirv.size % 4 == 0); 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_ci bool dump_meta = device->instance->debug_flags & RADV_DEBUG_DUMP_META_SHADERS; 700bf215546Sopenharmony_ci if ((device->instance->debug_flags & RADV_DEBUG_DUMP_SPIRV) && 701bf215546Sopenharmony_ci (!device->app_shaders_internal || dump_meta)) 702bf215546Sopenharmony_ci radv_print_spirv(stage->spirv.data, stage->spirv.size, stderr); 703bf215546Sopenharmony_ci 704bf215546Sopenharmony_ci uint32_t num_spec_entries = 0; 705bf215546Sopenharmony_ci struct nir_spirv_specialization *spec_entries = 706bf215546Sopenharmony_ci vk_spec_info_to_nir_spirv(stage->spec_info, &num_spec_entries); 707bf215546Sopenharmony_ci struct radv_shader_debug_data spirv_debug_data = { 708bf215546Sopenharmony_ci .device = device, 709bf215546Sopenharmony_ci .object = stage->spirv.object, 710bf215546Sopenharmony_ci }; 711bf215546Sopenharmony_ci const struct spirv_to_nir_options spirv_options = { 712bf215546Sopenharmony_ci .caps = 713bf215546Sopenharmony_ci { 714bf215546Sopenharmony_ci .amd_fragment_mask = true, 715bf215546Sopenharmony_ci .amd_gcn_shader = true, 716bf215546Sopenharmony_ci .amd_image_gather_bias_lod = true, 717bf215546Sopenharmony_ci .amd_image_read_write_lod = true, 718bf215546Sopenharmony_ci .amd_shader_ballot = true, 719bf215546Sopenharmony_ci .amd_shader_explicit_vertex_parameter = true, 720bf215546Sopenharmony_ci .amd_trinary_minmax = true, 721bf215546Sopenharmony_ci .demote_to_helper_invocation = true, 722bf215546Sopenharmony_ci .derivative_group = true, 723bf215546Sopenharmony_ci .descriptor_array_dynamic_indexing = true, 724bf215546Sopenharmony_ci .descriptor_array_non_uniform_indexing = true, 725bf215546Sopenharmony_ci .descriptor_indexing = true, 726bf215546Sopenharmony_ci .device_group = true, 727bf215546Sopenharmony_ci .draw_parameters = true, 728bf215546Sopenharmony_ci .float_controls = true, 729bf215546Sopenharmony_ci .float16 = device->physical_device->rad_info.has_packed_math_16bit, 730bf215546Sopenharmony_ci .float32_atomic_add = true, 731bf215546Sopenharmony_ci .float32_atomic_min_max = true, 732bf215546Sopenharmony_ci .float64 = true, 733bf215546Sopenharmony_ci .float64_atomic_min_max = true, 734bf215546Sopenharmony_ci .geometry_streams = true, 735bf215546Sopenharmony_ci .groups = true, 736bf215546Sopenharmony_ci .image_atomic_int64 = true, 737bf215546Sopenharmony_ci .image_ms_array = true, 738bf215546Sopenharmony_ci .image_read_without_format = true, 739bf215546Sopenharmony_ci .image_write_without_format = true, 740bf215546Sopenharmony_ci .int8 = true, 741bf215546Sopenharmony_ci .int16 = true, 742bf215546Sopenharmony_ci .int64 = true, 743bf215546Sopenharmony_ci .int64_atomics = true, 744bf215546Sopenharmony_ci .integer_functions2 = true, 745bf215546Sopenharmony_ci .mesh_shading_nv = true, 746bf215546Sopenharmony_ci .min_lod = true, 747bf215546Sopenharmony_ci .multiview = true, 748bf215546Sopenharmony_ci .physical_storage_buffer_address = true, 749bf215546Sopenharmony_ci .post_depth_coverage = true, 750bf215546Sopenharmony_ci .ray_cull_mask = true, 751bf215546Sopenharmony_ci .ray_query = true, 752bf215546Sopenharmony_ci .ray_tracing = true, 753bf215546Sopenharmony_ci .ray_traversal_primitive_culling = true, 754bf215546Sopenharmony_ci .runtime_descriptor_array = true, 755bf215546Sopenharmony_ci .shader_clock = true, 756bf215546Sopenharmony_ci .shader_viewport_index_layer = true, 757bf215546Sopenharmony_ci .sparse_residency = true, 758bf215546Sopenharmony_ci .stencil_export = true, 759bf215546Sopenharmony_ci .storage_8bit = true, 760bf215546Sopenharmony_ci .storage_16bit = true, 761bf215546Sopenharmony_ci .storage_image_ms = true, 762bf215546Sopenharmony_ci .subgroup_arithmetic = true, 763bf215546Sopenharmony_ci .subgroup_ballot = true, 764bf215546Sopenharmony_ci .subgroup_basic = true, 765bf215546Sopenharmony_ci .subgroup_quad = true, 766bf215546Sopenharmony_ci .subgroup_shuffle = true, 767bf215546Sopenharmony_ci .subgroup_uniform_control_flow = true, 768bf215546Sopenharmony_ci .subgroup_vote = true, 769bf215546Sopenharmony_ci .tessellation = true, 770bf215546Sopenharmony_ci .transform_feedback = true, 771bf215546Sopenharmony_ci .variable_pointers = true, 772bf215546Sopenharmony_ci .vk_memory_model = true, 773bf215546Sopenharmony_ci .vk_memory_model_device_scope = true, 774bf215546Sopenharmony_ci .fragment_shading_rate = device->physical_device->rad_info.gfx_level >= GFX10_3, 775bf215546Sopenharmony_ci .workgroup_memory_explicit_layout = true, 776bf215546Sopenharmony_ci }, 777bf215546Sopenharmony_ci .ubo_addr_format = nir_address_format_vec2_index_32bit_offset, 778bf215546Sopenharmony_ci .ssbo_addr_format = nir_address_format_vec2_index_32bit_offset, 779bf215546Sopenharmony_ci .phys_ssbo_addr_format = nir_address_format_64bit_global, 780bf215546Sopenharmony_ci .push_const_addr_format = nir_address_format_logical, 781bf215546Sopenharmony_ci .shared_addr_format = nir_address_format_32bit_offset, 782bf215546Sopenharmony_ci .constant_addr_format = nir_address_format_64bit_global, 783bf215546Sopenharmony_ci .use_deref_buffer_array_length = true, 784bf215546Sopenharmony_ci .debug = 785bf215546Sopenharmony_ci { 786bf215546Sopenharmony_ci .func = radv_spirv_nir_debug, 787bf215546Sopenharmony_ci .private_data = &spirv_debug_data, 788bf215546Sopenharmony_ci }, 789bf215546Sopenharmony_ci }; 790bf215546Sopenharmony_ci nir = spirv_to_nir(spirv, stage->spirv.size / 4, spec_entries, num_spec_entries, stage->stage, 791bf215546Sopenharmony_ci stage->entrypoint, &spirv_options, 792bf215546Sopenharmony_ci &device->physical_device->nir_options[stage->stage]); 793bf215546Sopenharmony_ci nir->info.internal |= device->app_shaders_internal; 794bf215546Sopenharmony_ci assert(nir->info.stage == stage->stage); 795bf215546Sopenharmony_ci nir_validate_shader(nir, "after spirv_to_nir"); 796bf215546Sopenharmony_ci 797bf215546Sopenharmony_ci free(spec_entries); 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci const struct nir_lower_sysvals_to_varyings_options sysvals_to_varyings = { 800bf215546Sopenharmony_ci .point_coord = true, 801bf215546Sopenharmony_ci }; 802bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_sysvals_to_varyings, &sysvals_to_varyings); 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_ci /* We have to lower away local constant initializers right before we 805bf215546Sopenharmony_ci * inline functions. That way they get properly initialized at the top 806bf215546Sopenharmony_ci * of the function and not at the top of its caller. 807bf215546Sopenharmony_ci */ 808bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_variable_initializers, nir_var_function_temp); 809bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_returns); 810bf215546Sopenharmony_ci bool progress = false; 811bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_inline_functions); 812bf215546Sopenharmony_ci if (progress) { 813bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_copy_prop_vars); 814bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_copy_prop); 815bf215546Sopenharmony_ci } 816bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_deref); 817bf215546Sopenharmony_ci 818bf215546Sopenharmony_ci /* Pick off the single entrypoint that we want */ 819bf215546Sopenharmony_ci foreach_list_typed_safe(nir_function, func, node, &nir->functions) 820bf215546Sopenharmony_ci { 821bf215546Sopenharmony_ci if (func->is_entrypoint) 822bf215546Sopenharmony_ci func->name = ralloc_strdup(func, "main"); 823bf215546Sopenharmony_ci else 824bf215546Sopenharmony_ci exec_node_remove(&func->node); 825bf215546Sopenharmony_ci } 826bf215546Sopenharmony_ci assert(exec_list_length(&nir->functions) == 1); 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_ci /* Make sure we lower constant initializers on output variables so that 829bf215546Sopenharmony_ci * nir_remove_dead_variables below sees the corresponding stores 830bf215546Sopenharmony_ci */ 831bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_variable_initializers, nir_var_shader_out); 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_ci /* Now that we've deleted all but the main function, we can go ahead and 834bf215546Sopenharmony_ci * lower the rest of the constant initializers. 835bf215546Sopenharmony_ci */ 836bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_variable_initializers, ~0); 837bf215546Sopenharmony_ci 838bf215546Sopenharmony_ci /* Split member structs. We do this before lower_io_to_temporaries so that 839bf215546Sopenharmony_ci * it doesn't lower system values to temporaries by accident. 840bf215546Sopenharmony_ci */ 841bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_split_var_copies); 842bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_split_per_member_structs); 843bf215546Sopenharmony_ci 844bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_FRAGMENT) 845bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_io_to_vector, nir_var_shader_out); 846bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_FRAGMENT) 847bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_input_attachments, 848bf215546Sopenharmony_ci &(nir_input_attachment_options){ 849bf215546Sopenharmony_ci .use_fragcoord_sysval = true, 850bf215546Sopenharmony_ci .use_layer_id_sysval = false, 851bf215546Sopenharmony_ci }); 852bf215546Sopenharmony_ci 853bf215546Sopenharmony_ci nir_remove_dead_variables_options dead_vars_opts = { 854bf215546Sopenharmony_ci .can_remove_var = is_not_xfb_output, 855bf215546Sopenharmony_ci }; 856bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_remove_dead_variables, 857bf215546Sopenharmony_ci nir_var_shader_in | nir_var_shader_out | nir_var_system_value | nir_var_mem_shared, 858bf215546Sopenharmony_ci &dead_vars_opts); 859bf215546Sopenharmony_ci 860bf215546Sopenharmony_ci /* Variables can make nir_propagate_invariant more conservative 861bf215546Sopenharmony_ci * than it needs to be. 862bf215546Sopenharmony_ci */ 863bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_global_vars_to_local); 864bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_vars_to_ssa); 865bf215546Sopenharmony_ci 866bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_propagate_invariant, key->invariant_geom); 867bf215546Sopenharmony_ci 868bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_clip_cull_distance_arrays); 869bf215546Sopenharmony_ci 870bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_VERTEX || 871bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_TESS_EVAL || 872bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_GEOMETRY) 873bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_shader_gather_xfb_info); 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_discard_or_demote, key->ps.lower_discard_to_demote); 876bf215546Sopenharmony_ci 877bf215546Sopenharmony_ci nir_lower_doubles_options lower_doubles = nir->options->lower_doubles_options; 878bf215546Sopenharmony_ci 879bf215546Sopenharmony_ci if (device->physical_device->rad_info.gfx_level == GFX6) { 880bf215546Sopenharmony_ci /* GFX6 doesn't support v_floor_f64 and the precision 881bf215546Sopenharmony_ci * of v_fract_f64 which is used to implement 64-bit 882bf215546Sopenharmony_ci * floor is less than what Vulkan requires. 883bf215546Sopenharmony_ci */ 884bf215546Sopenharmony_ci lower_doubles |= nir_lower_dfloor; 885bf215546Sopenharmony_ci } 886bf215546Sopenharmony_ci 887bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_doubles, NULL, lower_doubles); 888bf215546Sopenharmony_ci 889bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_shader_lower_instructions, &is_sincos, &lower_sincos, NULL); 890bf215546Sopenharmony_ci } 891bf215546Sopenharmony_ci 892bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_system_values); 893bf215546Sopenharmony_ci nir_lower_compute_system_values_options csv_options = { 894bf215546Sopenharmony_ci /* Mesh shaders run as NGG which can implement local_invocation_index from 895bf215546Sopenharmony_ci * the wave ID in merged_wave_info, but they don't have local_invocation_ids. 896bf215546Sopenharmony_ci */ 897bf215546Sopenharmony_ci .lower_cs_local_id_to_index = nir->info.stage == MESA_SHADER_MESH, 898bf215546Sopenharmony_ci .lower_local_invocation_index = nir->info.stage == MESA_SHADER_COMPUTE && 899bf215546Sopenharmony_ci ((nir->info.workgroup_size[0] == 1) + 900bf215546Sopenharmony_ci (nir->info.workgroup_size[1] == 1) + 901bf215546Sopenharmony_ci (nir->info.workgroup_size[2] == 1)) == 2, 902bf215546Sopenharmony_ci }; 903bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_compute_system_values, &csv_options); 904bf215546Sopenharmony_ci 905bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_MESH) { 906bf215546Sopenharmony_ci /* NV_mesh_shader: include first_task (aka. first_vertex) in workgroup ID. */ 907bf215546Sopenharmony_ci NIR_PASS(_, nir, radv_lower_ms_workgroup_id); 908bf215546Sopenharmony_ci 909bf215546Sopenharmony_ci /* Mesh shaders only have a 1D "vertex index" which we use 910bf215546Sopenharmony_ci * as "workgroup index" to emulate the 3D workgroup ID. 911bf215546Sopenharmony_ci */ 912bf215546Sopenharmony_ci nir_lower_compute_system_values_options o = { 913bf215546Sopenharmony_ci .lower_workgroup_id_to_index = true, 914bf215546Sopenharmony_ci }; 915bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_compute_system_values, &o); 916bf215546Sopenharmony_ci } 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci /* Vulkan uses the separate-shader linking model */ 919bf215546Sopenharmony_ci nir->info.separate_shader = true; 920bf215546Sopenharmony_ci 921bf215546Sopenharmony_ci nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir)); 922bf215546Sopenharmony_ci 923bf215546Sopenharmony_ci if (nir->info.ray_queries > 0) { 924bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_ray_queries); 925bf215546Sopenharmony_ci NIR_PASS(_, nir, radv_nir_lower_ray_queries, device); 926bf215546Sopenharmony_ci } 927bf215546Sopenharmony_ci 928bf215546Sopenharmony_ci static const nir_lower_tex_options tex_options = { 929bf215546Sopenharmony_ci .lower_txp = ~0, 930bf215546Sopenharmony_ci .lower_txf_offset = true, 931bf215546Sopenharmony_ci .lower_tg4_offsets = true, 932bf215546Sopenharmony_ci .lower_txs_cube_array = true, 933bf215546Sopenharmony_ci .lower_to_fragment_fetch_amd = true, 934bf215546Sopenharmony_ci .lower_lod_zero_width = true, 935bf215546Sopenharmony_ci .lower_invalid_implicit_lod = true, 936bf215546Sopenharmony_ci .lower_array_layer_round_even = true, 937bf215546Sopenharmony_ci }; 938bf215546Sopenharmony_ci 939bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_tex, &tex_options); 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_ci static const nir_lower_image_options image_options = { 942bf215546Sopenharmony_ci .lower_cube_size = true, 943bf215546Sopenharmony_ci }; 944bf215546Sopenharmony_ci 945bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_image, &image_options); 946bf215546Sopenharmony_ci 947bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_vars_to_ssa); 948bf215546Sopenharmony_ci 949bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_VERTEX || nir->info.stage == MESA_SHADER_GEOMETRY || 950bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_FRAGMENT) { 951bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_io_to_temporaries, nir_shader_get_entrypoint(nir), true, true); 952bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_TESS_EVAL) { 953bf215546Sopenharmony_ci NIR_PASS_V(nir, nir_lower_io_to_temporaries, nir_shader_get_entrypoint(nir), true, false); 954bf215546Sopenharmony_ci } 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_split_var_copies); 957bf215546Sopenharmony_ci 958bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_global_vars_to_local); 959bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_remove_dead_variables, nir_var_function_temp, NULL); 960bf215546Sopenharmony_ci bool gfx7minus = device->physical_device->rad_info.gfx_level <= GFX7; 961bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_subgroups, 962bf215546Sopenharmony_ci &(struct nir_lower_subgroups_options){ 963bf215546Sopenharmony_ci .subgroup_size = subgroup_size, 964bf215546Sopenharmony_ci .ballot_bit_size = ballot_bit_size, 965bf215546Sopenharmony_ci .ballot_components = 1, 966bf215546Sopenharmony_ci .lower_to_scalar = 1, 967bf215546Sopenharmony_ci .lower_subgroup_masks = 1, 968bf215546Sopenharmony_ci .lower_relative_shuffle = 1, 969bf215546Sopenharmony_ci .lower_shuffle_to_32bit = 1, 970bf215546Sopenharmony_ci .lower_vote_eq = 1, 971bf215546Sopenharmony_ci .lower_quad_broadcast_dynamic = 1, 972bf215546Sopenharmony_ci .lower_quad_broadcast_dynamic_to_const = gfx7minus, 973bf215546Sopenharmony_ci .lower_shuffle_to_swizzle_amd = 1, 974bf215546Sopenharmony_ci }); 975bf215546Sopenharmony_ci 976bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_load_const_to_scalar); 977bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_shrink_stores, !device->instance->disable_shrink_image_store); 978bf215546Sopenharmony_ci 979bf215546Sopenharmony_ci if (!key->optimisations_disabled) 980bf215546Sopenharmony_ci radv_optimize_nir(nir, false, true); 981bf215546Sopenharmony_ci 982bf215546Sopenharmony_ci /* We call nir_lower_var_copies() after the first radv_optimize_nir() 983bf215546Sopenharmony_ci * to remove any copies introduced by nir_opt_find_array_copies(). 984bf215546Sopenharmony_ci */ 985bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_var_copies); 986bf215546Sopenharmony_ci 987bf215546Sopenharmony_ci unsigned lower_flrp = (nir->options->lower_flrp16 ? 16 : 0) | 988bf215546Sopenharmony_ci (nir->options->lower_flrp32 ? 32 : 0) | 989bf215546Sopenharmony_ci (nir->options->lower_flrp64 ? 64 : 0); 990bf215546Sopenharmony_ci if (lower_flrp != 0) { 991bf215546Sopenharmony_ci bool progress = false; 992bf215546Sopenharmony_ci NIR_PASS(progress, nir, nir_lower_flrp, lower_flrp, false /* always precise */); 993bf215546Sopenharmony_ci if (progress) 994bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_constant_folding); 995bf215546Sopenharmony_ci } 996bf215546Sopenharmony_ci 997bf215546Sopenharmony_ci const nir_opt_access_options opt_access_options = { 998bf215546Sopenharmony_ci .is_vulkan = true, 999bf215546Sopenharmony_ci .infer_non_readable = true, 1000bf215546Sopenharmony_ci }; 1001bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_access, &opt_access_options); 1002bf215546Sopenharmony_ci 1003bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_push_const, nir_address_format_32bit_offset); 1004bf215546Sopenharmony_ci 1005bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_ubo | nir_var_mem_ssbo, 1006bf215546Sopenharmony_ci nir_address_format_vec2_index_32bit_offset); 1007bf215546Sopenharmony_ci 1008bf215546Sopenharmony_ci NIR_PASS(_, nir, lower_intrinsics, key); 1009bf215546Sopenharmony_ci 1010bf215546Sopenharmony_ci /* Lower deref operations for compute shared memory. */ 1011bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_COMPUTE || 1012bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_TASK || 1013bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_MESH) { 1014bf215546Sopenharmony_ci nir_variable_mode var_modes = nir_var_mem_shared; 1015bf215546Sopenharmony_ci 1016bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_TASK || 1017bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_MESH) 1018bf215546Sopenharmony_ci var_modes |= nir_var_mem_task_payload; 1019bf215546Sopenharmony_ci 1020bf215546Sopenharmony_ci if (!nir->info.shared_memory_explicit_layout) { 1021bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_vars_to_explicit_types, var_modes, shared_var_info); 1022bf215546Sopenharmony_ci } 1023bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_explicit_io, var_modes, nir_address_format_32bit_offset); 1024bf215546Sopenharmony_ci 1025bf215546Sopenharmony_ci if (nir->info.zero_initialize_shared_memory && nir->info.shared_size > 0) { 1026bf215546Sopenharmony_ci const unsigned chunk_size = 16; /* max single store size */ 1027bf215546Sopenharmony_ci const unsigned shared_size = ALIGN(nir->info.shared_size, chunk_size); 1028bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_zero_initialize_shared_memory, shared_size, chunk_size); 1029bf215546Sopenharmony_ci } 1030bf215546Sopenharmony_ci } 1031bf215546Sopenharmony_ci 1032bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_global | nir_var_mem_constant, 1033bf215546Sopenharmony_ci nir_address_format_64bit_global); 1034bf215546Sopenharmony_ci 1035bf215546Sopenharmony_ci /* Lower large variables that are always constant with load_constant 1036bf215546Sopenharmony_ci * intrinsics, which get turned into PC-relative loads from a data 1037bf215546Sopenharmony_ci * section next to the shader. 1038bf215546Sopenharmony_ci */ 1039bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_large_constants, glsl_get_natural_size_align_bytes, 16); 1040bf215546Sopenharmony_ci 1041bf215546Sopenharmony_ci /* Lower primitive shading rate to match HW requirements. */ 1042bf215546Sopenharmony_ci if ((nir->info.stage == MESA_SHADER_VERTEX || 1043bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_GEOMETRY || 1044bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_MESH) && 1045bf215546Sopenharmony_ci nir->info.outputs_written & BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_SHADING_RATE)) { 1046bf215546Sopenharmony_ci /* Lower primitive shading rate to match HW requirements. */ 1047bf215546Sopenharmony_ci NIR_PASS(_, nir, radv_lower_primitive_shading_rate, 1048bf215546Sopenharmony_ci device->physical_device->rad_info.gfx_level); 1049bf215546Sopenharmony_ci } 1050bf215546Sopenharmony_ci 1051bf215546Sopenharmony_ci /* Indirect lowering must be called after the radv_optimize_nir() loop 1052bf215546Sopenharmony_ci * has been called at least once. Otherwise indirect lowering can 1053bf215546Sopenharmony_ci * bloat the instruction count of the loop and cause it to be 1054bf215546Sopenharmony_ci * considered too large for unrolling. 1055bf215546Sopenharmony_ci */ 1056bf215546Sopenharmony_ci if (ac_nir_lower_indirect_derefs(nir, device->physical_device->rad_info.gfx_level) && 1057bf215546Sopenharmony_ci !key->optimisations_disabled && nir->info.stage != MESA_SHADER_COMPUTE) { 1058bf215546Sopenharmony_ci /* Optimize the lowered code before the linking optimizations. */ 1059bf215546Sopenharmony_ci radv_optimize_nir(nir, false, false); 1060bf215546Sopenharmony_ci } 1061bf215546Sopenharmony_ci 1062bf215546Sopenharmony_ci 1063bf215546Sopenharmony_ci return nir; 1064bf215546Sopenharmony_ci} 1065bf215546Sopenharmony_ci 1066bf215546Sopenharmony_cistatic int 1067bf215546Sopenharmony_citype_size_vec4(const struct glsl_type *type, bool bindless) 1068bf215546Sopenharmony_ci{ 1069bf215546Sopenharmony_ci return glsl_count_attribute_slots(type, false); 1070bf215546Sopenharmony_ci} 1071bf215546Sopenharmony_ci 1072bf215546Sopenharmony_cistatic nir_variable * 1073bf215546Sopenharmony_cifind_layer_in_var(nir_shader *nir) 1074bf215546Sopenharmony_ci{ 1075bf215546Sopenharmony_ci nir_variable *var = nir_find_variable_with_location(nir, nir_var_shader_in, VARYING_SLOT_LAYER); 1076bf215546Sopenharmony_ci if (var != NULL) 1077bf215546Sopenharmony_ci return var; 1078bf215546Sopenharmony_ci 1079bf215546Sopenharmony_ci var = nir_variable_create(nir, nir_var_shader_in, glsl_int_type(), "layer id"); 1080bf215546Sopenharmony_ci var->data.location = VARYING_SLOT_LAYER; 1081bf215546Sopenharmony_ci var->data.interpolation = INTERP_MODE_FLAT; 1082bf215546Sopenharmony_ci return var; 1083bf215546Sopenharmony_ci} 1084bf215546Sopenharmony_ci 1085bf215546Sopenharmony_ci/* We use layered rendering to implement multiview, which means we need to map 1086bf215546Sopenharmony_ci * view_index to gl_Layer. The code generates a load from the layer_id sysval, 1087bf215546Sopenharmony_ci * but since we don't have a way to get at this information from the fragment 1088bf215546Sopenharmony_ci * shader, we also need to lower this to the gl_Layer varying. This pass 1089bf215546Sopenharmony_ci * lowers both to a varying load from the LAYER slot, before lowering io, so 1090bf215546Sopenharmony_ci * that nir_assign_var_locations() will give the LAYER varying the correct 1091bf215546Sopenharmony_ci * driver_location. 1092bf215546Sopenharmony_ci */ 1093bf215546Sopenharmony_ci 1094bf215546Sopenharmony_cistatic bool 1095bf215546Sopenharmony_cilower_view_index(nir_shader *nir, bool per_primitive) 1096bf215546Sopenharmony_ci{ 1097bf215546Sopenharmony_ci bool progress = false; 1098bf215546Sopenharmony_ci nir_function_impl *entry = nir_shader_get_entrypoint(nir); 1099bf215546Sopenharmony_ci nir_builder b; 1100bf215546Sopenharmony_ci nir_builder_init(&b, entry); 1101bf215546Sopenharmony_ci 1102bf215546Sopenharmony_ci nir_variable *layer = NULL; 1103bf215546Sopenharmony_ci nir_foreach_block (block, entry) { 1104bf215546Sopenharmony_ci nir_foreach_instr_safe (instr, block) { 1105bf215546Sopenharmony_ci if (instr->type != nir_instr_type_intrinsic) 1106bf215546Sopenharmony_ci continue; 1107bf215546Sopenharmony_ci 1108bf215546Sopenharmony_ci nir_intrinsic_instr *load = nir_instr_as_intrinsic(instr); 1109bf215546Sopenharmony_ci if (load->intrinsic != nir_intrinsic_load_view_index) 1110bf215546Sopenharmony_ci continue; 1111bf215546Sopenharmony_ci 1112bf215546Sopenharmony_ci if (!layer) 1113bf215546Sopenharmony_ci layer = find_layer_in_var(nir); 1114bf215546Sopenharmony_ci 1115bf215546Sopenharmony_ci layer->data.per_primitive = per_primitive; 1116bf215546Sopenharmony_ci b.cursor = nir_before_instr(instr); 1117bf215546Sopenharmony_ci nir_ssa_def *def = nir_load_var(&b, layer); 1118bf215546Sopenharmony_ci nir_ssa_def_rewrite_uses(&load->dest.ssa, def); 1119bf215546Sopenharmony_ci 1120bf215546Sopenharmony_ci /* Update inputs_read to reflect that the pass added a new input. */ 1121bf215546Sopenharmony_ci nir->info.inputs_read |= VARYING_BIT_LAYER; 1122bf215546Sopenharmony_ci if (per_primitive) 1123bf215546Sopenharmony_ci nir->info.per_primitive_inputs |= VARYING_BIT_LAYER; 1124bf215546Sopenharmony_ci 1125bf215546Sopenharmony_ci nir_instr_remove(instr); 1126bf215546Sopenharmony_ci progress = true; 1127bf215546Sopenharmony_ci } 1128bf215546Sopenharmony_ci } 1129bf215546Sopenharmony_ci 1130bf215546Sopenharmony_ci if (progress) 1131bf215546Sopenharmony_ci nir_metadata_preserve(entry, nir_metadata_block_index | nir_metadata_dominance); 1132bf215546Sopenharmony_ci else 1133bf215546Sopenharmony_ci nir_metadata_preserve(entry, nir_metadata_all); 1134bf215546Sopenharmony_ci 1135bf215546Sopenharmony_ci return progress; 1136bf215546Sopenharmony_ci} 1137bf215546Sopenharmony_ci 1138bf215546Sopenharmony_civoid 1139bf215546Sopenharmony_ciradv_lower_io(struct radv_device *device, nir_shader *nir, bool is_mesh_shading) 1140bf215546Sopenharmony_ci{ 1141bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_COMPUTE) 1142bf215546Sopenharmony_ci return; 1143bf215546Sopenharmony_ci 1144bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_FRAGMENT) { 1145bf215546Sopenharmony_ci NIR_PASS(_, nir, lower_view_index, is_mesh_shading); 1146bf215546Sopenharmony_ci nir_assign_io_var_locations(nir, nir_var_shader_in, &nir->num_inputs, MESA_SHADER_FRAGMENT); 1147bf215546Sopenharmony_ci } 1148bf215546Sopenharmony_ci 1149bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_lower_io, nir_var_shader_in | nir_var_shader_out, type_size_vec4, 1150bf215546Sopenharmony_ci nir_lower_io_lower_64bit_to_32); 1151bf215546Sopenharmony_ci 1152bf215546Sopenharmony_ci /* This pass needs actual constants */ 1153bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_opt_constant_folding); 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_ci NIR_PASS(_, nir, nir_io_add_const_offset_to_base, nir_var_shader_in | nir_var_shader_out); 1156bf215546Sopenharmony_ci} 1157bf215546Sopenharmony_ci 1158bf215546Sopenharmony_cibool 1159bf215546Sopenharmony_ciradv_lower_io_to_mem(struct radv_device *device, struct radv_pipeline_stage *stage, 1160bf215546Sopenharmony_ci const struct radv_pipeline_key *pl_key) 1161bf215546Sopenharmony_ci{ 1162bf215546Sopenharmony_ci const struct radv_shader_info *info = &stage->info; 1163bf215546Sopenharmony_ci nir_shader *nir = stage->nir; 1164bf215546Sopenharmony_ci 1165bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_VERTEX) { 1166bf215546Sopenharmony_ci if (info->vs.as_ls) { 1167bf215546Sopenharmony_ci NIR_PASS_V(nir, ac_nir_lower_ls_outputs_to_mem, NULL, info->vs.tcs_in_out_eq, 1168bf215546Sopenharmony_ci info->vs.tcs_temp_only_input_mask); 1169bf215546Sopenharmony_ci return true; 1170bf215546Sopenharmony_ci } else if (info->vs.as_es) { 1171bf215546Sopenharmony_ci NIR_PASS_V(nir, ac_nir_lower_es_outputs_to_mem, NULL, 1172bf215546Sopenharmony_ci device->physical_device->rad_info.gfx_level, 1173bf215546Sopenharmony_ci info->vs.num_linked_outputs * 16u); 1174bf215546Sopenharmony_ci return true; 1175bf215546Sopenharmony_ci } 1176bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_TESS_CTRL) { 1177bf215546Sopenharmony_ci NIR_PASS_V(nir, ac_nir_lower_hs_inputs_to_mem, NULL, info->vs.tcs_in_out_eq); 1178bf215546Sopenharmony_ci NIR_PASS_V(nir, ac_nir_lower_hs_outputs_to_mem, NULL, 1179bf215546Sopenharmony_ci device->physical_device->rad_info.gfx_level, 1180bf215546Sopenharmony_ci info->tcs.tes_reads_tess_factors, info->tcs.tes_inputs_read, 1181bf215546Sopenharmony_ci info->tcs.tes_patch_inputs_read, info->tcs.num_linked_outputs, 1182bf215546Sopenharmony_ci info->tcs.num_linked_patch_outputs, info->wave_size, 1183bf215546Sopenharmony_ci false, false, true); 1184bf215546Sopenharmony_ci 1185bf215546Sopenharmony_ci return true; 1186bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_TESS_EVAL) { 1187bf215546Sopenharmony_ci NIR_PASS_V(nir, ac_nir_lower_tes_inputs_to_mem, NULL); 1188bf215546Sopenharmony_ci 1189bf215546Sopenharmony_ci if (info->tes.as_es) { 1190bf215546Sopenharmony_ci NIR_PASS_V(nir, ac_nir_lower_es_outputs_to_mem, NULL, 1191bf215546Sopenharmony_ci device->physical_device->rad_info.gfx_level, 1192bf215546Sopenharmony_ci info->tes.num_linked_outputs * 16u); 1193bf215546Sopenharmony_ci } 1194bf215546Sopenharmony_ci 1195bf215546Sopenharmony_ci return true; 1196bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_GEOMETRY) { 1197bf215546Sopenharmony_ci NIR_PASS_V(nir, ac_nir_lower_gs_inputs_to_mem, NULL, 1198bf215546Sopenharmony_ci device->physical_device->rad_info.gfx_level, false); 1199bf215546Sopenharmony_ci return true; 1200bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_TASK) { 1201bf215546Sopenharmony_ci ac_nir_apply_first_task_to_task_shader(nir); 1202bf215546Sopenharmony_ci ac_nir_lower_task_outputs_to_mem(nir, AC_TASK_PAYLOAD_ENTRY_BYTES, 1203bf215546Sopenharmony_ci device->physical_device->task_info.num_entries); 1204bf215546Sopenharmony_ci return true; 1205bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_MESH) { 1206bf215546Sopenharmony_ci ac_nir_lower_mesh_inputs_to_mem(nir, AC_TASK_PAYLOAD_ENTRY_BYTES, 1207bf215546Sopenharmony_ci device->physical_device->task_info.num_entries); 1208bf215546Sopenharmony_ci return true; 1209bf215546Sopenharmony_ci } 1210bf215546Sopenharmony_ci 1211bf215546Sopenharmony_ci return false; 1212bf215546Sopenharmony_ci} 1213bf215546Sopenharmony_ci 1214bf215546Sopenharmony_cibool 1215bf215546Sopenharmony_ciradv_consider_culling(const struct radv_physical_device *pdevice, struct nir_shader *nir, uint64_t ps_inputs_read, 1216bf215546Sopenharmony_ci unsigned num_vertices_per_primitive, const struct radv_shader_info *info) 1217bf215546Sopenharmony_ci{ 1218bf215546Sopenharmony_ci /* Culling doesn't make sense for meta shaders. */ 1219bf215546Sopenharmony_ci if (is_meta_shader(nir)) 1220bf215546Sopenharmony_ci return false; 1221bf215546Sopenharmony_ci 1222bf215546Sopenharmony_ci /* We don't support culling with multiple viewports yet. */ 1223bf215546Sopenharmony_ci if (nir->info.outputs_written & (VARYING_BIT_VIEWPORT | VARYING_BIT_VIEWPORT_MASK)) 1224bf215546Sopenharmony_ci return false; 1225bf215546Sopenharmony_ci 1226bf215546Sopenharmony_ci /* We don't support culling with vertex shader prologs. */ 1227bf215546Sopenharmony_ci if (info->vs.has_prolog) 1228bf215546Sopenharmony_ci return false; 1229bf215546Sopenharmony_ci 1230bf215546Sopenharmony_ci if (!pdevice->use_ngg_culling) 1231bf215546Sopenharmony_ci return false; 1232bf215546Sopenharmony_ci 1233bf215546Sopenharmony_ci /* Shader based culling efficiency can depend on PS throughput. 1234bf215546Sopenharmony_ci * Estimate an upper limit for PS input param count based on GPU info. 1235bf215546Sopenharmony_ci */ 1236bf215546Sopenharmony_ci unsigned max_ps_params; 1237bf215546Sopenharmony_ci unsigned max_render_backends = pdevice->rad_info.max_render_backends; 1238bf215546Sopenharmony_ci unsigned max_se = pdevice->rad_info.max_se; 1239bf215546Sopenharmony_ci 1240bf215546Sopenharmony_ci if (max_render_backends / max_se == 4) 1241bf215546Sopenharmony_ci max_ps_params = 6; /* Navi21 and other GFX10.3 dGPUs. */ 1242bf215546Sopenharmony_ci else 1243bf215546Sopenharmony_ci max_ps_params = 4; /* Navi 1x. */ 1244bf215546Sopenharmony_ci 1245bf215546Sopenharmony_ci /* TODO: consider other heuristics here, such as PS execution time */ 1246bf215546Sopenharmony_ci if (util_bitcount64(ps_inputs_read & ~VARYING_BIT_POS) > max_ps_params) 1247bf215546Sopenharmony_ci return false; 1248bf215546Sopenharmony_ci 1249bf215546Sopenharmony_ci /* Only triangle culling is supported. */ 1250bf215546Sopenharmony_ci if (num_vertices_per_primitive != 3) 1251bf215546Sopenharmony_ci return false; 1252bf215546Sopenharmony_ci 1253bf215546Sopenharmony_ci /* When the shader writes memory, it is difficult to guarantee correctness. 1254bf215546Sopenharmony_ci * Future work: 1255bf215546Sopenharmony_ci * - if only write-only SSBOs are used 1256bf215546Sopenharmony_ci * - if we can prove that non-position outputs don't rely on memory stores 1257bf215546Sopenharmony_ci * then may be okay to keep the memory stores in the 1st shader part, and delete them from the 2nd. 1258bf215546Sopenharmony_ci */ 1259bf215546Sopenharmony_ci if (nir->info.writes_memory) 1260bf215546Sopenharmony_ci return false; 1261bf215546Sopenharmony_ci 1262bf215546Sopenharmony_ci /* When the shader relies on the subgroup invocation ID, we'd break it, because the ID changes after the culling. 1263bf215546Sopenharmony_ci * Future work: try to save this to LDS and reload, but it can still be broken in subtle ways. 1264bf215546Sopenharmony_ci */ 1265bf215546Sopenharmony_ci if (BITSET_TEST(nir->info.system_values_read, SYSTEM_VALUE_SUBGROUP_INVOCATION)) 1266bf215546Sopenharmony_ci return false; 1267bf215546Sopenharmony_ci 1268bf215546Sopenharmony_ci return true; 1269bf215546Sopenharmony_ci} 1270bf215546Sopenharmony_ci 1271bf215546Sopenharmony_civoid radv_lower_ngg(struct radv_device *device, struct radv_pipeline_stage *ngg_stage, 1272bf215546Sopenharmony_ci const struct radv_pipeline_key *pl_key) 1273bf215546Sopenharmony_ci{ 1274bf215546Sopenharmony_ci const struct radv_shader_info *info = &ngg_stage->info; 1275bf215546Sopenharmony_ci nir_shader *nir = ngg_stage->nir; 1276bf215546Sopenharmony_ci 1277bf215546Sopenharmony_ci assert(nir->info.stage == MESA_SHADER_VERTEX || 1278bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_TESS_EVAL || 1279bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_GEOMETRY || 1280bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_MESH); 1281bf215546Sopenharmony_ci 1282bf215546Sopenharmony_ci const struct gfx10_ngg_info *ngg_info = &info->ngg_info; 1283bf215546Sopenharmony_ci unsigned num_vertices_per_prim = 3; 1284bf215546Sopenharmony_ci 1285bf215546Sopenharmony_ci /* Get the number of vertices per input primitive */ 1286bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_TESS_EVAL) { 1287bf215546Sopenharmony_ci if (nir->info.tess.point_mode) 1288bf215546Sopenharmony_ci num_vertices_per_prim = 1; 1289bf215546Sopenharmony_ci else if (nir->info.tess._primitive_mode == TESS_PRIMITIVE_ISOLINES) 1290bf215546Sopenharmony_ci num_vertices_per_prim = 2; 1291bf215546Sopenharmony_ci 1292bf215546Sopenharmony_ci /* Manually mark the primitive ID used, so the shader can repack it. */ 1293bf215546Sopenharmony_ci if (info->tes.outinfo.export_prim_id) 1294bf215546Sopenharmony_ci BITSET_SET(nir->info.system_values_read, SYSTEM_VALUE_PRIMITIVE_ID); 1295bf215546Sopenharmony_ci 1296bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_VERTEX) { 1297bf215546Sopenharmony_ci /* Need to add 1, because: V_028A6C_POINTLIST=0, V_028A6C_LINESTRIP=1, V_028A6C_TRISTRIP=2, etc. */ 1298bf215546Sopenharmony_ci num_vertices_per_prim = si_conv_prim_to_gs_out(pl_key->vs.topology) + 1; 1299bf215546Sopenharmony_ci 1300bf215546Sopenharmony_ci /* Manually mark the instance ID used, so the shader can repack it. */ 1301bf215546Sopenharmony_ci if (pl_key->vs.instance_rate_inputs) 1302bf215546Sopenharmony_ci BITSET_SET(nir->info.system_values_read, SYSTEM_VALUE_INSTANCE_ID); 1303bf215546Sopenharmony_ci 1304bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_GEOMETRY) { 1305bf215546Sopenharmony_ci num_vertices_per_prim = nir->info.gs.vertices_in; 1306bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_MESH) { 1307bf215546Sopenharmony_ci if (nir->info.mesh.primitive_type == SHADER_PRIM_POINTS) 1308bf215546Sopenharmony_ci num_vertices_per_prim = 1; 1309bf215546Sopenharmony_ci else if (nir->info.mesh.primitive_type == SHADER_PRIM_LINES) 1310bf215546Sopenharmony_ci num_vertices_per_prim = 2; 1311bf215546Sopenharmony_ci else 1312bf215546Sopenharmony_ci assert(nir->info.mesh.primitive_type == SHADER_PRIM_TRIANGLES); 1313bf215546Sopenharmony_ci } else { 1314bf215546Sopenharmony_ci unreachable("NGG needs to be VS, TES or GS."); 1315bf215546Sopenharmony_ci } 1316bf215546Sopenharmony_ci 1317bf215546Sopenharmony_ci /* Invocations that process an input vertex */ 1318bf215546Sopenharmony_ci unsigned max_vtx_in = MIN2(256, ngg_info->enable_vertex_grouping ? ngg_info->hw_max_esverts : num_vertices_per_prim * ngg_info->max_gsprims); 1319bf215546Sopenharmony_ci 1320bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_VERTEX || 1321bf215546Sopenharmony_ci nir->info.stage == MESA_SHADER_TESS_EVAL) { 1322bf215546Sopenharmony_ci bool export_prim_id; 1323bf215546Sopenharmony_ci 1324bf215546Sopenharmony_ci assert(info->is_ngg); 1325bf215546Sopenharmony_ci 1326bf215546Sopenharmony_ci if (info->has_ngg_culling) 1327bf215546Sopenharmony_ci radv_optimize_nir_algebraic(nir, false); 1328bf215546Sopenharmony_ci 1329bf215546Sopenharmony_ci if (nir->info.stage == MESA_SHADER_VERTEX) { 1330bf215546Sopenharmony_ci export_prim_id = info->vs.outinfo.export_prim_id; 1331bf215546Sopenharmony_ci } else { 1332bf215546Sopenharmony_ci export_prim_id = info->tes.outinfo.export_prim_id; 1333bf215546Sopenharmony_ci } 1334bf215546Sopenharmony_ci 1335bf215546Sopenharmony_ci NIR_PASS_V(nir, ac_nir_lower_ngg_nogs, 1336bf215546Sopenharmony_ci device->physical_device->rad_info.family, 1337bf215546Sopenharmony_ci max_vtx_in, num_vertices_per_prim, 1338bf215546Sopenharmony_ci info->workgroup_size, info->wave_size, info->has_ngg_culling, 1339bf215546Sopenharmony_ci info->has_ngg_early_prim_export, info->is_ngg_passthrough, export_prim_id, 1340bf215546Sopenharmony_ci pl_key->vs.provoking_vtx_last, false, pl_key->primitives_generated_query, 1341bf215546Sopenharmony_ci pl_key->vs.instance_rate_inputs); 1342bf215546Sopenharmony_ci 1343bf215546Sopenharmony_ci /* Increase ESGS ring size so the LLVM binary contains the correct LDS size. */ 1344bf215546Sopenharmony_ci ngg_stage->info.ngg_info.esgs_ring_size = nir->info.shared_size; 1345bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_GEOMETRY) { 1346bf215546Sopenharmony_ci assert(info->is_ngg); 1347bf215546Sopenharmony_ci NIR_PASS_V(nir, ac_nir_lower_ngg_gs, info->wave_size, info->workgroup_size, 1348bf215546Sopenharmony_ci info->ngg_info.esgs_ring_size, info->gs.gsvs_vertex_size, 1349bf215546Sopenharmony_ci info->ngg_info.ngg_emit_size * 4u, pl_key->vs.provoking_vtx_last); 1350bf215546Sopenharmony_ci } else if (nir->info.stage == MESA_SHADER_MESH) { 1351bf215546Sopenharmony_ci bool scratch_ring = false; 1352bf215546Sopenharmony_ci NIR_PASS_V(nir, ac_nir_lower_ngg_ms, &scratch_ring, info->wave_size, pl_key->has_multiview_view_index); 1353bf215546Sopenharmony_ci ngg_stage->info.ms.needs_ms_scratch_ring = scratch_ring; 1354bf215546Sopenharmony_ci } else { 1355bf215546Sopenharmony_ci unreachable("invalid SW stage passed to radv_lower_ngg"); 1356bf215546Sopenharmony_ci } 1357bf215546Sopenharmony_ci} 1358bf215546Sopenharmony_ci 1359bf215546Sopenharmony_cistatic unsigned 1360bf215546Sopenharmony_ciget_size_class(unsigned size, bool round_up) 1361bf215546Sopenharmony_ci{ 1362bf215546Sopenharmony_ci size = round_up ? util_logbase2_ceil(size) : util_logbase2(size); 1363bf215546Sopenharmony_ci unsigned size_class = 1364bf215546Sopenharmony_ci MAX2(size, RADV_SHADER_ALLOC_MIN_SIZE_CLASS) - RADV_SHADER_ALLOC_MIN_SIZE_CLASS; 1365bf215546Sopenharmony_ci return MIN2(size_class, RADV_SHADER_ALLOC_NUM_FREE_LISTS - 1); 1366bf215546Sopenharmony_ci} 1367bf215546Sopenharmony_ci 1368bf215546Sopenharmony_cistatic void 1369bf215546Sopenharmony_ciremove_hole(struct radv_device *device, union radv_shader_arena_block *hole) 1370bf215546Sopenharmony_ci{ 1371bf215546Sopenharmony_ci unsigned size_class = get_size_class(hole->size, false); 1372bf215546Sopenharmony_ci list_del(&hole->freelist); 1373bf215546Sopenharmony_ci if (list_is_empty(&device->shader_free_lists[size_class])) 1374bf215546Sopenharmony_ci device->shader_free_list_mask &= ~(1u << size_class); 1375bf215546Sopenharmony_ci} 1376bf215546Sopenharmony_ci 1377bf215546Sopenharmony_cistatic void 1378bf215546Sopenharmony_ciadd_hole(struct radv_device *device, union radv_shader_arena_block *hole) 1379bf215546Sopenharmony_ci{ 1380bf215546Sopenharmony_ci unsigned size_class = get_size_class(hole->size, false); 1381bf215546Sopenharmony_ci list_addtail(&hole->freelist, &device->shader_free_lists[size_class]); 1382bf215546Sopenharmony_ci device->shader_free_list_mask |= 1u << size_class; 1383bf215546Sopenharmony_ci} 1384bf215546Sopenharmony_ci 1385bf215546Sopenharmony_cistatic union radv_shader_arena_block * 1386bf215546Sopenharmony_cialloc_block_obj(struct radv_device *device) 1387bf215546Sopenharmony_ci{ 1388bf215546Sopenharmony_ci if (!list_is_empty(&device->shader_block_obj_pool)) { 1389bf215546Sopenharmony_ci union radv_shader_arena_block *block = 1390bf215546Sopenharmony_ci list_first_entry(&device->shader_block_obj_pool, union radv_shader_arena_block, pool); 1391bf215546Sopenharmony_ci list_del(&block->pool); 1392bf215546Sopenharmony_ci return block; 1393bf215546Sopenharmony_ci } 1394bf215546Sopenharmony_ci 1395bf215546Sopenharmony_ci return malloc(sizeof(union radv_shader_arena_block)); 1396bf215546Sopenharmony_ci} 1397bf215546Sopenharmony_ci 1398bf215546Sopenharmony_cistatic void 1399bf215546Sopenharmony_cifree_block_obj(struct radv_device *device, union radv_shader_arena_block *block) 1400bf215546Sopenharmony_ci{ 1401bf215546Sopenharmony_ci list_add(&block->pool, &device->shader_block_obj_pool); 1402bf215546Sopenharmony_ci} 1403bf215546Sopenharmony_ci 1404bf215546Sopenharmony_ci/* Segregated fit allocator, implementing a good-fit allocation policy. 1405bf215546Sopenharmony_ci * 1406bf215546Sopenharmony_ci * This is an variation of sequential fit allocation with several lists of free blocks ("holes") 1407bf215546Sopenharmony_ci * instead of one. Each list of holes only contains holes of a certain range of sizes, so holes that 1408bf215546Sopenharmony_ci * are too small can easily be ignored while allocating. Because this also ignores holes that are 1409bf215546Sopenharmony_ci * larger than necessary (approximating best-fit allocation), this could be described as a 1410bf215546Sopenharmony_ci * "good-fit" allocator. 1411bf215546Sopenharmony_ci * 1412bf215546Sopenharmony_ci * Typically, shaders are allocated and only free'd when the device is destroyed. For this pattern, 1413bf215546Sopenharmony_ci * this should allocate blocks for shaders fast and with no fragmentation, while still allowing 1414bf215546Sopenharmony_ci * free'd memory to be re-used. 1415bf215546Sopenharmony_ci */ 1416bf215546Sopenharmony_ciunion radv_shader_arena_block * 1417bf215546Sopenharmony_ciradv_alloc_shader_memory(struct radv_device *device, uint32_t size, void *ptr) 1418bf215546Sopenharmony_ci{ 1419bf215546Sopenharmony_ci size = align(size, RADV_SHADER_ALLOC_ALIGNMENT); 1420bf215546Sopenharmony_ci 1421bf215546Sopenharmony_ci mtx_lock(&device->shader_arena_mutex); 1422bf215546Sopenharmony_ci 1423bf215546Sopenharmony_ci /* Try to use an existing hole. Unless the shader is very large, this should only have to look 1424bf215546Sopenharmony_ci * at the first one available. 1425bf215546Sopenharmony_ci */ 1426bf215546Sopenharmony_ci unsigned free_list_mask = BITFIELD_MASK(RADV_SHADER_ALLOC_NUM_FREE_LISTS); 1427bf215546Sopenharmony_ci unsigned size_class = 1428bf215546Sopenharmony_ci ffs(device->shader_free_list_mask & (free_list_mask << get_size_class(size, true))); 1429bf215546Sopenharmony_ci if (size_class) { 1430bf215546Sopenharmony_ci size_class--; 1431bf215546Sopenharmony_ci 1432bf215546Sopenharmony_ci list_for_each_entry(union radv_shader_arena_block, hole, 1433bf215546Sopenharmony_ci &device->shader_free_lists[size_class], freelist) 1434bf215546Sopenharmony_ci { 1435bf215546Sopenharmony_ci if (hole->size < size) 1436bf215546Sopenharmony_ci continue; 1437bf215546Sopenharmony_ci 1438bf215546Sopenharmony_ci assert(hole->offset % RADV_SHADER_ALLOC_ALIGNMENT == 0); 1439bf215546Sopenharmony_ci 1440bf215546Sopenharmony_ci if (size == hole->size) { 1441bf215546Sopenharmony_ci remove_hole(device, hole); 1442bf215546Sopenharmony_ci hole->freelist.next = ptr; 1443bf215546Sopenharmony_ci mtx_unlock(&device->shader_arena_mutex); 1444bf215546Sopenharmony_ci return hole; 1445bf215546Sopenharmony_ci } else { 1446bf215546Sopenharmony_ci union radv_shader_arena_block *alloc = alloc_block_obj(device); 1447bf215546Sopenharmony_ci if (!alloc) { 1448bf215546Sopenharmony_ci mtx_unlock(&device->shader_arena_mutex); 1449bf215546Sopenharmony_ci return NULL; 1450bf215546Sopenharmony_ci } 1451bf215546Sopenharmony_ci list_addtail(&alloc->list, &hole->list); 1452bf215546Sopenharmony_ci alloc->freelist.prev = NULL; 1453bf215546Sopenharmony_ci alloc->freelist.next = ptr; 1454bf215546Sopenharmony_ci alloc->arena = hole->arena; 1455bf215546Sopenharmony_ci alloc->offset = hole->offset; 1456bf215546Sopenharmony_ci alloc->size = size; 1457bf215546Sopenharmony_ci 1458bf215546Sopenharmony_ci remove_hole(device, hole); 1459bf215546Sopenharmony_ci hole->offset += size; 1460bf215546Sopenharmony_ci hole->size -= size; 1461bf215546Sopenharmony_ci add_hole(device, hole); 1462bf215546Sopenharmony_ci 1463bf215546Sopenharmony_ci mtx_unlock(&device->shader_arena_mutex); 1464bf215546Sopenharmony_ci return alloc; 1465bf215546Sopenharmony_ci } 1466bf215546Sopenharmony_ci } 1467bf215546Sopenharmony_ci } 1468bf215546Sopenharmony_ci 1469bf215546Sopenharmony_ci /* Allocate a new shader arena. */ 1470bf215546Sopenharmony_ci struct radv_shader_arena *arena = calloc(1, sizeof(struct radv_shader_arena)); 1471bf215546Sopenharmony_ci union radv_shader_arena_block *alloc = NULL, *hole = NULL; 1472bf215546Sopenharmony_ci if (!arena) 1473bf215546Sopenharmony_ci goto fail; 1474bf215546Sopenharmony_ci 1475bf215546Sopenharmony_ci unsigned arena_size = 1476bf215546Sopenharmony_ci MAX2(RADV_SHADER_ALLOC_MIN_ARENA_SIZE 1477bf215546Sopenharmony_ci << MIN2(RADV_SHADER_ALLOC_MAX_ARENA_SIZE_SHIFT, device->shader_arena_shift), 1478bf215546Sopenharmony_ci size); 1479bf215546Sopenharmony_ci VkResult result = device->ws->buffer_create( 1480bf215546Sopenharmony_ci device->ws, arena_size, RADV_SHADER_ALLOC_ALIGNMENT, RADEON_DOMAIN_VRAM, 1481bf215546Sopenharmony_ci RADEON_FLAG_NO_INTERPROCESS_SHARING | RADEON_FLAG_32BIT | 1482bf215546Sopenharmony_ci (device->physical_device->rad_info.cpdma_prefetch_writes_memory ? 0 1483bf215546Sopenharmony_ci : RADEON_FLAG_READ_ONLY), 1484bf215546Sopenharmony_ci RADV_BO_PRIORITY_SHADER, 0, &arena->bo); 1485bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1486bf215546Sopenharmony_ci goto fail; 1487bf215546Sopenharmony_ci 1488bf215546Sopenharmony_ci list_inithead(&arena->entries); 1489bf215546Sopenharmony_ci 1490bf215546Sopenharmony_ci arena->ptr = (char *)device->ws->buffer_map(arena->bo); 1491bf215546Sopenharmony_ci if (!arena->ptr) 1492bf215546Sopenharmony_ci goto fail; 1493bf215546Sopenharmony_ci 1494bf215546Sopenharmony_ci alloc = alloc_block_obj(device); 1495bf215546Sopenharmony_ci hole = arena_size - size > 0 ? alloc_block_obj(device) : alloc; 1496bf215546Sopenharmony_ci if (!alloc || !hole) 1497bf215546Sopenharmony_ci goto fail; 1498bf215546Sopenharmony_ci list_addtail(&alloc->list, &arena->entries); 1499bf215546Sopenharmony_ci alloc->freelist.prev = NULL; 1500bf215546Sopenharmony_ci alloc->freelist.next = ptr; 1501bf215546Sopenharmony_ci alloc->arena = arena; 1502bf215546Sopenharmony_ci alloc->offset = 0; 1503bf215546Sopenharmony_ci alloc->size = size; 1504bf215546Sopenharmony_ci 1505bf215546Sopenharmony_ci if (hole != alloc) { 1506bf215546Sopenharmony_ci hole->arena = arena; 1507bf215546Sopenharmony_ci hole->offset = size; 1508bf215546Sopenharmony_ci hole->size = arena_size - size; 1509bf215546Sopenharmony_ci 1510bf215546Sopenharmony_ci list_addtail(&hole->list, &arena->entries); 1511bf215546Sopenharmony_ci add_hole(device, hole); 1512bf215546Sopenharmony_ci } 1513bf215546Sopenharmony_ci 1514bf215546Sopenharmony_ci ++device->shader_arena_shift; 1515bf215546Sopenharmony_ci list_addtail(&arena->list, &device->shader_arenas); 1516bf215546Sopenharmony_ci 1517bf215546Sopenharmony_ci mtx_unlock(&device->shader_arena_mutex); 1518bf215546Sopenharmony_ci return alloc; 1519bf215546Sopenharmony_ci 1520bf215546Sopenharmony_cifail: 1521bf215546Sopenharmony_ci mtx_unlock(&device->shader_arena_mutex); 1522bf215546Sopenharmony_ci free(alloc); 1523bf215546Sopenharmony_ci free(hole); 1524bf215546Sopenharmony_ci if (arena && arena->bo) 1525bf215546Sopenharmony_ci device->ws->buffer_destroy(device->ws, arena->bo); 1526bf215546Sopenharmony_ci free(arena); 1527bf215546Sopenharmony_ci return NULL; 1528bf215546Sopenharmony_ci} 1529bf215546Sopenharmony_ci 1530bf215546Sopenharmony_cistatic union radv_shader_arena_block * 1531bf215546Sopenharmony_ciget_hole(struct radv_shader_arena *arena, struct list_head *head) 1532bf215546Sopenharmony_ci{ 1533bf215546Sopenharmony_ci if (head == &arena->entries) 1534bf215546Sopenharmony_ci return NULL; 1535bf215546Sopenharmony_ci 1536bf215546Sopenharmony_ci union radv_shader_arena_block *hole = list_entry(head, union radv_shader_arena_block, list); 1537bf215546Sopenharmony_ci return hole->freelist.prev ? hole : NULL; 1538bf215546Sopenharmony_ci} 1539bf215546Sopenharmony_ci 1540bf215546Sopenharmony_civoid 1541bf215546Sopenharmony_ciradv_free_shader_memory(struct radv_device *device, union radv_shader_arena_block *alloc) 1542bf215546Sopenharmony_ci{ 1543bf215546Sopenharmony_ci mtx_lock(&device->shader_arena_mutex); 1544bf215546Sopenharmony_ci 1545bf215546Sopenharmony_ci union radv_shader_arena_block *hole_prev = get_hole(alloc->arena, alloc->list.prev); 1546bf215546Sopenharmony_ci union radv_shader_arena_block *hole_next = get_hole(alloc->arena, alloc->list.next); 1547bf215546Sopenharmony_ci 1548bf215546Sopenharmony_ci union radv_shader_arena_block *hole = alloc; 1549bf215546Sopenharmony_ci 1550bf215546Sopenharmony_ci /* merge with previous hole */ 1551bf215546Sopenharmony_ci if (hole_prev) { 1552bf215546Sopenharmony_ci remove_hole(device, hole_prev); 1553bf215546Sopenharmony_ci 1554bf215546Sopenharmony_ci hole_prev->size += hole->size; 1555bf215546Sopenharmony_ci list_del(&hole->list); 1556bf215546Sopenharmony_ci free_block_obj(device, hole); 1557bf215546Sopenharmony_ci 1558bf215546Sopenharmony_ci hole = hole_prev; 1559bf215546Sopenharmony_ci } 1560bf215546Sopenharmony_ci 1561bf215546Sopenharmony_ci /* merge with next hole */ 1562bf215546Sopenharmony_ci if (hole_next) { 1563bf215546Sopenharmony_ci remove_hole(device, hole_next); 1564bf215546Sopenharmony_ci 1565bf215546Sopenharmony_ci hole_next->offset -= hole->size; 1566bf215546Sopenharmony_ci hole_next->size += hole->size; 1567bf215546Sopenharmony_ci list_del(&hole->list); 1568bf215546Sopenharmony_ci free_block_obj(device, hole); 1569bf215546Sopenharmony_ci 1570bf215546Sopenharmony_ci hole = hole_next; 1571bf215546Sopenharmony_ci } 1572bf215546Sopenharmony_ci 1573bf215546Sopenharmony_ci if (list_is_singular(&hole->list)) { 1574bf215546Sopenharmony_ci struct radv_shader_arena *arena = hole->arena; 1575bf215546Sopenharmony_ci free_block_obj(device, hole); 1576bf215546Sopenharmony_ci 1577bf215546Sopenharmony_ci device->ws->buffer_destroy(device->ws, arena->bo); 1578bf215546Sopenharmony_ci list_del(&arena->list); 1579bf215546Sopenharmony_ci free(arena); 1580bf215546Sopenharmony_ci } else { 1581bf215546Sopenharmony_ci add_hole(device, hole); 1582bf215546Sopenharmony_ci } 1583bf215546Sopenharmony_ci 1584bf215546Sopenharmony_ci mtx_unlock(&device->shader_arena_mutex); 1585bf215546Sopenharmony_ci} 1586bf215546Sopenharmony_ci 1587bf215546Sopenharmony_civoid 1588bf215546Sopenharmony_ciradv_init_shader_arenas(struct radv_device *device) 1589bf215546Sopenharmony_ci{ 1590bf215546Sopenharmony_ci mtx_init(&device->shader_arena_mutex, mtx_plain); 1591bf215546Sopenharmony_ci 1592bf215546Sopenharmony_ci device->shader_free_list_mask = 0; 1593bf215546Sopenharmony_ci 1594bf215546Sopenharmony_ci list_inithead(&device->shader_arenas); 1595bf215546Sopenharmony_ci list_inithead(&device->shader_block_obj_pool); 1596bf215546Sopenharmony_ci for (unsigned i = 0; i < RADV_SHADER_ALLOC_NUM_FREE_LISTS; i++) 1597bf215546Sopenharmony_ci list_inithead(&device->shader_free_lists[i]); 1598bf215546Sopenharmony_ci} 1599bf215546Sopenharmony_ci 1600bf215546Sopenharmony_civoid 1601bf215546Sopenharmony_ciradv_destroy_shader_arenas(struct radv_device *device) 1602bf215546Sopenharmony_ci{ 1603bf215546Sopenharmony_ci list_for_each_entry_safe(union radv_shader_arena_block, block, &device->shader_block_obj_pool, 1604bf215546Sopenharmony_ci pool) free(block); 1605bf215546Sopenharmony_ci 1606bf215546Sopenharmony_ci list_for_each_entry_safe(struct radv_shader_arena, arena, &device->shader_arenas, list) 1607bf215546Sopenharmony_ci { 1608bf215546Sopenharmony_ci device->ws->buffer_destroy(device->ws, arena->bo); 1609bf215546Sopenharmony_ci free(arena); 1610bf215546Sopenharmony_ci } 1611bf215546Sopenharmony_ci mtx_destroy(&device->shader_arena_mutex); 1612bf215546Sopenharmony_ci} 1613bf215546Sopenharmony_ci 1614bf215546Sopenharmony_ci/* For the UMR disassembler. */ 1615bf215546Sopenharmony_ci#define DEBUGGER_END_OF_CODE_MARKER 0xbf9f0000 /* invalid instruction */ 1616bf215546Sopenharmony_ci#define DEBUGGER_NUM_MARKERS 5 1617bf215546Sopenharmony_ci 1618bf215546Sopenharmony_cistatic unsigned 1619bf215546Sopenharmony_ciradv_get_shader_binary_size(size_t code_size) 1620bf215546Sopenharmony_ci{ 1621bf215546Sopenharmony_ci return code_size + DEBUGGER_NUM_MARKERS * 4; 1622bf215546Sopenharmony_ci} 1623bf215546Sopenharmony_ci 1624bf215546Sopenharmony_cistatic bool 1625bf215546Sopenharmony_ciradv_should_use_wgp_mode(const struct radv_device *device, gl_shader_stage stage, 1626bf215546Sopenharmony_ci const struct radv_shader_info *info) 1627bf215546Sopenharmony_ci{ 1628bf215546Sopenharmony_ci enum amd_gfx_level chip = device->physical_device->rad_info.gfx_level; 1629bf215546Sopenharmony_ci switch (stage) { 1630bf215546Sopenharmony_ci case MESA_SHADER_COMPUTE: 1631bf215546Sopenharmony_ci case MESA_SHADER_TESS_CTRL: 1632bf215546Sopenharmony_ci return chip >= GFX10; 1633bf215546Sopenharmony_ci case MESA_SHADER_GEOMETRY: 1634bf215546Sopenharmony_ci return chip == GFX10 || (chip >= GFX10_3 && !info->is_ngg); 1635bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: 1636bf215546Sopenharmony_ci case MESA_SHADER_TESS_EVAL: 1637bf215546Sopenharmony_ci return chip == GFX10 && info->is_ngg; 1638bf215546Sopenharmony_ci default: 1639bf215546Sopenharmony_ci return false; 1640bf215546Sopenharmony_ci } 1641bf215546Sopenharmony_ci} 1642bf215546Sopenharmony_ci 1643bf215546Sopenharmony_cistatic void 1644bf215546Sopenharmony_ciradv_postprocess_config(const struct radv_device *device, const struct ac_shader_config *config_in, 1645bf215546Sopenharmony_ci const struct radv_shader_info *info, gl_shader_stage stage, 1646bf215546Sopenharmony_ci const struct radv_shader_args *args, 1647bf215546Sopenharmony_ci struct ac_shader_config *config_out) 1648bf215546Sopenharmony_ci{ 1649bf215546Sopenharmony_ci const struct radv_physical_device *pdevice = device->physical_device; 1650bf215546Sopenharmony_ci bool scratch_enabled = config_in->scratch_bytes_per_wave > 0; 1651bf215546Sopenharmony_ci bool trap_enabled = !!device->trap_handler_shader; 1652bf215546Sopenharmony_ci unsigned vgpr_comp_cnt = 0; 1653bf215546Sopenharmony_ci unsigned num_input_vgprs = args->ac.num_vgprs_used; 1654bf215546Sopenharmony_ci 1655bf215546Sopenharmony_ci if (stage == MESA_SHADER_FRAGMENT) { 1656bf215546Sopenharmony_ci num_input_vgprs = ac_get_fs_input_vgpr_cnt(config_in, NULL, NULL, NULL); 1657bf215546Sopenharmony_ci } 1658bf215546Sopenharmony_ci 1659bf215546Sopenharmony_ci unsigned num_vgprs = MAX2(config_in->num_vgprs, num_input_vgprs); 1660bf215546Sopenharmony_ci /* +2 for the ring offsets, +3 for scratch wave offset and VCC */ 1661bf215546Sopenharmony_ci unsigned num_sgprs = MAX2(config_in->num_sgprs, args->ac.num_sgprs_used + 2 + 3); 1662bf215546Sopenharmony_ci unsigned num_shared_vgprs = config_in->num_shared_vgprs; 1663bf215546Sopenharmony_ci /* shared VGPRs are introduced in Navi and are allocated in blocks of 8 (RDNA ref 3.6.5) */ 1664bf215546Sopenharmony_ci assert((pdevice->rad_info.gfx_level >= GFX10 && num_shared_vgprs % 8 == 0) || 1665bf215546Sopenharmony_ci (pdevice->rad_info.gfx_level < GFX10 && num_shared_vgprs == 0)); 1666bf215546Sopenharmony_ci unsigned num_shared_vgpr_blocks = num_shared_vgprs / 8; 1667bf215546Sopenharmony_ci unsigned excp_en = 0; 1668bf215546Sopenharmony_ci 1669bf215546Sopenharmony_ci *config_out = *config_in; 1670bf215546Sopenharmony_ci config_out->num_vgprs = num_vgprs; 1671bf215546Sopenharmony_ci config_out->num_sgprs = num_sgprs; 1672bf215546Sopenharmony_ci config_out->num_shared_vgprs = num_shared_vgprs; 1673bf215546Sopenharmony_ci 1674bf215546Sopenharmony_ci config_out->rsrc2 = S_00B12C_USER_SGPR(args->num_user_sgprs) | 1675bf215546Sopenharmony_ci S_00B12C_SCRATCH_EN(scratch_enabled) | S_00B12C_TRAP_PRESENT(trap_enabled); 1676bf215546Sopenharmony_ci 1677bf215546Sopenharmony_ci if (trap_enabled) { 1678bf215546Sopenharmony_ci /* Configure the shader exceptions like memory violation, etc. 1679bf215546Sopenharmony_ci * TODO: Enable (and validate) more exceptions. 1680bf215546Sopenharmony_ci */ 1681bf215546Sopenharmony_ci excp_en = 1 << 8; /* mem_viol */ 1682bf215546Sopenharmony_ci } 1683bf215546Sopenharmony_ci 1684bf215546Sopenharmony_ci if (!pdevice->use_ngg_streamout) { 1685bf215546Sopenharmony_ci config_out->rsrc2 |= 1686bf215546Sopenharmony_ci S_00B12C_SO_BASE0_EN(!!info->so.strides[0]) | S_00B12C_SO_BASE1_EN(!!info->so.strides[1]) | 1687bf215546Sopenharmony_ci S_00B12C_SO_BASE2_EN(!!info->so.strides[2]) | S_00B12C_SO_BASE3_EN(!!info->so.strides[3]) | 1688bf215546Sopenharmony_ci S_00B12C_SO_EN(!!info->so.num_outputs); 1689bf215546Sopenharmony_ci } 1690bf215546Sopenharmony_ci 1691bf215546Sopenharmony_ci config_out->rsrc1 = S_00B848_VGPRS((num_vgprs - 1) / (info->wave_size == 32 ? 8 : 4)) | 1692bf215546Sopenharmony_ci S_00B848_DX10_CLAMP(1) | S_00B848_FLOAT_MODE(config_out->float_mode); 1693bf215546Sopenharmony_ci 1694bf215546Sopenharmony_ci if (pdevice->rad_info.gfx_level >= GFX10) { 1695bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B22C_USER_SGPR_MSB_GFX10(args->num_user_sgprs >> 5); 1696bf215546Sopenharmony_ci } else { 1697bf215546Sopenharmony_ci config_out->rsrc1 |= S_00B228_SGPRS((num_sgprs - 1) / 8); 1698bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B22C_USER_SGPR_MSB_GFX9(args->num_user_sgprs >> 5); 1699bf215546Sopenharmony_ci } 1700bf215546Sopenharmony_ci 1701bf215546Sopenharmony_ci bool wgp_mode = radv_should_use_wgp_mode(device, stage, info); 1702bf215546Sopenharmony_ci 1703bf215546Sopenharmony_ci switch (stage) { 1704bf215546Sopenharmony_ci case MESA_SHADER_TESS_EVAL: 1705bf215546Sopenharmony_ci if (info->is_ngg) { 1706bf215546Sopenharmony_ci config_out->rsrc1 |= S_00B228_MEM_ORDERED(pdevice->rad_info.gfx_level >= GFX10); 1707bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B22C_OC_LDS_EN(1) | S_00B22C_EXCP_EN(excp_en); 1708bf215546Sopenharmony_ci } else if (info->tes.as_es) { 1709bf215546Sopenharmony_ci assert(pdevice->rad_info.gfx_level <= GFX8); 1710bf215546Sopenharmony_ci vgpr_comp_cnt = info->uses_prim_id ? 3 : 2; 1711bf215546Sopenharmony_ci 1712bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B12C_OC_LDS_EN(1) | S_00B12C_EXCP_EN(excp_en); 1713bf215546Sopenharmony_ci } else { 1714bf215546Sopenharmony_ci bool enable_prim_id = info->tes.outinfo.export_prim_id || info->uses_prim_id; 1715bf215546Sopenharmony_ci vgpr_comp_cnt = enable_prim_id ? 3 : 2; 1716bf215546Sopenharmony_ci 1717bf215546Sopenharmony_ci config_out->rsrc1 |= S_00B128_MEM_ORDERED(pdevice->rad_info.gfx_level >= GFX10); 1718bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B12C_OC_LDS_EN(1) | S_00B12C_EXCP_EN(excp_en); 1719bf215546Sopenharmony_ci } 1720bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B22C_SHARED_VGPR_CNT(num_shared_vgpr_blocks); 1721bf215546Sopenharmony_ci break; 1722bf215546Sopenharmony_ci case MESA_SHADER_TESS_CTRL: 1723bf215546Sopenharmony_ci if (pdevice->rad_info.gfx_level >= GFX9) { 1724bf215546Sopenharmony_ci /* We need at least 2 components for LS. 1725bf215546Sopenharmony_ci * VGPR0-3: (VertexID, RelAutoindex, InstanceID / StepRate0, InstanceID). 1726bf215546Sopenharmony_ci * StepRate0 is set to 1. so that VGPR3 doesn't have to be loaded. 1727bf215546Sopenharmony_ci */ 1728bf215546Sopenharmony_ci if (pdevice->rad_info.gfx_level >= GFX10) { 1729bf215546Sopenharmony_ci if (info->vs.needs_instance_id) { 1730bf215546Sopenharmony_ci vgpr_comp_cnt = 3; 1731bf215546Sopenharmony_ci } else if (pdevice->rad_info.gfx_level <= GFX10_3) { 1732bf215546Sopenharmony_ci vgpr_comp_cnt = 1; 1733bf215546Sopenharmony_ci } 1734bf215546Sopenharmony_ci config_out->rsrc2 |= 1735bf215546Sopenharmony_ci S_00B42C_LDS_SIZE_GFX10(info->tcs.num_lds_blocks) | S_00B42C_EXCP_EN_GFX6(excp_en); 1736bf215546Sopenharmony_ci } else { 1737bf215546Sopenharmony_ci vgpr_comp_cnt = info->vs.needs_instance_id ? 2 : 1; 1738bf215546Sopenharmony_ci config_out->rsrc2 |= 1739bf215546Sopenharmony_ci S_00B42C_LDS_SIZE_GFX9(info->tcs.num_lds_blocks) | S_00B42C_EXCP_EN_GFX9(excp_en); 1740bf215546Sopenharmony_ci } 1741bf215546Sopenharmony_ci } else { 1742bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B12C_OC_LDS_EN(1) | S_00B12C_EXCP_EN(excp_en); 1743bf215546Sopenharmony_ci } 1744bf215546Sopenharmony_ci config_out->rsrc1 |= 1745bf215546Sopenharmony_ci S_00B428_MEM_ORDERED(pdevice->rad_info.gfx_level >= GFX10) | S_00B428_WGP_MODE(wgp_mode); 1746bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B42C_SHARED_VGPR_CNT(num_shared_vgpr_blocks); 1747bf215546Sopenharmony_ci break; 1748bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: 1749bf215546Sopenharmony_ci if (info->is_ngg) { 1750bf215546Sopenharmony_ci config_out->rsrc1 |= S_00B228_MEM_ORDERED(pdevice->rad_info.gfx_level >= GFX10); 1751bf215546Sopenharmony_ci } else if (info->vs.as_ls) { 1752bf215546Sopenharmony_ci assert(pdevice->rad_info.gfx_level <= GFX8); 1753bf215546Sopenharmony_ci /* We need at least 2 components for LS. 1754bf215546Sopenharmony_ci * VGPR0-3: (VertexID, RelAutoindex, InstanceID / StepRate0, InstanceID). 1755bf215546Sopenharmony_ci * StepRate0 is set to 1. so that VGPR3 doesn't have to be loaded. 1756bf215546Sopenharmony_ci */ 1757bf215546Sopenharmony_ci vgpr_comp_cnt = info->vs.needs_instance_id ? 2 : 1; 1758bf215546Sopenharmony_ci } else if (info->vs.as_es) { 1759bf215546Sopenharmony_ci assert(pdevice->rad_info.gfx_level <= GFX8); 1760bf215546Sopenharmony_ci /* VGPR0-3: (VertexID, InstanceID / StepRate0, ...) */ 1761bf215546Sopenharmony_ci vgpr_comp_cnt = info->vs.needs_instance_id ? 1 : 0; 1762bf215546Sopenharmony_ci } else { 1763bf215546Sopenharmony_ci /* VGPR0-3: (VertexID, InstanceID / StepRate0, PrimID, InstanceID) 1764bf215546Sopenharmony_ci * If PrimID is disabled. InstanceID / StepRate1 is loaded instead. 1765bf215546Sopenharmony_ci * StepRate0 is set to 1. so that VGPR3 doesn't have to be loaded. 1766bf215546Sopenharmony_ci */ 1767bf215546Sopenharmony_ci if (info->vs.needs_instance_id && pdevice->rad_info.gfx_level >= GFX10) { 1768bf215546Sopenharmony_ci vgpr_comp_cnt = 3; 1769bf215546Sopenharmony_ci } else if (info->vs.outinfo.export_prim_id) { 1770bf215546Sopenharmony_ci vgpr_comp_cnt = 2; 1771bf215546Sopenharmony_ci } else if (info->vs.needs_instance_id) { 1772bf215546Sopenharmony_ci vgpr_comp_cnt = 1; 1773bf215546Sopenharmony_ci } else { 1774bf215546Sopenharmony_ci vgpr_comp_cnt = 0; 1775bf215546Sopenharmony_ci } 1776bf215546Sopenharmony_ci 1777bf215546Sopenharmony_ci config_out->rsrc1 |= S_00B128_MEM_ORDERED(pdevice->rad_info.gfx_level >= GFX10); 1778bf215546Sopenharmony_ci } 1779bf215546Sopenharmony_ci config_out->rsrc2 |= 1780bf215546Sopenharmony_ci S_00B12C_SHARED_VGPR_CNT(num_shared_vgpr_blocks) | S_00B12C_EXCP_EN(excp_en); 1781bf215546Sopenharmony_ci break; 1782bf215546Sopenharmony_ci case MESA_SHADER_MESH: 1783bf215546Sopenharmony_ci config_out->rsrc1 |= S_00B228_MEM_ORDERED(1); 1784bf215546Sopenharmony_ci config_out->rsrc2 |= 1785bf215546Sopenharmony_ci S_00B12C_SHARED_VGPR_CNT(num_shared_vgpr_blocks) | S_00B12C_EXCP_EN(excp_en); 1786bf215546Sopenharmony_ci break; 1787bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: 1788bf215546Sopenharmony_ci config_out->rsrc1 |= S_00B028_MEM_ORDERED(pdevice->rad_info.gfx_level >= GFX10); 1789bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B02C_SHARED_VGPR_CNT(num_shared_vgpr_blocks) | 1790bf215546Sopenharmony_ci S_00B02C_EXCP_EN(excp_en); 1791bf215546Sopenharmony_ci break; 1792bf215546Sopenharmony_ci case MESA_SHADER_GEOMETRY: 1793bf215546Sopenharmony_ci config_out->rsrc1 |= S_00B228_MEM_ORDERED(pdevice->rad_info.gfx_level >= GFX10); 1794bf215546Sopenharmony_ci config_out->rsrc2 |= 1795bf215546Sopenharmony_ci S_00B22C_SHARED_VGPR_CNT(num_shared_vgpr_blocks) | S_00B22C_EXCP_EN(excp_en); 1796bf215546Sopenharmony_ci break; 1797bf215546Sopenharmony_ci case MESA_SHADER_COMPUTE: 1798bf215546Sopenharmony_ci case MESA_SHADER_TASK: 1799bf215546Sopenharmony_ci config_out->rsrc1 |= 1800bf215546Sopenharmony_ci S_00B848_MEM_ORDERED(pdevice->rad_info.gfx_level >= GFX10) | S_00B848_WGP_MODE(wgp_mode); 1801bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B84C_TGID_X_EN(info->cs.uses_block_id[0]) | 1802bf215546Sopenharmony_ci S_00B84C_TGID_Y_EN(info->cs.uses_block_id[1]) | 1803bf215546Sopenharmony_ci S_00B84C_TGID_Z_EN(info->cs.uses_block_id[2]) | 1804bf215546Sopenharmony_ci S_00B84C_TIDIG_COMP_CNT(info->cs.uses_thread_id[2] ? 2 1805bf215546Sopenharmony_ci : info->cs.uses_thread_id[1] ? 1 1806bf215546Sopenharmony_ci : 0) | 1807bf215546Sopenharmony_ci S_00B84C_TG_SIZE_EN(info->cs.uses_local_invocation_idx) | 1808bf215546Sopenharmony_ci S_00B84C_LDS_SIZE(config_in->lds_size) | S_00B84C_EXCP_EN(excp_en); 1809bf215546Sopenharmony_ci config_out->rsrc3 |= S_00B8A0_SHARED_VGPR_CNT(num_shared_vgpr_blocks); 1810bf215546Sopenharmony_ci 1811bf215546Sopenharmony_ci break; 1812bf215546Sopenharmony_ci default: 1813bf215546Sopenharmony_ci unreachable("unsupported shader type"); 1814bf215546Sopenharmony_ci break; 1815bf215546Sopenharmony_ci } 1816bf215546Sopenharmony_ci 1817bf215546Sopenharmony_ci if (pdevice->rad_info.gfx_level >= GFX10 && info->is_ngg && 1818bf215546Sopenharmony_ci (stage == MESA_SHADER_VERTEX || stage == MESA_SHADER_TESS_EVAL || 1819bf215546Sopenharmony_ci stage == MESA_SHADER_GEOMETRY || stage == MESA_SHADER_MESH)) { 1820bf215546Sopenharmony_ci unsigned gs_vgpr_comp_cnt, es_vgpr_comp_cnt; 1821bf215546Sopenharmony_ci gl_shader_stage es_stage = stage; 1822bf215546Sopenharmony_ci if (stage == MESA_SHADER_GEOMETRY) 1823bf215546Sopenharmony_ci es_stage = info->gs.es_type; 1824bf215546Sopenharmony_ci 1825bf215546Sopenharmony_ci /* VGPR5-8: (VertexID, UserVGPR0, UserVGPR1, UserVGPR2 / InstanceID) */ 1826bf215546Sopenharmony_ci if (es_stage == MESA_SHADER_VERTEX) { 1827bf215546Sopenharmony_ci es_vgpr_comp_cnt = info->vs.needs_instance_id ? 3 : 0; 1828bf215546Sopenharmony_ci } else if (es_stage == MESA_SHADER_TESS_EVAL) { 1829bf215546Sopenharmony_ci bool enable_prim_id = info->tes.outinfo.export_prim_id || info->uses_prim_id; 1830bf215546Sopenharmony_ci es_vgpr_comp_cnt = enable_prim_id ? 3 : 2; 1831bf215546Sopenharmony_ci } else if (es_stage == MESA_SHADER_MESH) { 1832bf215546Sopenharmony_ci es_vgpr_comp_cnt = 0; 1833bf215546Sopenharmony_ci } else { 1834bf215546Sopenharmony_ci unreachable("Unexpected ES shader stage"); 1835bf215546Sopenharmony_ci } 1836bf215546Sopenharmony_ci 1837bf215546Sopenharmony_ci /* GS vertex offsets in NGG: 1838bf215546Sopenharmony_ci * - in passthrough mode, they are all packed into VGPR0 1839bf215546Sopenharmony_ci * - in the default mode: VGPR0: offsets 0, 1; VGPR1: offsets 2, 3 1840bf215546Sopenharmony_ci * 1841bf215546Sopenharmony_ci * The vertex offset 2 is always needed when NGG isn't in passthrough mode 1842bf215546Sopenharmony_ci * and uses triangle input primitives, including with NGG culling. 1843bf215546Sopenharmony_ci */ 1844bf215546Sopenharmony_ci bool need_gs_vtx_offset2 = !info->is_ngg_passthrough || info->gs.vertices_in >= 3; 1845bf215546Sopenharmony_ci 1846bf215546Sopenharmony_ci /* TES only needs vertex offset 2 for triangles or quads. */ 1847bf215546Sopenharmony_ci if (stage == MESA_SHADER_TESS_EVAL) 1848bf215546Sopenharmony_ci need_gs_vtx_offset2 &= info->tes._primitive_mode == TESS_PRIMITIVE_TRIANGLES || 1849bf215546Sopenharmony_ci info->tes._primitive_mode == TESS_PRIMITIVE_QUADS; 1850bf215546Sopenharmony_ci 1851bf215546Sopenharmony_ci if (info->uses_invocation_id) { 1852bf215546Sopenharmony_ci gs_vgpr_comp_cnt = 3; /* VGPR3 contains InvocationID. */ 1853bf215546Sopenharmony_ci } else if (info->uses_prim_id || (es_stage == MESA_SHADER_VERTEX && 1854bf215546Sopenharmony_ci info->vs.outinfo.export_prim_id)) { 1855bf215546Sopenharmony_ci gs_vgpr_comp_cnt = 2; /* VGPR2 contains PrimitiveID. */ 1856bf215546Sopenharmony_ci } else if (need_gs_vtx_offset2) { 1857bf215546Sopenharmony_ci gs_vgpr_comp_cnt = 1; /* VGPR1 contains offsets 2, 3 */ 1858bf215546Sopenharmony_ci } else { 1859bf215546Sopenharmony_ci gs_vgpr_comp_cnt = 0; /* VGPR0 contains offsets 0, 1 (or passthrough prim) */ 1860bf215546Sopenharmony_ci } 1861bf215546Sopenharmony_ci 1862bf215546Sopenharmony_ci /* Disable the WGP mode on gfx10.3 because it can hang. (it 1863bf215546Sopenharmony_ci * happened on VanGogh) Let's disable it on all chips that 1864bf215546Sopenharmony_ci * disable exactly 1 CU per SA for GS. 1865bf215546Sopenharmony_ci */ 1866bf215546Sopenharmony_ci config_out->rsrc1 |= 1867bf215546Sopenharmony_ci S_00B228_GS_VGPR_COMP_CNT(gs_vgpr_comp_cnt) | S_00B228_WGP_MODE(wgp_mode); 1868bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B22C_ES_VGPR_COMP_CNT(es_vgpr_comp_cnt) | 1869bf215546Sopenharmony_ci S_00B22C_LDS_SIZE(config_in->lds_size) | 1870bf215546Sopenharmony_ci S_00B22C_OC_LDS_EN(es_stage == MESA_SHADER_TESS_EVAL); 1871bf215546Sopenharmony_ci } else if (pdevice->rad_info.gfx_level >= GFX9 && stage == MESA_SHADER_GEOMETRY) { 1872bf215546Sopenharmony_ci unsigned es_type = info->gs.es_type; 1873bf215546Sopenharmony_ci unsigned gs_vgpr_comp_cnt, es_vgpr_comp_cnt; 1874bf215546Sopenharmony_ci 1875bf215546Sopenharmony_ci if (es_type == MESA_SHADER_VERTEX) { 1876bf215546Sopenharmony_ci /* VGPR0-3: (VertexID, InstanceID / StepRate0, ...) */ 1877bf215546Sopenharmony_ci if (info->vs.needs_instance_id) { 1878bf215546Sopenharmony_ci es_vgpr_comp_cnt = pdevice->rad_info.gfx_level >= GFX10 ? 3 : 1; 1879bf215546Sopenharmony_ci } else { 1880bf215546Sopenharmony_ci es_vgpr_comp_cnt = 0; 1881bf215546Sopenharmony_ci } 1882bf215546Sopenharmony_ci } else if (es_type == MESA_SHADER_TESS_EVAL) { 1883bf215546Sopenharmony_ci es_vgpr_comp_cnt = info->uses_prim_id ? 3 : 2; 1884bf215546Sopenharmony_ci } else { 1885bf215546Sopenharmony_ci unreachable("invalid shader ES type"); 1886bf215546Sopenharmony_ci } 1887bf215546Sopenharmony_ci 1888bf215546Sopenharmony_ci /* If offsets 4, 5 are used, GS_VGPR_COMP_CNT is ignored and 1889bf215546Sopenharmony_ci * VGPR[0:4] are always loaded. 1890bf215546Sopenharmony_ci */ 1891bf215546Sopenharmony_ci if (info->uses_invocation_id) { 1892bf215546Sopenharmony_ci gs_vgpr_comp_cnt = 3; /* VGPR3 contains InvocationID. */ 1893bf215546Sopenharmony_ci } else if (info->uses_prim_id) { 1894bf215546Sopenharmony_ci gs_vgpr_comp_cnt = 2; /* VGPR2 contains PrimitiveID. */ 1895bf215546Sopenharmony_ci } else if (info->gs.vertices_in >= 3) { 1896bf215546Sopenharmony_ci gs_vgpr_comp_cnt = 1; /* VGPR1 contains offsets 2, 3 */ 1897bf215546Sopenharmony_ci } else { 1898bf215546Sopenharmony_ci gs_vgpr_comp_cnt = 0; /* VGPR0 contains offsets 0, 1 */ 1899bf215546Sopenharmony_ci } 1900bf215546Sopenharmony_ci 1901bf215546Sopenharmony_ci config_out->rsrc1 |= 1902bf215546Sopenharmony_ci S_00B228_GS_VGPR_COMP_CNT(gs_vgpr_comp_cnt) | S_00B228_WGP_MODE(wgp_mode); 1903bf215546Sopenharmony_ci config_out->rsrc2 |= S_00B22C_ES_VGPR_COMP_CNT(es_vgpr_comp_cnt) | 1904bf215546Sopenharmony_ci S_00B22C_OC_LDS_EN(es_type == MESA_SHADER_TESS_EVAL); 1905bf215546Sopenharmony_ci } else if (pdevice->rad_info.gfx_level >= GFX9 && stage == MESA_SHADER_TESS_CTRL) { 1906bf215546Sopenharmony_ci config_out->rsrc1 |= S_00B428_LS_VGPR_COMP_CNT(vgpr_comp_cnt); 1907bf215546Sopenharmony_ci } else { 1908bf215546Sopenharmony_ci config_out->rsrc1 |= S_00B128_VGPR_COMP_CNT(vgpr_comp_cnt); 1909bf215546Sopenharmony_ci } 1910bf215546Sopenharmony_ci} 1911bf215546Sopenharmony_ci 1912bf215546Sopenharmony_ci#ifndef _WIN32 1913bf215546Sopenharmony_cistatic bool 1914bf215546Sopenharmony_ciradv_open_rtld_binary(struct radv_device *device, const struct radv_shader *shader, 1915bf215546Sopenharmony_ci const struct radv_shader_binary *binary, struct ac_rtld_binary *rtld_binary) 1916bf215546Sopenharmony_ci{ 1917bf215546Sopenharmony_ci const char *elf_data = (const char *)((struct radv_shader_binary_rtld *)binary)->data; 1918bf215546Sopenharmony_ci size_t elf_size = ((struct radv_shader_binary_rtld *)binary)->elf_size; 1919bf215546Sopenharmony_ci struct ac_rtld_symbol lds_symbols[3]; 1920bf215546Sopenharmony_ci unsigned num_lds_symbols = 0; 1921bf215546Sopenharmony_ci 1922bf215546Sopenharmony_ci if (device->physical_device->rad_info.gfx_level >= GFX9 && 1923bf215546Sopenharmony_ci (binary->stage == MESA_SHADER_GEOMETRY || binary->info.is_ngg) && 1924bf215546Sopenharmony_ci !binary->is_gs_copy_shader) { 1925bf215546Sopenharmony_ci struct ac_rtld_symbol *sym = &lds_symbols[num_lds_symbols++]; 1926bf215546Sopenharmony_ci sym->name = "esgs_ring"; 1927bf215546Sopenharmony_ci sym->size = binary->info.ngg_info.esgs_ring_size; 1928bf215546Sopenharmony_ci sym->align = 64 * 1024; 1929bf215546Sopenharmony_ci } 1930bf215546Sopenharmony_ci 1931bf215546Sopenharmony_ci if (binary->info.is_ngg && binary->stage == MESA_SHADER_GEOMETRY) { 1932bf215546Sopenharmony_ci struct ac_rtld_symbol *sym = &lds_symbols[num_lds_symbols++]; 1933bf215546Sopenharmony_ci sym->name = "ngg_emit"; 1934bf215546Sopenharmony_ci sym->size = binary->info.ngg_info.ngg_emit_size * 4; 1935bf215546Sopenharmony_ci sym->align = 4; 1936bf215546Sopenharmony_ci 1937bf215546Sopenharmony_ci sym = &lds_symbols[num_lds_symbols++]; 1938bf215546Sopenharmony_ci sym->name = "ngg_scratch"; 1939bf215546Sopenharmony_ci sym->size = 8; 1940bf215546Sopenharmony_ci sym->align = 4; 1941bf215546Sopenharmony_ci } 1942bf215546Sopenharmony_ci 1943bf215546Sopenharmony_ci struct ac_rtld_open_info open_info = { 1944bf215546Sopenharmony_ci .info = &device->physical_device->rad_info, 1945bf215546Sopenharmony_ci .shader_type = binary->stage, 1946bf215546Sopenharmony_ci .wave_size = binary->info.wave_size, 1947bf215546Sopenharmony_ci .num_parts = 1, 1948bf215546Sopenharmony_ci .elf_ptrs = &elf_data, 1949bf215546Sopenharmony_ci .elf_sizes = &elf_size, 1950bf215546Sopenharmony_ci .num_shared_lds_symbols = num_lds_symbols, 1951bf215546Sopenharmony_ci .shared_lds_symbols = lds_symbols, 1952bf215546Sopenharmony_ci }; 1953bf215546Sopenharmony_ci 1954bf215546Sopenharmony_ci return ac_rtld_open(rtld_binary, open_info); 1955bf215546Sopenharmony_ci} 1956bf215546Sopenharmony_ci#endif 1957bf215546Sopenharmony_ci 1958bf215546Sopenharmony_cibool 1959bf215546Sopenharmony_ciradv_shader_binary_upload(struct radv_device *device, const struct radv_shader_binary *binary, 1960bf215546Sopenharmony_ci struct radv_shader *shader, void *dest_ptr) 1961bf215546Sopenharmony_ci{ 1962bf215546Sopenharmony_ci if (binary->type == RADV_BINARY_TYPE_RTLD) { 1963bf215546Sopenharmony_ci#ifdef _WIN32 1964bf215546Sopenharmony_ci return false; 1965bf215546Sopenharmony_ci#else 1966bf215546Sopenharmony_ci struct ac_rtld_binary rtld_binary = {0}; 1967bf215546Sopenharmony_ci 1968bf215546Sopenharmony_ci if (!radv_open_rtld_binary(device, shader, binary, &rtld_binary)) { 1969bf215546Sopenharmony_ci free(shader); 1970bf215546Sopenharmony_ci return false; 1971bf215546Sopenharmony_ci } 1972bf215546Sopenharmony_ci 1973bf215546Sopenharmony_ci struct ac_rtld_upload_info info = { 1974bf215546Sopenharmony_ci .binary = &rtld_binary, 1975bf215546Sopenharmony_ci .rx_va = radv_shader_get_va(shader), 1976bf215546Sopenharmony_ci .rx_ptr = dest_ptr, 1977bf215546Sopenharmony_ci }; 1978bf215546Sopenharmony_ci 1979bf215546Sopenharmony_ci if (!ac_rtld_upload(&info)) { 1980bf215546Sopenharmony_ci radv_shader_destroy(device, shader); 1981bf215546Sopenharmony_ci ac_rtld_close(&rtld_binary); 1982bf215546Sopenharmony_ci return false; 1983bf215546Sopenharmony_ci } 1984bf215546Sopenharmony_ci 1985bf215546Sopenharmony_ci shader->code_ptr = dest_ptr; 1986bf215546Sopenharmony_ci ac_rtld_close(&rtld_binary); 1987bf215546Sopenharmony_ci#endif 1988bf215546Sopenharmony_ci } else { 1989bf215546Sopenharmony_ci struct radv_shader_binary_legacy *bin = (struct radv_shader_binary_legacy *)binary; 1990bf215546Sopenharmony_ci memcpy(dest_ptr, bin->data + bin->stats_size, bin->code_size); 1991bf215546Sopenharmony_ci 1992bf215546Sopenharmony_ci /* Add end-of-code markers for the UMR disassembler. */ 1993bf215546Sopenharmony_ci uint32_t *ptr32 = (uint32_t *)dest_ptr + bin->code_size / 4; 1994bf215546Sopenharmony_ci for (unsigned i = 0; i < DEBUGGER_NUM_MARKERS; i++) 1995bf215546Sopenharmony_ci ptr32[i] = DEBUGGER_END_OF_CODE_MARKER; 1996bf215546Sopenharmony_ci 1997bf215546Sopenharmony_ci shader->code_ptr = dest_ptr; 1998bf215546Sopenharmony_ci } 1999bf215546Sopenharmony_ci 2000bf215546Sopenharmony_ci return true; 2001bf215546Sopenharmony_ci} 2002bf215546Sopenharmony_ci 2003bf215546Sopenharmony_cistruct radv_shader * 2004bf215546Sopenharmony_ciradv_shader_create(struct radv_device *device, const struct radv_shader_binary *binary, 2005bf215546Sopenharmony_ci bool keep_shader_info, bool from_cache, const struct radv_shader_args *args) 2006bf215546Sopenharmony_ci{ 2007bf215546Sopenharmony_ci struct ac_shader_config config = {0}; 2008bf215546Sopenharmony_ci struct radv_shader *shader = calloc(1, sizeof(struct radv_shader)); 2009bf215546Sopenharmony_ci if (!shader) 2010bf215546Sopenharmony_ci return NULL; 2011bf215546Sopenharmony_ci 2012bf215546Sopenharmony_ci shader->ref_count = 1; 2013bf215546Sopenharmony_ci 2014bf215546Sopenharmony_ci if (binary->type == RADV_BINARY_TYPE_RTLD) { 2015bf215546Sopenharmony_ci#ifdef _WIN32 2016bf215546Sopenharmony_ci free(shader); 2017bf215546Sopenharmony_ci return NULL; 2018bf215546Sopenharmony_ci#else 2019bf215546Sopenharmony_ci struct ac_rtld_binary rtld_binary = {0}; 2020bf215546Sopenharmony_ci 2021bf215546Sopenharmony_ci if (!radv_open_rtld_binary(device, shader, binary, &rtld_binary)) { 2022bf215546Sopenharmony_ci free(shader); 2023bf215546Sopenharmony_ci return NULL; 2024bf215546Sopenharmony_ci } 2025bf215546Sopenharmony_ci 2026bf215546Sopenharmony_ci if (!ac_rtld_read_config(&device->physical_device->rad_info, &rtld_binary, &config)) { 2027bf215546Sopenharmony_ci ac_rtld_close(&rtld_binary); 2028bf215546Sopenharmony_ci free(shader); 2029bf215546Sopenharmony_ci return NULL; 2030bf215546Sopenharmony_ci } 2031bf215546Sopenharmony_ci 2032bf215546Sopenharmony_ci if (rtld_binary.lds_size > 0) { 2033bf215546Sopenharmony_ci unsigned encode_granularity = device->physical_device->rad_info.lds_encode_granularity; 2034bf215546Sopenharmony_ci config.lds_size = DIV_ROUND_UP(rtld_binary.lds_size, encode_granularity); 2035bf215546Sopenharmony_ci } 2036bf215546Sopenharmony_ci if (!config.lds_size && binary->stage == MESA_SHADER_TESS_CTRL) { 2037bf215546Sopenharmony_ci /* This is used for reporting LDS statistics */ 2038bf215546Sopenharmony_ci config.lds_size = binary->info.tcs.num_lds_blocks; 2039bf215546Sopenharmony_ci } 2040bf215546Sopenharmony_ci 2041bf215546Sopenharmony_ci assert(!binary->info.has_ngg_culling || config.lds_size); 2042bf215546Sopenharmony_ci 2043bf215546Sopenharmony_ci shader->code_size = rtld_binary.rx_size; 2044bf215546Sopenharmony_ci shader->exec_size = rtld_binary.exec_size; 2045bf215546Sopenharmony_ci ac_rtld_close(&rtld_binary); 2046bf215546Sopenharmony_ci#endif 2047bf215546Sopenharmony_ci } else { 2048bf215546Sopenharmony_ci assert(binary->type == RADV_BINARY_TYPE_LEGACY); 2049bf215546Sopenharmony_ci config = ((struct radv_shader_binary_legacy *)binary)->base.config; 2050bf215546Sopenharmony_ci shader->code_size = 2051bf215546Sopenharmony_ci radv_get_shader_binary_size(((struct radv_shader_binary_legacy *)binary)->code_size); 2052bf215546Sopenharmony_ci shader->exec_size = ((struct radv_shader_binary_legacy *)binary)->exec_size; 2053bf215546Sopenharmony_ci } 2054bf215546Sopenharmony_ci 2055bf215546Sopenharmony_ci shader->info = binary->info; 2056bf215546Sopenharmony_ci 2057bf215546Sopenharmony_ci if (from_cache) { 2058bf215546Sopenharmony_ci /* Copy the shader binary configuration from the cache. */ 2059bf215546Sopenharmony_ci memcpy(&shader->config, &binary->config, sizeof(shader->config)); 2060bf215546Sopenharmony_ci } else { 2061bf215546Sopenharmony_ci assert(args); 2062bf215546Sopenharmony_ci radv_postprocess_config(device, &config, &binary->info, binary->stage, args, &shader->config); 2063bf215546Sopenharmony_ci } 2064bf215546Sopenharmony_ci 2065bf215546Sopenharmony_ci if (binary->type == RADV_BINARY_TYPE_RTLD) { 2066bf215546Sopenharmony_ci#ifdef _WIN32 2067bf215546Sopenharmony_ci free(shader); 2068bf215546Sopenharmony_ci return NULL; 2069bf215546Sopenharmony_ci#else 2070bf215546Sopenharmony_ci struct radv_shader_binary_rtld *bin = (struct radv_shader_binary_rtld *)binary; 2071bf215546Sopenharmony_ci struct ac_rtld_binary rtld_binary = {0}; 2072bf215546Sopenharmony_ci 2073bf215546Sopenharmony_ci if (!radv_open_rtld_binary(device, shader, binary, &rtld_binary)) { 2074bf215546Sopenharmony_ci free(shader); 2075bf215546Sopenharmony_ci return NULL; 2076bf215546Sopenharmony_ci } 2077bf215546Sopenharmony_ci 2078bf215546Sopenharmony_ci if (keep_shader_info || (device->instance->debug_flags & RADV_DEBUG_DUMP_SHADERS)) { 2079bf215546Sopenharmony_ci const char *disasm_data; 2080bf215546Sopenharmony_ci size_t disasm_size; 2081bf215546Sopenharmony_ci if (!ac_rtld_get_section_by_name(&rtld_binary, ".AMDGPU.disasm", &disasm_data, 2082bf215546Sopenharmony_ci &disasm_size)) { 2083bf215546Sopenharmony_ci radv_shader_destroy(device, shader); 2084bf215546Sopenharmony_ci ac_rtld_close(&rtld_binary); 2085bf215546Sopenharmony_ci return NULL; 2086bf215546Sopenharmony_ci } 2087bf215546Sopenharmony_ci 2088bf215546Sopenharmony_ci shader->ir_string = 2089bf215546Sopenharmony_ci bin->llvm_ir_size ? strdup((const char *)(bin->data + bin->elf_size)) : NULL; 2090bf215546Sopenharmony_ci shader->disasm_string = malloc(disasm_size + 1); 2091bf215546Sopenharmony_ci memcpy(shader->disasm_string, disasm_data, disasm_size); 2092bf215546Sopenharmony_ci shader->disasm_string[disasm_size] = 0; 2093bf215546Sopenharmony_ci } 2094bf215546Sopenharmony_ci ac_rtld_close(&rtld_binary); 2095bf215546Sopenharmony_ci#endif 2096bf215546Sopenharmony_ci } else { 2097bf215546Sopenharmony_ci struct radv_shader_binary_legacy *bin = (struct radv_shader_binary_legacy *)binary; 2098bf215546Sopenharmony_ci 2099bf215546Sopenharmony_ci shader->ir_string = 2100bf215546Sopenharmony_ci bin->ir_size ? strdup((const char *)(bin->data + bin->stats_size + bin->code_size)) : NULL; 2101bf215546Sopenharmony_ci shader->disasm_string = 2102bf215546Sopenharmony_ci bin->disasm_size 2103bf215546Sopenharmony_ci ? strdup((const char *)(bin->data + bin->stats_size + bin->code_size + bin->ir_size)) 2104bf215546Sopenharmony_ci : NULL; 2105bf215546Sopenharmony_ci 2106bf215546Sopenharmony_ci if (bin->stats_size) { 2107bf215546Sopenharmony_ci shader->statistics = calloc(bin->stats_size, 1); 2108bf215546Sopenharmony_ci memcpy(shader->statistics, bin->data, bin->stats_size); 2109bf215546Sopenharmony_ci } 2110bf215546Sopenharmony_ci } 2111bf215546Sopenharmony_ci return shader; 2112bf215546Sopenharmony_ci} 2113bf215546Sopenharmony_ci 2114bf215546Sopenharmony_cistatic char * 2115bf215546Sopenharmony_ciradv_dump_nir_shaders(struct nir_shader *const *shaders, int shader_count) 2116bf215546Sopenharmony_ci{ 2117bf215546Sopenharmony_ci char *data = NULL; 2118bf215546Sopenharmony_ci char *ret = NULL; 2119bf215546Sopenharmony_ci size_t size = 0; 2120bf215546Sopenharmony_ci struct u_memstream mem; 2121bf215546Sopenharmony_ci if (u_memstream_open(&mem, &data, &size)) { 2122bf215546Sopenharmony_ci FILE *const memf = u_memstream_get(&mem); 2123bf215546Sopenharmony_ci for (int i = 0; i < shader_count; ++i) 2124bf215546Sopenharmony_ci nir_print_shader(shaders[i], memf); 2125bf215546Sopenharmony_ci u_memstream_close(&mem); 2126bf215546Sopenharmony_ci } 2127bf215546Sopenharmony_ci 2128bf215546Sopenharmony_ci ret = malloc(size + 1); 2129bf215546Sopenharmony_ci if (ret) { 2130bf215546Sopenharmony_ci memcpy(ret, data, size); 2131bf215546Sopenharmony_ci ret[size] = 0; 2132bf215546Sopenharmony_ci } 2133bf215546Sopenharmony_ci free(data); 2134bf215546Sopenharmony_ci return ret; 2135bf215546Sopenharmony_ci} 2136bf215546Sopenharmony_ci 2137bf215546Sopenharmony_cistatic void 2138bf215546Sopenharmony_ciradv_aco_build_shader_binary(void **bin, 2139bf215546Sopenharmony_ci gl_shader_stage stage, 2140bf215546Sopenharmony_ci bool is_gs_copy_shader, 2141bf215546Sopenharmony_ci const struct ac_shader_config *config, 2142bf215546Sopenharmony_ci const char *llvm_ir_str, 2143bf215546Sopenharmony_ci unsigned llvm_ir_size, 2144bf215546Sopenharmony_ci const char *disasm_str, 2145bf215546Sopenharmony_ci unsigned disasm_size, 2146bf215546Sopenharmony_ci uint32_t *statistics, 2147bf215546Sopenharmony_ci uint32_t stats_size, 2148bf215546Sopenharmony_ci uint32_t exec_size, 2149bf215546Sopenharmony_ci const uint32_t *code, 2150bf215546Sopenharmony_ci uint32_t code_dw) 2151bf215546Sopenharmony_ci{ 2152bf215546Sopenharmony_ci struct radv_shader_binary **binary = (struct radv_shader_binary **)bin; 2153bf215546Sopenharmony_ci size_t size = llvm_ir_size; 2154bf215546Sopenharmony_ci 2155bf215546Sopenharmony_ci size += disasm_size; 2156bf215546Sopenharmony_ci size += stats_size; 2157bf215546Sopenharmony_ci 2158bf215546Sopenharmony_ci size += code_dw * sizeof(uint32_t) + sizeof(struct radv_shader_binary_legacy); 2159bf215546Sopenharmony_ci 2160bf215546Sopenharmony_ci /* We need to calloc to prevent unintialized data because this will be used 2161bf215546Sopenharmony_ci * directly for the disk cache. Uninitialized data can appear because of 2162bf215546Sopenharmony_ci * padding in the struct or because legacy_binary->data can be at an offset 2163bf215546Sopenharmony_ci * from the start less than sizeof(radv_shader_binary_legacy). */ 2164bf215546Sopenharmony_ci struct radv_shader_binary_legacy *legacy_binary = (struct radv_shader_binary_legacy *)calloc(size, 1); 2165bf215546Sopenharmony_ci legacy_binary->base.type = RADV_BINARY_TYPE_LEGACY; 2166bf215546Sopenharmony_ci legacy_binary->base.stage = stage; 2167bf215546Sopenharmony_ci legacy_binary->base.is_gs_copy_shader = is_gs_copy_shader; 2168bf215546Sopenharmony_ci legacy_binary->base.total_size = size; 2169bf215546Sopenharmony_ci legacy_binary->base.config = *config; 2170bf215546Sopenharmony_ci 2171bf215546Sopenharmony_ci if (stats_size) 2172bf215546Sopenharmony_ci memcpy(legacy_binary->data, statistics, stats_size); 2173bf215546Sopenharmony_ci legacy_binary->stats_size = stats_size; 2174bf215546Sopenharmony_ci 2175bf215546Sopenharmony_ci memcpy(legacy_binary->data + legacy_binary->stats_size, code, 2176bf215546Sopenharmony_ci code_dw * sizeof(uint32_t)); 2177bf215546Sopenharmony_ci legacy_binary->exec_size = exec_size; 2178bf215546Sopenharmony_ci legacy_binary->code_size = code_dw * sizeof(uint32_t); 2179bf215546Sopenharmony_ci 2180bf215546Sopenharmony_ci legacy_binary->disasm_size = 0; 2181bf215546Sopenharmony_ci legacy_binary->ir_size = llvm_ir_size; 2182bf215546Sopenharmony_ci 2183bf215546Sopenharmony_ci memcpy((char*)legacy_binary->data + legacy_binary->stats_size + legacy_binary->code_size, 2184bf215546Sopenharmony_ci llvm_ir_str, llvm_ir_size); 2185bf215546Sopenharmony_ci 2186bf215546Sopenharmony_ci legacy_binary->disasm_size = disasm_size; 2187bf215546Sopenharmony_ci if (disasm_size) { 2188bf215546Sopenharmony_ci memcpy((char*)legacy_binary->data + legacy_binary->stats_size + 2189bf215546Sopenharmony_ci legacy_binary->code_size + llvm_ir_size, disasm_str, 2190bf215546Sopenharmony_ci disasm_size); 2191bf215546Sopenharmony_ci } 2192bf215546Sopenharmony_ci *binary = (struct radv_shader_binary*)legacy_binary; 2193bf215546Sopenharmony_ci} 2194bf215546Sopenharmony_ci 2195bf215546Sopenharmony_cistatic struct radv_shader * 2196bf215546Sopenharmony_cishader_compile(struct radv_device *device, struct nir_shader *const *shaders, int shader_count, gl_shader_stage stage, 2197bf215546Sopenharmony_ci struct radv_shader_info *info, const struct radv_shader_args *args, 2198bf215546Sopenharmony_ci struct radv_nir_compiler_options *options, bool gs_copy_shader, 2199bf215546Sopenharmony_ci bool trap_handler_shader, bool keep_shader_info, bool keep_statistic_info, 2200bf215546Sopenharmony_ci struct radv_shader_binary **binary_out) 2201bf215546Sopenharmony_ci{ 2202bf215546Sopenharmony_ci enum radeon_family chip_family = device->physical_device->rad_info.family; 2203bf215546Sopenharmony_ci struct radv_shader_binary *binary = NULL; 2204bf215546Sopenharmony_ci 2205bf215546Sopenharmony_ci struct radv_shader_debug_data debug_data = { 2206bf215546Sopenharmony_ci .device = device, 2207bf215546Sopenharmony_ci .object = NULL, 2208bf215546Sopenharmony_ci }; 2209bf215546Sopenharmony_ci 2210bf215546Sopenharmony_ci options->family = chip_family; 2211bf215546Sopenharmony_ci options->gfx_level = device->physical_device->rad_info.gfx_level; 2212bf215546Sopenharmony_ci options->has_3d_cube_border_color_mipmap = device->physical_device->rad_info.has_3d_cube_border_color_mipmap; 2213bf215546Sopenharmony_ci options->dump_shader = radv_can_dump_shader(device, shaders[0], gs_copy_shader || trap_handler_shader); 2214bf215546Sopenharmony_ci options->dump_preoptir = 2215bf215546Sopenharmony_ci options->dump_shader && device->instance->debug_flags & RADV_DEBUG_PREOPTIR; 2216bf215546Sopenharmony_ci options->record_ir = keep_shader_info; 2217bf215546Sopenharmony_ci options->record_stats = keep_statistic_info; 2218bf215546Sopenharmony_ci options->check_ir = device->instance->debug_flags & RADV_DEBUG_CHECKIR; 2219bf215546Sopenharmony_ci options->address32_hi = device->physical_device->rad_info.address32_hi; 2220bf215546Sopenharmony_ci options->has_ls_vgpr_init_bug = device->physical_device->rad_info.has_ls_vgpr_init_bug; 2221bf215546Sopenharmony_ci options->enable_mrt_output_nan_fixup = 2222bf215546Sopenharmony_ci !is_meta_shader(shaders[0]) && options->key.ps.enable_mrt_output_nan_fixup; 2223bf215546Sopenharmony_ci options->debug.func = radv_compiler_debug; 2224bf215546Sopenharmony_ci options->debug.private_data = &debug_data; 2225bf215546Sopenharmony_ci 2226bf215546Sopenharmony_ci#ifdef LLVM_AVAILABLE 2227bf215546Sopenharmony_ci if (radv_use_llvm_for_stage(device, stage) || options->dump_shader || options->record_ir) 2228bf215546Sopenharmony_ci ac_init_llvm_once(); 2229bf215546Sopenharmony_ci 2230bf215546Sopenharmony_ci if (radv_use_llvm_for_stage(device, stage)) { 2231bf215546Sopenharmony_ci llvm_compile_shader(options, info, shader_count, shaders, &binary, args); 2232bf215546Sopenharmony_ci#else 2233bf215546Sopenharmony_ci if (false) { 2234bf215546Sopenharmony_ci#endif 2235bf215546Sopenharmony_ci } else { 2236bf215546Sopenharmony_ci struct aco_shader_info ac_info; 2237bf215546Sopenharmony_ci struct aco_compiler_options ac_opts; 2238bf215546Sopenharmony_ci radv_aco_convert_opts(&ac_opts, options); 2239bf215546Sopenharmony_ci radv_aco_convert_shader_info(&ac_info, info); 2240bf215546Sopenharmony_ci aco_compile_shader(&ac_opts, &ac_info, shader_count, shaders, args, &radv_aco_build_shader_binary, (void **)&binary); 2241bf215546Sopenharmony_ci } 2242bf215546Sopenharmony_ci 2243bf215546Sopenharmony_ci binary->info = *info; 2244bf215546Sopenharmony_ci 2245bf215546Sopenharmony_ci struct radv_shader *shader = radv_shader_create(device, binary, keep_shader_info, false, args); 2246bf215546Sopenharmony_ci if (!shader) { 2247bf215546Sopenharmony_ci free(binary); 2248bf215546Sopenharmony_ci return NULL; 2249bf215546Sopenharmony_ci } 2250bf215546Sopenharmony_ci 2251bf215546Sopenharmony_ci if (options->dump_shader) { 2252bf215546Sopenharmony_ci fprintf(stderr, "%s", radv_get_shader_name(info, shaders[0]->info.stage)); 2253bf215546Sopenharmony_ci for (int i = 1; i < shader_count; ++i) 2254bf215546Sopenharmony_ci fprintf(stderr, " + %s", radv_get_shader_name(info, shaders[i]->info.stage)); 2255bf215546Sopenharmony_ci 2256bf215546Sopenharmony_ci fprintf(stderr, "\ndisasm:\n%s\n", shader->disasm_string); 2257bf215546Sopenharmony_ci } 2258bf215546Sopenharmony_ci 2259bf215546Sopenharmony_ci if (keep_shader_info) { 2260bf215546Sopenharmony_ci shader->nir_string = radv_dump_nir_shaders(shaders, shader_count); 2261bf215546Sopenharmony_ci } 2262bf215546Sopenharmony_ci 2263bf215546Sopenharmony_ci /* Copy the shader binary configuration to store it in the cache. */ 2264bf215546Sopenharmony_ci memcpy(&binary->config, &shader->config, sizeof(binary->config)); 2265bf215546Sopenharmony_ci 2266bf215546Sopenharmony_ci *binary_out = binary; 2267bf215546Sopenharmony_ci return shader; 2268bf215546Sopenharmony_ci} 2269bf215546Sopenharmony_ci 2270bf215546Sopenharmony_cistruct radv_shader * 2271bf215546Sopenharmony_ciradv_shader_nir_to_asm(struct radv_device *device, struct radv_pipeline_stage *pl_stage, 2272bf215546Sopenharmony_ci struct nir_shader *const *shaders, int shader_count, 2273bf215546Sopenharmony_ci const struct radv_pipeline_key *key, bool keep_shader_info, 2274bf215546Sopenharmony_ci bool keep_statistic_info, struct radv_shader_binary **binary_out) 2275bf215546Sopenharmony_ci{ 2276bf215546Sopenharmony_ci gl_shader_stage stage = shaders[shader_count - 1]->info.stage; 2277bf215546Sopenharmony_ci struct radv_nir_compiler_options options = {0}; 2278bf215546Sopenharmony_ci 2279bf215546Sopenharmony_ci if (key) 2280bf215546Sopenharmony_ci options.key = *key; 2281bf215546Sopenharmony_ci 2282bf215546Sopenharmony_ci options.robust_buffer_access = device->robust_buffer_access; 2283bf215546Sopenharmony_ci options.wgp_mode = radv_should_use_wgp_mode(device, stage, &pl_stage->info); 2284bf215546Sopenharmony_ci 2285bf215546Sopenharmony_ci return shader_compile(device, shaders, shader_count, stage, &pl_stage->info, 2286bf215546Sopenharmony_ci &pl_stage->args, &options, false, false, keep_shader_info, 2287bf215546Sopenharmony_ci keep_statistic_info, binary_out); 2288bf215546Sopenharmony_ci} 2289bf215546Sopenharmony_ci 2290bf215546Sopenharmony_cistruct radv_shader * 2291bf215546Sopenharmony_ciradv_create_gs_copy_shader(struct radv_device *device, struct nir_shader *shader, 2292bf215546Sopenharmony_ci struct radv_shader_info *info, const struct radv_shader_args *args, 2293bf215546Sopenharmony_ci struct radv_shader_binary **binary_out, bool keep_shader_info, 2294bf215546Sopenharmony_ci bool keep_statistic_info, bool disable_optimizations) 2295bf215546Sopenharmony_ci{ 2296bf215546Sopenharmony_ci struct radv_nir_compiler_options options = {0}; 2297bf215546Sopenharmony_ci gl_shader_stage stage = MESA_SHADER_VERTEX; 2298bf215546Sopenharmony_ci 2299bf215546Sopenharmony_ci options.key.optimisations_disabled = disable_optimizations; 2300bf215546Sopenharmony_ci 2301bf215546Sopenharmony_ci return shader_compile(device, &shader, 1, stage, info, args, &options, true, false, 2302bf215546Sopenharmony_ci keep_shader_info, keep_statistic_info, binary_out); 2303bf215546Sopenharmony_ci} 2304bf215546Sopenharmony_ci 2305bf215546Sopenharmony_cistruct radv_trap_handler_shader * 2306bf215546Sopenharmony_ciradv_create_trap_handler_shader(struct radv_device *device) 2307bf215546Sopenharmony_ci{ 2308bf215546Sopenharmony_ci struct radv_nir_compiler_options options = {0}; 2309bf215546Sopenharmony_ci struct radv_shader *shader = NULL; 2310bf215546Sopenharmony_ci struct radv_shader_binary *binary = NULL; 2311bf215546Sopenharmony_ci struct radv_shader_info info = {0}; 2312bf215546Sopenharmony_ci struct radv_pipeline_key key = {0}; 2313bf215546Sopenharmony_ci struct radv_trap_handler_shader *trap; 2314bf215546Sopenharmony_ci 2315bf215546Sopenharmony_ci trap = malloc(sizeof(struct radv_trap_handler_shader)); 2316bf215546Sopenharmony_ci if (!trap) 2317bf215546Sopenharmony_ci return NULL; 2318bf215546Sopenharmony_ci 2319bf215546Sopenharmony_ci nir_builder b = radv_meta_init_shader(device, MESA_SHADER_COMPUTE, "meta_trap_handler"); 2320bf215546Sopenharmony_ci 2321bf215546Sopenharmony_ci options.wgp_mode = radv_should_use_wgp_mode(device, MESA_SHADER_COMPUTE, &info); 2322bf215546Sopenharmony_ci info.wave_size = 64; 2323bf215546Sopenharmony_ci 2324bf215546Sopenharmony_ci struct radv_shader_args args; 2325bf215546Sopenharmony_ci args.explicit_scratch_args = true; 2326bf215546Sopenharmony_ci args.is_trap_handler_shader = true; 2327bf215546Sopenharmony_ci radv_declare_shader_args(device->physical_device->rad_info.gfx_level, &key, &info, 2328bf215546Sopenharmony_ci MESA_SHADER_COMPUTE, false, MESA_SHADER_VERTEX, &args); 2329bf215546Sopenharmony_ci 2330bf215546Sopenharmony_ci shader = shader_compile(device, &b.shader, 1, MESA_SHADER_COMPUTE, &info, &args, &options, 2331bf215546Sopenharmony_ci false, true, false, false, &binary); 2332bf215546Sopenharmony_ci 2333bf215546Sopenharmony_ci trap->alloc = radv_alloc_shader_memory(device, shader->code_size, NULL); 2334bf215546Sopenharmony_ci 2335bf215546Sopenharmony_ci trap->bo = trap->alloc->arena->bo; 2336bf215546Sopenharmony_ci char *dest_ptr = trap->alloc->arena->ptr + trap->alloc->offset; 2337bf215546Sopenharmony_ci 2338bf215546Sopenharmony_ci struct radv_shader_binary_legacy *bin = (struct radv_shader_binary_legacy *)binary; 2339bf215546Sopenharmony_ci memcpy(dest_ptr, bin->data, bin->code_size); 2340bf215546Sopenharmony_ci 2341bf215546Sopenharmony_ci ralloc_free(b.shader); 2342bf215546Sopenharmony_ci free(shader); 2343bf215546Sopenharmony_ci free(binary); 2344bf215546Sopenharmony_ci 2345bf215546Sopenharmony_ci return trap; 2346bf215546Sopenharmony_ci} 2347bf215546Sopenharmony_ci 2348bf215546Sopenharmony_ciuint64_t radv_trap_handler_shader_get_va(const struct radv_trap_handler_shader *trap) 2349bf215546Sopenharmony_ci{ 2350bf215546Sopenharmony_ci return radv_buffer_get_va(trap->alloc->arena->bo) + trap->alloc->offset; 2351bf215546Sopenharmony_ci} 2352bf215546Sopenharmony_ci 2353bf215546Sopenharmony_civoid 2354bf215546Sopenharmony_ciradv_trap_handler_shader_destroy(struct radv_device *device, struct radv_trap_handler_shader *trap) 2355bf215546Sopenharmony_ci{ 2356bf215546Sopenharmony_ci if (!trap) 2357bf215546Sopenharmony_ci return; 2358bf215546Sopenharmony_ci 2359bf215546Sopenharmony_ci radv_free_shader_memory(device, trap->alloc); 2360bf215546Sopenharmony_ci free(trap); 2361bf215546Sopenharmony_ci} 2362bf215546Sopenharmony_ci 2363bf215546Sopenharmony_cistatic struct radv_shader_part * 2364bf215546Sopenharmony_ciupload_shader_part(struct radv_device *device, struct radv_shader_part_binary *bin, unsigned wave_size) 2365bf215546Sopenharmony_ci{ 2366bf215546Sopenharmony_ci uint32_t code_size = radv_get_shader_binary_size(bin->code_size); 2367bf215546Sopenharmony_ci struct radv_shader_part *shader_part = malloc(sizeof(struct radv_shader_part)); 2368bf215546Sopenharmony_ci if (!shader_part) 2369bf215546Sopenharmony_ci return NULL; 2370bf215546Sopenharmony_ci 2371bf215546Sopenharmony_ci shader_part->alloc = radv_alloc_shader_memory(device, code_size, NULL); 2372bf215546Sopenharmony_ci if (!shader_part->alloc) { 2373bf215546Sopenharmony_ci free(shader_part); 2374bf215546Sopenharmony_ci return NULL; 2375bf215546Sopenharmony_ci } 2376bf215546Sopenharmony_ci 2377bf215546Sopenharmony_ci shader_part->bo = shader_part->alloc->arena->bo; 2378bf215546Sopenharmony_ci char *dest_ptr = shader_part->alloc->arena->ptr + shader_part->alloc->offset; 2379bf215546Sopenharmony_ci 2380bf215546Sopenharmony_ci memcpy(dest_ptr, bin->data, bin->code_size); 2381bf215546Sopenharmony_ci 2382bf215546Sopenharmony_ci /* Add end-of-code markers for the UMR disassembler. */ 2383bf215546Sopenharmony_ci uint32_t *ptr32 = (uint32_t *)dest_ptr + bin->code_size / 4; 2384bf215546Sopenharmony_ci for (unsigned i = 0; i < DEBUGGER_NUM_MARKERS; i++) 2385bf215546Sopenharmony_ci ptr32[i] = DEBUGGER_END_OF_CODE_MARKER; 2386bf215546Sopenharmony_ci 2387bf215546Sopenharmony_ci shader_part->rsrc1 = S_00B848_VGPRS((bin->num_vgprs - 1) / (wave_size == 32 ? 8 : 4)) | 2388bf215546Sopenharmony_ci S_00B228_SGPRS((bin->num_sgprs - 1) / 8); 2389bf215546Sopenharmony_ci shader_part->num_preserved_sgprs = bin->num_preserved_sgprs; 2390bf215546Sopenharmony_ci shader_part->disasm_string = NULL; 2391bf215546Sopenharmony_ci 2392bf215546Sopenharmony_ci return shader_part; 2393bf215546Sopenharmony_ci} 2394bf215546Sopenharmony_ci 2395bf215546Sopenharmony_cistatic void radv_aco_build_shader_part(void **bin, 2396bf215546Sopenharmony_ci uint32_t num_sgprs, 2397bf215546Sopenharmony_ci uint32_t num_vgprs, 2398bf215546Sopenharmony_ci uint32_t num_preserved_sgprs, 2399bf215546Sopenharmony_ci const uint32_t *code, 2400bf215546Sopenharmony_ci uint32_t code_size, 2401bf215546Sopenharmony_ci const char *disasm_str, 2402bf215546Sopenharmony_ci uint32_t disasm_size) 2403bf215546Sopenharmony_ci{ 2404bf215546Sopenharmony_ci struct radv_shader_part_binary **binary = (struct radv_shader_part_binary **)bin; 2405bf215546Sopenharmony_ci size_t size = code_size * sizeof(uint32_t) + sizeof(struct radv_shader_part_binary); 2406bf215546Sopenharmony_ci 2407bf215546Sopenharmony_ci size += disasm_size; 2408bf215546Sopenharmony_ci struct radv_shader_part_binary *part_binary = (struct radv_shader_part_binary *)calloc(size, 1); 2409bf215546Sopenharmony_ci 2410bf215546Sopenharmony_ci part_binary->num_sgprs = num_sgprs; 2411bf215546Sopenharmony_ci part_binary->num_vgprs = num_vgprs; 2412bf215546Sopenharmony_ci part_binary->num_preserved_sgprs = num_preserved_sgprs; 2413bf215546Sopenharmony_ci part_binary->code_size = code_size * sizeof(uint32_t); 2414bf215546Sopenharmony_ci memcpy(part_binary->data, code, part_binary->code_size); 2415bf215546Sopenharmony_ci if (disasm_size) { 2416bf215546Sopenharmony_ci memcpy((char*)part_binary->data + part_binary->code_size, 2417bf215546Sopenharmony_ci disasm_str, disasm_size); 2418bf215546Sopenharmony_ci part_binary->disasm_size = disasm_size; 2419bf215546Sopenharmony_ci } 2420bf215546Sopenharmony_ci 2421bf215546Sopenharmony_ci *binary = part_binary; 2422bf215546Sopenharmony_ci} 2423bf215546Sopenharmony_ci 2424bf215546Sopenharmony_cistruct radv_shader_part * 2425bf215546Sopenharmony_ciradv_create_vs_prolog(struct radv_device *device, const struct radv_vs_prolog_key *key) 2426bf215546Sopenharmony_ci{ 2427bf215546Sopenharmony_ci struct radv_shader_args args = {0}; 2428bf215546Sopenharmony_ci struct radv_nir_compiler_options options = {0}; 2429bf215546Sopenharmony_ci options.family = device->physical_device->rad_info.family; 2430bf215546Sopenharmony_ci options.gfx_level = device->physical_device->rad_info.gfx_level; 2431bf215546Sopenharmony_ci options.has_3d_cube_border_color_mipmap = device->physical_device->rad_info.has_3d_cube_border_color_mipmap; 2432bf215546Sopenharmony_ci options.address32_hi = device->physical_device->rad_info.address32_hi; 2433bf215546Sopenharmony_ci options.dump_shader = device->instance->debug_flags & RADV_DEBUG_DUMP_PROLOGS; 2434bf215546Sopenharmony_ci options.record_ir = device->instance->debug_flags & RADV_DEBUG_HANG; 2435bf215546Sopenharmony_ci 2436bf215546Sopenharmony_ci struct radv_shader_info info = {0}; 2437bf215546Sopenharmony_ci info.wave_size = key->wave32 ? 32 : 64; 2438bf215546Sopenharmony_ci info.vs.needs_instance_id = true; 2439bf215546Sopenharmony_ci info.vs.needs_base_instance = true; 2440bf215546Sopenharmony_ci info.vs.needs_draw_id = true; 2441bf215546Sopenharmony_ci info.vs.use_per_attribute_vb_descs = true; 2442bf215546Sopenharmony_ci info.vs.vb_desc_usage_mask = BITFIELD_MASK(key->num_attributes); 2443bf215546Sopenharmony_ci info.vs.has_prolog = true; 2444bf215546Sopenharmony_ci info.vs.as_ls = key->as_ls; 2445bf215546Sopenharmony_ci info.is_ngg = key->is_ngg; 2446bf215546Sopenharmony_ci 2447bf215546Sopenharmony_ci struct radv_pipeline_key pipeline_key = {0}; 2448bf215546Sopenharmony_ci 2449bf215546Sopenharmony_ci args.explicit_scratch_args = true; 2450bf215546Sopenharmony_ci radv_declare_shader_args(options.gfx_level, &pipeline_key, &info, key->next_stage, 2451bf215546Sopenharmony_ci key->next_stage != MESA_SHADER_VERTEX, MESA_SHADER_VERTEX, &args); 2452bf215546Sopenharmony_ci 2453bf215546Sopenharmony_ci info.user_sgprs_locs = args.user_sgprs_locs; 2454bf215546Sopenharmony_ci info.inline_push_constant_mask = args.ac.inline_push_const_mask; 2455bf215546Sopenharmony_ci 2456bf215546Sopenharmony_ci#ifdef LLVM_AVAILABLE 2457bf215546Sopenharmony_ci if (options.dump_shader || options.record_ir) 2458bf215546Sopenharmony_ci ac_init_llvm_once(); 2459bf215546Sopenharmony_ci#endif 2460bf215546Sopenharmony_ci 2461bf215546Sopenharmony_ci struct radv_shader_part_binary *binary = NULL; 2462bf215546Sopenharmony_ci struct aco_shader_info ac_info; 2463bf215546Sopenharmony_ci struct aco_vs_prolog_key ac_key; 2464bf215546Sopenharmony_ci struct aco_compiler_options ac_opts; 2465bf215546Sopenharmony_ci radv_aco_convert_shader_info(&ac_info, &info); 2466bf215546Sopenharmony_ci radv_aco_convert_opts(&ac_opts, &options); 2467bf215546Sopenharmony_ci radv_aco_convert_vs_prolog_key(&ac_key, key); 2468bf215546Sopenharmony_ci aco_compile_vs_prolog(&ac_opts, &ac_info, &ac_key, &args, &radv_aco_build_shader_part, 2469bf215546Sopenharmony_ci (void **)&binary); 2470bf215546Sopenharmony_ci struct radv_shader_part *prolog = upload_shader_part(device, binary, info.wave_size); 2471bf215546Sopenharmony_ci if (prolog) { 2472bf215546Sopenharmony_ci prolog->nontrivial_divisors = key->state->nontrivial_divisors; 2473bf215546Sopenharmony_ci prolog->disasm_string = 2474bf215546Sopenharmony_ci binary->disasm_size ? strdup((const char *)(binary->data + binary->code_size)) : NULL; 2475bf215546Sopenharmony_ci } 2476bf215546Sopenharmony_ci 2477bf215546Sopenharmony_ci free(binary); 2478bf215546Sopenharmony_ci 2479bf215546Sopenharmony_ci if (prolog && options.dump_shader) { 2480bf215546Sopenharmony_ci fprintf(stderr, "Vertex prolog"); 2481bf215546Sopenharmony_ci fprintf(stderr, "\ndisasm:\n%s\n", prolog->disasm_string); 2482bf215546Sopenharmony_ci } 2483bf215546Sopenharmony_ci 2484bf215546Sopenharmony_ci return prolog; 2485bf215546Sopenharmony_ci} 2486bf215546Sopenharmony_ci 2487bf215546Sopenharmony_cistruct radv_shader_part * 2488bf215546Sopenharmony_ciradv_create_ps_epilog(struct radv_device *device, const struct radv_ps_epilog_key *key) 2489bf215546Sopenharmony_ci{ 2490bf215546Sopenharmony_ci struct radv_shader_args args = {0}; 2491bf215546Sopenharmony_ci struct radv_nir_compiler_options options = {0}; 2492bf215546Sopenharmony_ci options.family = device->physical_device->rad_info.family; 2493bf215546Sopenharmony_ci options.gfx_level = device->physical_device->rad_info.gfx_level; 2494bf215546Sopenharmony_ci options.address32_hi = device->physical_device->rad_info.address32_hi; 2495bf215546Sopenharmony_ci options.dump_shader = device->instance->debug_flags & RADV_DEBUG_DUMP_EPILOGS; 2496bf215546Sopenharmony_ci options.record_ir = device->instance->debug_flags & RADV_DEBUG_HANG; 2497bf215546Sopenharmony_ci options.dump_preoptir = device->instance->debug_flags & RADV_DEBUG_DUMP_EPILOGS; 2498bf215546Sopenharmony_ci options.dump_shader = device->instance->debug_flags & RADV_DEBUG_DUMP_EPILOGS; 2499bf215546Sopenharmony_ci 2500bf215546Sopenharmony_ci struct radv_shader_info info = {0}; 2501bf215546Sopenharmony_ci info.wave_size = key->wave32 ? 32 : 64; 2502bf215546Sopenharmony_ci info.workgroup_size = 64; 2503bf215546Sopenharmony_ci 2504bf215546Sopenharmony_ci radv_declare_ps_epilog_args(device->physical_device->rad_info.gfx_level, key, &args); 2505bf215546Sopenharmony_ci 2506bf215546Sopenharmony_ci#ifdef LLVM_AVAILABLE 2507bf215546Sopenharmony_ci if (options.dump_shader || options.record_ir) 2508bf215546Sopenharmony_ci ac_init_llvm_once(); 2509bf215546Sopenharmony_ci#endif 2510bf215546Sopenharmony_ci 2511bf215546Sopenharmony_ci struct radv_shader_part_binary *binary = NULL; 2512bf215546Sopenharmony_ci struct aco_shader_info ac_info; 2513bf215546Sopenharmony_ci struct aco_ps_epilog_key ac_key; 2514bf215546Sopenharmony_ci struct aco_compiler_options ac_opts; 2515bf215546Sopenharmony_ci radv_aco_convert_shader_info(&ac_info, &info); 2516bf215546Sopenharmony_ci radv_aco_convert_opts(&ac_opts, &options); 2517bf215546Sopenharmony_ci radv_aco_convert_ps_epilog_key(&ac_key, key); 2518bf215546Sopenharmony_ci aco_compile_ps_epilog(&ac_opts, &ac_info, &ac_key, &args, &radv_aco_build_shader_part, 2519bf215546Sopenharmony_ci (void **)&binary); 2520bf215546Sopenharmony_ci struct radv_shader_part *epilog = upload_shader_part(device, binary, info.wave_size); 2521bf215546Sopenharmony_ci if (epilog) { 2522bf215546Sopenharmony_ci epilog->disasm_string = 2523bf215546Sopenharmony_ci binary->disasm_size ? strdup((const char *)(binary->data + binary->code_size)) : NULL; 2524bf215546Sopenharmony_ci } 2525bf215546Sopenharmony_ci 2526bf215546Sopenharmony_ci free(binary); 2527bf215546Sopenharmony_ci 2528bf215546Sopenharmony_ci if (epilog && options.dump_shader) { 2529bf215546Sopenharmony_ci fprintf(stderr, "Fragment epilog"); 2530bf215546Sopenharmony_ci fprintf(stderr, "\ndisasm:\n%s\n", epilog->disasm_string); 2531bf215546Sopenharmony_ci } 2532bf215546Sopenharmony_ci 2533bf215546Sopenharmony_ci return epilog; 2534bf215546Sopenharmony_ci} 2535bf215546Sopenharmony_ci 2536bf215546Sopenharmony_civoid 2537bf215546Sopenharmony_ciradv_shader_destroy(struct radv_device *device, struct radv_shader *shader) 2538bf215546Sopenharmony_ci{ 2539bf215546Sopenharmony_ci if (!p_atomic_dec_zero(&shader->ref_count)) 2540bf215546Sopenharmony_ci return; 2541bf215546Sopenharmony_ci 2542bf215546Sopenharmony_ci free(shader->spirv); 2543bf215546Sopenharmony_ci free(shader->nir_string); 2544bf215546Sopenharmony_ci free(shader->disasm_string); 2545bf215546Sopenharmony_ci free(shader->ir_string); 2546bf215546Sopenharmony_ci free(shader->statistics); 2547bf215546Sopenharmony_ci free(shader); 2548bf215546Sopenharmony_ci} 2549bf215546Sopenharmony_ci 2550bf215546Sopenharmony_civoid 2551bf215546Sopenharmony_ciradv_shader_part_destroy(struct radv_device *device, struct radv_shader_part *shader_part) 2552bf215546Sopenharmony_ci{ 2553bf215546Sopenharmony_ci if (!shader_part) 2554bf215546Sopenharmony_ci return; 2555bf215546Sopenharmony_ci 2556bf215546Sopenharmony_ci radv_free_shader_memory(device, shader_part->alloc); 2557bf215546Sopenharmony_ci free(shader_part->disasm_string); 2558bf215546Sopenharmony_ci free(shader_part); 2559bf215546Sopenharmony_ci} 2560bf215546Sopenharmony_ci 2561bf215546Sopenharmony_ciuint64_t 2562bf215546Sopenharmony_ciradv_shader_get_va(const struct radv_shader *shader) 2563bf215546Sopenharmony_ci{ 2564bf215546Sopenharmony_ci return shader->va; 2565bf215546Sopenharmony_ci} 2566bf215546Sopenharmony_ci 2567bf215546Sopenharmony_cistruct radv_shader * 2568bf215546Sopenharmony_ciradv_find_shader(struct radv_device *device, uint64_t pc) 2569bf215546Sopenharmony_ci{ 2570bf215546Sopenharmony_ci mtx_lock(&device->shader_arena_mutex); 2571bf215546Sopenharmony_ci list_for_each_entry(struct radv_shader_arena, arena, &device->shader_arenas, list) 2572bf215546Sopenharmony_ci { 2573bf215546Sopenharmony_ci#ifdef __GNUC__ 2574bf215546Sopenharmony_ci#pragma GCC diagnostic push 2575bf215546Sopenharmony_ci#pragma GCC diagnostic ignored "-Wshadow" 2576bf215546Sopenharmony_ci#endif 2577bf215546Sopenharmony_ci list_for_each_entry(union radv_shader_arena_block, block, &arena->entries, list) 2578bf215546Sopenharmony_ci { 2579bf215546Sopenharmony_ci#ifdef __GNUC__ 2580bf215546Sopenharmony_ci#pragma GCC diagnostic pop 2581bf215546Sopenharmony_ci#endif 2582bf215546Sopenharmony_ci uint64_t start = radv_buffer_get_va(block->arena->bo) + block->offset; 2583bf215546Sopenharmony_ci if (!block->freelist.prev && pc >= start && pc < start + block->size) { 2584bf215546Sopenharmony_ci mtx_unlock(&device->shader_arena_mutex); 2585bf215546Sopenharmony_ci 2586bf215546Sopenharmony_ci struct radv_pipeline *pipeline = (struct radv_pipeline *)block->freelist.next; 2587bf215546Sopenharmony_ci for (uint32_t i = 0; i < MESA_VULKAN_SHADER_STAGES; i++) { 2588bf215546Sopenharmony_ci struct radv_shader *shader = pipeline->shaders[i]; 2589bf215546Sopenharmony_ci if (!shader) 2590bf215546Sopenharmony_ci continue; 2591bf215546Sopenharmony_ci 2592bf215546Sopenharmony_ci if (pc >= shader->va && 2593bf215546Sopenharmony_ci pc < shader->va + align(shader->code_size, RADV_SHADER_ALLOC_ALIGNMENT)) 2594bf215546Sopenharmony_ci return shader; 2595bf215546Sopenharmony_ci } 2596bf215546Sopenharmony_ci } 2597bf215546Sopenharmony_ci } 2598bf215546Sopenharmony_ci } 2599bf215546Sopenharmony_ci 2600bf215546Sopenharmony_ci mtx_unlock(&device->shader_arena_mutex); 2601bf215546Sopenharmony_ci return NULL; 2602bf215546Sopenharmony_ci} 2603bf215546Sopenharmony_ci 2604bf215546Sopenharmony_ciconst char * 2605bf215546Sopenharmony_ciradv_get_shader_name(const struct radv_shader_info *info, gl_shader_stage stage) 2606bf215546Sopenharmony_ci{ 2607bf215546Sopenharmony_ci switch (stage) { 2608bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: 2609bf215546Sopenharmony_ci if (info->vs.as_ls) 2610bf215546Sopenharmony_ci return "Vertex Shader as LS"; 2611bf215546Sopenharmony_ci else if (info->vs.as_es) 2612bf215546Sopenharmony_ci return "Vertex Shader as ES"; 2613bf215546Sopenharmony_ci else if (info->is_ngg) 2614bf215546Sopenharmony_ci return "Vertex Shader as ESGS"; 2615bf215546Sopenharmony_ci else 2616bf215546Sopenharmony_ci return "Vertex Shader as VS"; 2617bf215546Sopenharmony_ci case MESA_SHADER_TESS_CTRL: 2618bf215546Sopenharmony_ci return "Tessellation Control Shader"; 2619bf215546Sopenharmony_ci case MESA_SHADER_TESS_EVAL: 2620bf215546Sopenharmony_ci if (info->tes.as_es) 2621bf215546Sopenharmony_ci return "Tessellation Evaluation Shader as ES"; 2622bf215546Sopenharmony_ci else if (info->is_ngg) 2623bf215546Sopenharmony_ci return "Tessellation Evaluation Shader as ESGS"; 2624bf215546Sopenharmony_ci else 2625bf215546Sopenharmony_ci return "Tessellation Evaluation Shader as VS"; 2626bf215546Sopenharmony_ci case MESA_SHADER_GEOMETRY: 2627bf215546Sopenharmony_ci return "Geometry Shader"; 2628bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: 2629bf215546Sopenharmony_ci return "Pixel Shader"; 2630bf215546Sopenharmony_ci case MESA_SHADER_COMPUTE: 2631bf215546Sopenharmony_ci return "Compute Shader"; 2632bf215546Sopenharmony_ci case MESA_SHADER_MESH: 2633bf215546Sopenharmony_ci return "Mesh Shader as NGG"; 2634bf215546Sopenharmony_ci case MESA_SHADER_TASK: 2635bf215546Sopenharmony_ci return "Task Shader as CS"; 2636bf215546Sopenharmony_ci default: 2637bf215546Sopenharmony_ci return "Unknown shader"; 2638bf215546Sopenharmony_ci }; 2639bf215546Sopenharmony_ci} 2640bf215546Sopenharmony_ci 2641bf215546Sopenharmony_ciunsigned 2642bf215546Sopenharmony_ciradv_get_max_waves(const struct radv_device *device, struct radv_shader *shader, 2643bf215546Sopenharmony_ci gl_shader_stage stage) 2644bf215546Sopenharmony_ci{ 2645bf215546Sopenharmony_ci struct radeon_info *info = &device->physical_device->rad_info; 2646bf215546Sopenharmony_ci enum amd_gfx_level gfx_level = info->gfx_level; 2647bf215546Sopenharmony_ci uint8_t wave_size = shader->info.wave_size; 2648bf215546Sopenharmony_ci struct ac_shader_config *conf = &shader->config; 2649bf215546Sopenharmony_ci unsigned max_simd_waves; 2650bf215546Sopenharmony_ci unsigned lds_per_wave = 0; 2651bf215546Sopenharmony_ci 2652bf215546Sopenharmony_ci max_simd_waves = info->max_wave64_per_simd * (64 / wave_size); 2653bf215546Sopenharmony_ci 2654bf215546Sopenharmony_ci if (stage == MESA_SHADER_FRAGMENT) { 2655bf215546Sopenharmony_ci lds_per_wave = 2656bf215546Sopenharmony_ci conf->lds_size * info->lds_encode_granularity + shader->info.ps.num_interp * 48; 2657bf215546Sopenharmony_ci lds_per_wave = align(lds_per_wave, info->lds_alloc_granularity); 2658bf215546Sopenharmony_ci } else if (stage == MESA_SHADER_COMPUTE || stage == MESA_SHADER_TASK) { 2659bf215546Sopenharmony_ci unsigned max_workgroup_size = shader->info.workgroup_size; 2660bf215546Sopenharmony_ci lds_per_wave = 2661bf215546Sopenharmony_ci align(conf->lds_size * info->lds_encode_granularity, info->lds_alloc_granularity); 2662bf215546Sopenharmony_ci lds_per_wave /= DIV_ROUND_UP(max_workgroup_size, wave_size); 2663bf215546Sopenharmony_ci } 2664bf215546Sopenharmony_ci 2665bf215546Sopenharmony_ci if (conf->num_sgprs && gfx_level < GFX10) { 2666bf215546Sopenharmony_ci unsigned sgprs = align(conf->num_sgprs, gfx_level >= GFX8 ? 16 : 8); 2667bf215546Sopenharmony_ci max_simd_waves = MIN2(max_simd_waves, info->num_physical_sgprs_per_simd / sgprs); 2668bf215546Sopenharmony_ci } 2669bf215546Sopenharmony_ci 2670bf215546Sopenharmony_ci if (conf->num_vgprs) { 2671bf215546Sopenharmony_ci unsigned physical_vgprs = info->num_physical_wave64_vgprs_per_simd * (64 / wave_size); 2672bf215546Sopenharmony_ci unsigned vgprs = align(conf->num_vgprs, wave_size == 32 ? 8 : 4); 2673bf215546Sopenharmony_ci if (gfx_level == GFX10_3) 2674bf215546Sopenharmony_ci vgprs = align(vgprs, wave_size == 32 ? 16 : 8); 2675bf215546Sopenharmony_ci max_simd_waves = MIN2(max_simd_waves, physical_vgprs / vgprs); 2676bf215546Sopenharmony_ci } 2677bf215546Sopenharmony_ci 2678bf215546Sopenharmony_ci unsigned simd_per_workgroup = info->num_simd_per_compute_unit; 2679bf215546Sopenharmony_ci if (gfx_level >= GFX10) 2680bf215546Sopenharmony_ci simd_per_workgroup *= 2; /* like lds_size_per_workgroup, assume WGP on GFX10+ */ 2681bf215546Sopenharmony_ci 2682bf215546Sopenharmony_ci unsigned max_lds_per_simd = info->lds_size_per_workgroup / simd_per_workgroup; 2683bf215546Sopenharmony_ci if (lds_per_wave) 2684bf215546Sopenharmony_ci max_simd_waves = MIN2(max_simd_waves, DIV_ROUND_UP(max_lds_per_simd, lds_per_wave)); 2685bf215546Sopenharmony_ci 2686bf215546Sopenharmony_ci return gfx_level >= GFX10 ? max_simd_waves * (wave_size / 32) : max_simd_waves; 2687bf215546Sopenharmony_ci} 2688bf215546Sopenharmony_ci 2689bf215546Sopenharmony_ciunsigned 2690bf215546Sopenharmony_ciradv_compute_spi_ps_input(const struct radv_pipeline_key *pipeline_key, 2691bf215546Sopenharmony_ci const struct radv_shader_info *info) 2692bf215546Sopenharmony_ci{ 2693bf215546Sopenharmony_ci unsigned spi_ps_input; 2694bf215546Sopenharmony_ci 2695bf215546Sopenharmony_ci spi_ps_input = S_0286CC_PERSP_CENTER_ENA(info->ps.reads_persp_center) | 2696bf215546Sopenharmony_ci S_0286CC_PERSP_CENTROID_ENA(info->ps.reads_persp_centroid) | 2697bf215546Sopenharmony_ci S_0286CC_PERSP_SAMPLE_ENA(info->ps.reads_persp_sample) | 2698bf215546Sopenharmony_ci S_0286CC_LINEAR_CENTER_ENA(info->ps.reads_linear_center) | 2699bf215546Sopenharmony_ci S_0286CC_LINEAR_CENTROID_ENA(info->ps.reads_linear_centroid) | 2700bf215546Sopenharmony_ci S_0286CC_LINEAR_SAMPLE_ENA(info->ps.reads_linear_sample)| 2701bf215546Sopenharmony_ci S_0286CC_PERSP_PULL_MODEL_ENA(info->ps.reads_barycentric_model) | 2702bf215546Sopenharmony_ci S_0286CC_FRONT_FACE_ENA(info->ps.reads_front_face); 2703bf215546Sopenharmony_ci 2704bf215546Sopenharmony_ci if (info->ps.reads_frag_coord_mask || 2705bf215546Sopenharmony_ci info->ps.reads_sample_pos_mask) { 2706bf215546Sopenharmony_ci uint8_t mask = info->ps.reads_frag_coord_mask | info->ps.reads_sample_pos_mask; 2707bf215546Sopenharmony_ci 2708bf215546Sopenharmony_ci for (unsigned i = 0; i < 4; i++) { 2709bf215546Sopenharmony_ci if (mask & (1 << i)) 2710bf215546Sopenharmony_ci spi_ps_input |= S_0286CC_POS_X_FLOAT_ENA(1) << i; 2711bf215546Sopenharmony_ci } 2712bf215546Sopenharmony_ci 2713bf215546Sopenharmony_ci if (pipeline_key->adjust_frag_coord_z && info->ps.reads_frag_coord_mask & (1 << 2)) { 2714bf215546Sopenharmony_ci spi_ps_input |= S_0286CC_ANCILLARY_ENA(1); 2715bf215546Sopenharmony_ci } 2716bf215546Sopenharmony_ci } 2717bf215546Sopenharmony_ci 2718bf215546Sopenharmony_ci if (info->ps.reads_sample_id || info->ps.reads_frag_shading_rate || info->ps.reads_sample_mask_in) { 2719bf215546Sopenharmony_ci spi_ps_input |= S_0286CC_ANCILLARY_ENA(1); 2720bf215546Sopenharmony_ci } 2721bf215546Sopenharmony_ci 2722bf215546Sopenharmony_ci if (info->ps.reads_sample_mask_in) { 2723bf215546Sopenharmony_ci spi_ps_input |= S_0286CC_SAMPLE_COVERAGE_ENA(1); 2724bf215546Sopenharmony_ci } 2725bf215546Sopenharmony_ci 2726bf215546Sopenharmony_ci if (G_0286CC_POS_W_FLOAT_ENA(spi_ps_input)) { 2727bf215546Sopenharmony_ci /* If POS_W_FLOAT (11) is enabled, at least one of PERSP_* must be enabled too */ 2728bf215546Sopenharmony_ci spi_ps_input |= S_0286CC_PERSP_CENTER_ENA(1); 2729bf215546Sopenharmony_ci } 2730bf215546Sopenharmony_ci 2731bf215546Sopenharmony_ci if (!(spi_ps_input & 0x7F)) { 2732bf215546Sopenharmony_ci /* At least one of PERSP_* (0xF) or LINEAR_* (0x70) must be enabled */ 2733bf215546Sopenharmony_ci spi_ps_input |= S_0286CC_PERSP_CENTER_ENA(1); 2734bf215546Sopenharmony_ci } 2735bf215546Sopenharmony_ci 2736bf215546Sopenharmony_ci return spi_ps_input; 2737bf215546Sopenharmony_ci} 2738bf215546Sopenharmony_ci 2739bf215546Sopenharmony_ciVkResult 2740bf215546Sopenharmony_ciradv_dump_shader_stats(struct radv_device *device, struct radv_pipeline *pipeline, 2741bf215546Sopenharmony_ci gl_shader_stage stage, FILE *output) 2742bf215546Sopenharmony_ci{ 2743bf215546Sopenharmony_ci struct radv_shader *shader = pipeline->shaders[stage]; 2744bf215546Sopenharmony_ci VkPipelineExecutablePropertiesKHR *props = NULL; 2745bf215546Sopenharmony_ci uint32_t prop_count = 0; 2746bf215546Sopenharmony_ci VkResult result; 2747bf215546Sopenharmony_ci 2748bf215546Sopenharmony_ci VkPipelineInfoKHR pipeline_info = {0}; 2749bf215546Sopenharmony_ci pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR; 2750bf215546Sopenharmony_ci pipeline_info.pipeline = radv_pipeline_to_handle(pipeline); 2751bf215546Sopenharmony_ci 2752bf215546Sopenharmony_ci result = radv_GetPipelineExecutablePropertiesKHR(radv_device_to_handle(device), &pipeline_info, 2753bf215546Sopenharmony_ci &prop_count, NULL); 2754bf215546Sopenharmony_ci if (result != VK_SUCCESS) 2755bf215546Sopenharmony_ci return result; 2756bf215546Sopenharmony_ci 2757bf215546Sopenharmony_ci props = calloc(prop_count, sizeof(*props)); 2758bf215546Sopenharmony_ci if (!props) 2759bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 2760bf215546Sopenharmony_ci 2761bf215546Sopenharmony_ci result = radv_GetPipelineExecutablePropertiesKHR(radv_device_to_handle(device), &pipeline_info, 2762bf215546Sopenharmony_ci &prop_count, props); 2763bf215546Sopenharmony_ci if (result != VK_SUCCESS) 2764bf215546Sopenharmony_ci goto fail; 2765bf215546Sopenharmony_ci 2766bf215546Sopenharmony_ci for (unsigned exec_idx = 0; exec_idx < prop_count; exec_idx++) { 2767bf215546Sopenharmony_ci if (!(props[exec_idx].stages & mesa_to_vk_shader_stage(stage))) 2768bf215546Sopenharmony_ci continue; 2769bf215546Sopenharmony_ci 2770bf215546Sopenharmony_ci VkPipelineExecutableStatisticKHR *stats = NULL; 2771bf215546Sopenharmony_ci uint32_t stat_count = 0; 2772bf215546Sopenharmony_ci 2773bf215546Sopenharmony_ci VkPipelineExecutableInfoKHR exec_info = {0}; 2774bf215546Sopenharmony_ci exec_info.pipeline = radv_pipeline_to_handle(pipeline); 2775bf215546Sopenharmony_ci exec_info.executableIndex = exec_idx; 2776bf215546Sopenharmony_ci 2777bf215546Sopenharmony_ci result = radv_GetPipelineExecutableStatisticsKHR(radv_device_to_handle(device), &exec_info, 2778bf215546Sopenharmony_ci &stat_count, NULL); 2779bf215546Sopenharmony_ci if (result != VK_SUCCESS) 2780bf215546Sopenharmony_ci goto fail; 2781bf215546Sopenharmony_ci 2782bf215546Sopenharmony_ci stats = calloc(stat_count, sizeof(*stats)); 2783bf215546Sopenharmony_ci if (!stats) { 2784bf215546Sopenharmony_ci result = VK_ERROR_OUT_OF_HOST_MEMORY; 2785bf215546Sopenharmony_ci goto fail; 2786bf215546Sopenharmony_ci } 2787bf215546Sopenharmony_ci 2788bf215546Sopenharmony_ci result = radv_GetPipelineExecutableStatisticsKHR(radv_device_to_handle(device), &exec_info, 2789bf215546Sopenharmony_ci &stat_count, stats); 2790bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 2791bf215546Sopenharmony_ci free(stats); 2792bf215546Sopenharmony_ci goto fail; 2793bf215546Sopenharmony_ci } 2794bf215546Sopenharmony_ci 2795bf215546Sopenharmony_ci fprintf(output, "\n%s:\n", radv_get_shader_name(&shader->info, stage)); 2796bf215546Sopenharmony_ci fprintf(output, "*** SHADER STATS ***\n"); 2797bf215546Sopenharmony_ci 2798bf215546Sopenharmony_ci for (unsigned i = 0; i < stat_count; i++) { 2799bf215546Sopenharmony_ci fprintf(output, "%s: ", stats[i].name); 2800bf215546Sopenharmony_ci switch (stats[i].format) { 2801bf215546Sopenharmony_ci case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR: 2802bf215546Sopenharmony_ci fprintf(output, "%s", stats[i].value.b32 == VK_TRUE ? "true" : "false"); 2803bf215546Sopenharmony_ci break; 2804bf215546Sopenharmony_ci case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR: 2805bf215546Sopenharmony_ci fprintf(output, "%" PRIi64, stats[i].value.i64); 2806bf215546Sopenharmony_ci break; 2807bf215546Sopenharmony_ci case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR: 2808bf215546Sopenharmony_ci fprintf(output, "%" PRIu64, stats[i].value.u64); 2809bf215546Sopenharmony_ci break; 2810bf215546Sopenharmony_ci case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR: 2811bf215546Sopenharmony_ci fprintf(output, "%f", stats[i].value.f64); 2812bf215546Sopenharmony_ci break; 2813bf215546Sopenharmony_ci default: 2814bf215546Sopenharmony_ci unreachable("Invalid pipeline statistic format"); 2815bf215546Sopenharmony_ci } 2816bf215546Sopenharmony_ci fprintf(output, "\n"); 2817bf215546Sopenharmony_ci } 2818bf215546Sopenharmony_ci 2819bf215546Sopenharmony_ci fprintf(output, "********************\n\n\n"); 2820bf215546Sopenharmony_ci 2821bf215546Sopenharmony_ci free(stats); 2822bf215546Sopenharmony_ci } 2823bf215546Sopenharmony_ci 2824bf215546Sopenharmony_cifail: 2825bf215546Sopenharmony_ci free(props); 2826bf215546Sopenharmony_ci return result; 2827bf215546Sopenharmony_ci} 2828