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