xref: /aosp_15_r20/external/mesa3d/src/amd/vulkan/radv_shader.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2016 Red Hat.
3*61046927SAndroid Build Coastguard Worker  * Copyright © 2016 Bas Nieuwenhuizen
4*61046927SAndroid Build Coastguard Worker  *
5*61046927SAndroid Build Coastguard Worker  * based in part on anv driver which is:
6*61046927SAndroid Build Coastguard Worker  * Copyright © 2015 Intel Corporation
7*61046927SAndroid Build Coastguard Worker  *
8*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
9*61046927SAndroid Build Coastguard Worker  */
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker #include "radv_shader.h"
12*61046927SAndroid Build Coastguard Worker #include "meta/radv_meta.h"
13*61046927SAndroid Build Coastguard Worker #include "nir/nir.h"
14*61046927SAndroid Build Coastguard Worker #include "nir/nir_builder.h"
15*61046927SAndroid Build Coastguard Worker #include "nir/nir_xfb_info.h"
16*61046927SAndroid Build Coastguard Worker #include "nir/radv_nir.h"
17*61046927SAndroid Build Coastguard Worker #include "spirv/nir_spirv.h"
18*61046927SAndroid Build Coastguard Worker #include "util/memstream.h"
19*61046927SAndroid Build Coastguard Worker #include "util/mesa-sha1.h"
20*61046927SAndroid Build Coastguard Worker #include "util/streaming-load-memcpy.h"
21*61046927SAndroid Build Coastguard Worker #include "util/u_atomic.h"
22*61046927SAndroid Build Coastguard Worker #include "radv_cs.h"
23*61046927SAndroid Build Coastguard Worker #include "radv_debug.h"
24*61046927SAndroid Build Coastguard Worker #include "radv_entrypoints.h"
25*61046927SAndroid Build Coastguard Worker #include "radv_nir_to_llvm.h"
26*61046927SAndroid Build Coastguard Worker #include "radv_printf.h"
27*61046927SAndroid Build Coastguard Worker #include "radv_sdma.h"
28*61046927SAndroid Build Coastguard Worker #include "radv_shader_args.h"
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
31*61046927SAndroid Build Coastguard Worker #include "ac_binary.h"
32*61046927SAndroid Build Coastguard Worker #include "ac_nir.h"
33*61046927SAndroid Build Coastguard Worker #if defined(USE_LIBELF)
34*61046927SAndroid Build Coastguard Worker #include "ac_rtld.h"
35*61046927SAndroid Build Coastguard Worker #endif
36*61046927SAndroid Build Coastguard Worker #include "aco_interface.h"
37*61046927SAndroid Build Coastguard Worker #include "sid.h"
38*61046927SAndroid Build Coastguard Worker #include "vk_debug_report.h"
39*61046927SAndroid Build Coastguard Worker #include "vk_format.h"
40*61046927SAndroid Build Coastguard Worker #include "vk_nir.h"
41*61046927SAndroid Build Coastguard Worker #include "vk_semaphore.h"
42*61046927SAndroid Build Coastguard Worker #include "vk_sync.h"
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker #include "aco_shader_info.h"
45*61046927SAndroid Build Coastguard Worker #include "radv_aco_shader_info.h"
46*61046927SAndroid Build Coastguard Worker #if AMD_LLVM_AVAILABLE
47*61046927SAndroid Build Coastguard Worker #include "ac_llvm_util.h"
48*61046927SAndroid Build Coastguard Worker #endif
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker static void
get_nir_options_for_stage(struct radv_physical_device * pdev,gl_shader_stage stage)51*61046927SAndroid Build Coastguard Worker get_nir_options_for_stage(struct radv_physical_device *pdev, gl_shader_stage stage)
52*61046927SAndroid Build Coastguard Worker {
53*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
54*61046927SAndroid Build Coastguard Worker    nir_shader_compiler_options *options = &pdev->nir_options[stage];
55*61046927SAndroid Build Coastguard Worker    bool split_fma =
56*61046927SAndroid Build Coastguard Worker       (stage <= MESA_SHADER_GEOMETRY || stage == MESA_SHADER_MESH) && instance->debug_flags & RADV_DEBUG_SPLIT_FMA;
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker    ac_set_nir_options(&pdev->info, pdev->use_llvm, options);
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker    options->lower_ffma16 = split_fma || pdev->info.gfx_level < GFX9;
61*61046927SAndroid Build Coastguard Worker    options->lower_ffma32 = split_fma || pdev->info.gfx_level < GFX10_3;
62*61046927SAndroid Build Coastguard Worker    options->lower_ffma64 = split_fma;
63*61046927SAndroid Build Coastguard Worker    options->max_unroll_iterations = 32;
64*61046927SAndroid Build Coastguard Worker    options->max_unroll_iterations_aggressive = 128;
65*61046927SAndroid Build Coastguard Worker    options->lower_doubles_options = nir_lower_drcp | nir_lower_dsqrt | nir_lower_drsq | nir_lower_ddiv;
66*61046927SAndroid Build Coastguard Worker    options->io_options |= nir_io_mediump_is_32bit;
67*61046927SAndroid Build Coastguard Worker    options->varying_estimate_instr_cost = ac_nir_varying_estimate_instr_cost;
68*61046927SAndroid Build Coastguard Worker    options->varying_expression_max_cost = ac_nir_varying_expression_max_cost;
69*61046927SAndroid Build Coastguard Worker }
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker void
radv_get_nir_options(struct radv_physical_device * pdev)72*61046927SAndroid Build Coastguard Worker radv_get_nir_options(struct radv_physical_device *pdev)
73*61046927SAndroid Build Coastguard Worker {
74*61046927SAndroid Build Coastguard Worker    for (gl_shader_stage stage = MESA_SHADER_VERTEX; stage < MESA_VULKAN_SHADER_STAGES; stage++)
75*61046927SAndroid Build Coastguard Worker       get_nir_options_for_stage(pdev, stage);
76*61046927SAndroid Build Coastguard Worker }
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker static uint8_t
vectorize_vec2_16bit(const nir_instr * instr,const void * _)79*61046927SAndroid Build Coastguard Worker vectorize_vec2_16bit(const nir_instr *instr, const void *_)
80*61046927SAndroid Build Coastguard Worker {
81*61046927SAndroid Build Coastguard Worker    if (instr->type != nir_instr_type_alu)
82*61046927SAndroid Build Coastguard Worker       return 0;
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    const nir_alu_instr *alu = nir_instr_as_alu(instr);
85*61046927SAndroid Build Coastguard Worker    const unsigned bit_size = alu->def.bit_size;
86*61046927SAndroid Build Coastguard Worker    if (bit_size == 16)
87*61046927SAndroid Build Coastguard Worker       return 2;
88*61046927SAndroid Build Coastguard Worker    else
89*61046927SAndroid Build Coastguard Worker       return 1;
90*61046927SAndroid Build Coastguard Worker }
91*61046927SAndroid Build Coastguard Worker 
92*61046927SAndroid Build Coastguard Worker static bool
is_meta_shader(nir_shader * nir)93*61046927SAndroid Build Coastguard Worker is_meta_shader(nir_shader *nir)
94*61046927SAndroid Build Coastguard Worker {
95*61046927SAndroid Build Coastguard Worker    return nir && nir->info.internal;
96*61046927SAndroid Build Coastguard Worker }
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker bool
radv_can_dump_shader(struct radv_device * device,nir_shader * nir,bool meta_shader)99*61046927SAndroid Build Coastguard Worker radv_can_dump_shader(struct radv_device *device, nir_shader *nir, bool meta_shader)
100*61046927SAndroid Build Coastguard Worker {
101*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
102*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker    if (!(instance->debug_flags & RADV_DEBUG_DUMP_SHADERS))
105*61046927SAndroid Build Coastguard Worker       return false;
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker    if ((is_meta_shader(nir) || meta_shader) && !(instance->debug_flags & RADV_DEBUG_DUMP_META_SHADERS))
108*61046927SAndroid Build Coastguard Worker       return false;
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker    return true;
111*61046927SAndroid Build Coastguard Worker }
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker bool
radv_can_dump_shader_stats(struct radv_device * device,nir_shader * nir)114*61046927SAndroid Build Coastguard Worker radv_can_dump_shader_stats(struct radv_device *device, nir_shader *nir)
115*61046927SAndroid Build Coastguard Worker {
116*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
117*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker    /* Only dump non-meta shader stats. */
120*61046927SAndroid Build Coastguard Worker    return instance->debug_flags & RADV_DEBUG_DUMP_SHADER_STATS && !is_meta_shader(nir);
121*61046927SAndroid Build Coastguard Worker }
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker void
radv_optimize_nir(struct nir_shader * shader,bool optimize_conservatively)124*61046927SAndroid Build Coastguard Worker radv_optimize_nir(struct nir_shader *shader, bool optimize_conservatively)
125*61046927SAndroid Build Coastguard Worker {
126*61046927SAndroid Build Coastguard Worker    bool progress;
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker    struct set *skip = _mesa_pointer_set_create(NULL);
129*61046927SAndroid Build Coastguard Worker    do {
130*61046927SAndroid Build Coastguard Worker       progress = false;
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_split_array_vars, nir_var_function_temp);
133*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_shrink_vec_array_vars, nir_var_function_temp);
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker       if (!shader->info.var_copies_lowered) {
136*61046927SAndroid Build Coastguard Worker          /* Only run this pass if nir_lower_var_copies was not called
137*61046927SAndroid Build Coastguard Worker           * yet. That would lower away any copy_deref instructions and we
138*61046927SAndroid Build Coastguard Worker           * don't want to introduce any more.
139*61046927SAndroid Build Coastguard Worker           */
140*61046927SAndroid Build Coastguard Worker          NIR_LOOP_PASS(progress, skip, shader, nir_opt_find_array_copies);
141*61046927SAndroid Build Coastguard Worker       }
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_opt_copy_prop_vars);
144*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_opt_dead_write_vars);
145*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(_, skip, shader, nir_lower_vars_to_ssa);
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(_, skip, shader, nir_lower_alu_width, vectorize_vec2_16bit, NULL);
148*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(_, skip, shader, nir_lower_phis_to_scalar, true);
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_copy_prop);
151*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_opt_remove_phis);
152*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_opt_dce);
153*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_opt_dead_cf);
154*61046927SAndroid Build Coastguard Worker       bool opt_loop_progress = false;
155*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS_NOT_IDEMPOTENT(opt_loop_progress, skip, shader, nir_opt_loop);
156*61046927SAndroid Build Coastguard Worker       if (opt_loop_progress) {
157*61046927SAndroid Build Coastguard Worker          progress = true;
158*61046927SAndroid Build Coastguard Worker          NIR_LOOP_PASS(progress, skip, shader, nir_copy_prop);
159*61046927SAndroid Build Coastguard Worker          NIR_LOOP_PASS(progress, skip, shader, nir_opt_remove_phis);
160*61046927SAndroid Build Coastguard Worker          NIR_LOOP_PASS(progress, skip, shader, nir_opt_dce);
161*61046927SAndroid Build Coastguard Worker       }
162*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS_NOT_IDEMPOTENT(progress, skip, shader, nir_opt_if, nir_opt_if_optimize_phi_true_false);
163*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_opt_cse);
164*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_opt_peephole_select, 8, true, true);
165*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_opt_constant_folding);
166*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_opt_intrinsics);
167*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS_NOT_IDEMPOTENT(progress, skip, shader, nir_opt_algebraic);
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(progress, skip, shader, nir_opt_undef);
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker       if (shader->options->max_unroll_iterations) {
172*61046927SAndroid Build Coastguard Worker          NIR_LOOP_PASS_NOT_IDEMPOTENT(progress, skip, shader, nir_opt_loop_unroll);
173*61046927SAndroid Build Coastguard Worker       }
174*61046927SAndroid Build Coastguard Worker    } while (progress && !optimize_conservatively);
175*61046927SAndroid Build Coastguard Worker    _mesa_set_destroy(skip, NULL);
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker    NIR_PASS(progress, shader, nir_opt_shrink_vectors, true);
178*61046927SAndroid Build Coastguard Worker    NIR_PASS(progress, shader, nir_remove_dead_variables,
179*61046927SAndroid Build Coastguard Worker             nir_var_function_temp | nir_var_shader_in | nir_var_shader_out | nir_var_mem_shared, NULL);
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker    if (shader->info.stage == MESA_SHADER_FRAGMENT && shader->info.fs.uses_discard) {
182*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, shader, nir_opt_conditional_discard);
183*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, shader, nir_opt_move_discards_to_top);
184*61046927SAndroid Build Coastguard Worker    }
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker    NIR_PASS(progress, shader, nir_opt_move, nir_move_load_ubo);
187*61046927SAndroid Build Coastguard Worker }
188*61046927SAndroid Build Coastguard Worker 
189*61046927SAndroid Build Coastguard Worker void
radv_optimize_nir_algebraic(nir_shader * nir,bool opt_offsets,bool opt_mqsad)190*61046927SAndroid Build Coastguard Worker radv_optimize_nir_algebraic(nir_shader *nir, bool opt_offsets, bool opt_mqsad)
191*61046927SAndroid Build Coastguard Worker {
192*61046927SAndroid Build Coastguard Worker    bool more_algebraic = true;
193*61046927SAndroid Build Coastguard Worker    while (more_algebraic) {
194*61046927SAndroid Build Coastguard Worker       more_algebraic = false;
195*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_copy_prop);
196*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_dce);
197*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_constant_folding);
198*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_cse);
199*61046927SAndroid Build Coastguard Worker       NIR_PASS(more_algebraic, nir, nir_opt_algebraic);
200*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_generate_bfi);
201*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_dead_cf);
202*61046927SAndroid Build Coastguard Worker    }
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker    if (opt_offsets) {
205*61046927SAndroid Build Coastguard Worker       static const nir_opt_offsets_options offset_options = {
206*61046927SAndroid Build Coastguard Worker          .uniform_max = 0,
207*61046927SAndroid Build Coastguard Worker          .buffer_max = ~0,
208*61046927SAndroid Build Coastguard Worker          .shared_max = ~0,
209*61046927SAndroid Build Coastguard Worker       };
210*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_offsets, &offset_options);
211*61046927SAndroid Build Coastguard Worker    }
212*61046927SAndroid Build Coastguard Worker    if (opt_mqsad)
213*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_mqsad);
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker    /* Do late algebraic optimization to turn add(a,
216*61046927SAndroid Build Coastguard Worker     * neg(b)) back into subs, then the mandatory cleanup
217*61046927SAndroid Build Coastguard Worker     * after algebraic.  Note that it may produce fnegs,
218*61046927SAndroid Build Coastguard Worker     * and if so then we need to keep running to squash
219*61046927SAndroid Build Coastguard Worker     * fneg(fneg(a)).
220*61046927SAndroid Build Coastguard Worker     */
221*61046927SAndroid Build Coastguard Worker    bool more_late_algebraic = true;
222*61046927SAndroid Build Coastguard Worker    struct set *skip = _mesa_pointer_set_create(NULL);
223*61046927SAndroid Build Coastguard Worker    while (more_late_algebraic) {
224*61046927SAndroid Build Coastguard Worker       more_late_algebraic = false;
225*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS_NOT_IDEMPOTENT(more_late_algebraic, skip, nir, nir_opt_algebraic_late);
226*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(_, skip, nir, nir_opt_constant_folding);
227*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(_, skip, nir, nir_copy_prop);
228*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(_, skip, nir, nir_opt_dce);
229*61046927SAndroid Build Coastguard Worker       NIR_LOOP_PASS(_, skip, nir, nir_opt_cse);
230*61046927SAndroid Build Coastguard Worker    }
231*61046927SAndroid Build Coastguard Worker    _mesa_set_destroy(skip, NULL);
232*61046927SAndroid Build Coastguard Worker }
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker static void
shared_var_info(const struct glsl_type * type,unsigned * size,unsigned * align)235*61046927SAndroid Build Coastguard Worker shared_var_info(const struct glsl_type *type, unsigned *size, unsigned *align)
236*61046927SAndroid Build Coastguard Worker {
237*61046927SAndroid Build Coastguard Worker    assert(glsl_type_is_vector_or_scalar(type));
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    uint32_t comp_size = glsl_type_is_boolean(type) ? 4 : glsl_get_bit_size(type) / 8;
240*61046927SAndroid Build Coastguard Worker    unsigned length = glsl_get_vector_elements(type);
241*61046927SAndroid Build Coastguard Worker    *size = comp_size * length, *align = comp_size;
242*61046927SAndroid Build Coastguard Worker }
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker struct radv_shader_debug_data {
245*61046927SAndroid Build Coastguard Worker    struct radv_device *device;
246*61046927SAndroid Build Coastguard Worker    const struct vk_object_base *object;
247*61046927SAndroid Build Coastguard Worker };
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker static void
radv_spirv_nir_debug(void * private_data,enum nir_spirv_debug_level level,size_t spirv_offset,const char * message)250*61046927SAndroid Build Coastguard Worker radv_spirv_nir_debug(void *private_data, enum nir_spirv_debug_level level, size_t spirv_offset, const char *message)
251*61046927SAndroid Build Coastguard Worker {
252*61046927SAndroid Build Coastguard Worker    struct radv_shader_debug_data *debug_data = private_data;
253*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(debug_data->device);
254*61046927SAndroid Build Coastguard Worker    struct radv_instance *instance = radv_physical_device_instance(pdev);
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker    static const VkDebugReportFlagsEXT vk_flags[] = {
257*61046927SAndroid Build Coastguard Worker       [NIR_SPIRV_DEBUG_LEVEL_INFO] = VK_DEBUG_REPORT_INFORMATION_BIT_EXT,
258*61046927SAndroid Build Coastguard Worker       [NIR_SPIRV_DEBUG_LEVEL_WARNING] = VK_DEBUG_REPORT_WARNING_BIT_EXT,
259*61046927SAndroid Build Coastguard Worker       [NIR_SPIRV_DEBUG_LEVEL_ERROR] = VK_DEBUG_REPORT_ERROR_BIT_EXT,
260*61046927SAndroid Build Coastguard Worker    };
261*61046927SAndroid Build Coastguard Worker    char buffer[256];
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker    snprintf(buffer, sizeof(buffer), "SPIR-V offset %lu: %s", (unsigned long)spirv_offset, message);
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker    vk_debug_report(&instance->vk, vk_flags[level], debug_data->object, 0, 0, "radv", buffer);
266*61046927SAndroid Build Coastguard Worker }
267*61046927SAndroid Build Coastguard Worker 
268*61046927SAndroid Build Coastguard Worker static void
radv_compiler_debug(void * private_data,enum aco_compiler_debug_level level,const char * message)269*61046927SAndroid Build Coastguard Worker radv_compiler_debug(void *private_data, enum aco_compiler_debug_level level, const char *message)
270*61046927SAndroid Build Coastguard Worker {
271*61046927SAndroid Build Coastguard Worker    struct radv_shader_debug_data *debug_data = private_data;
272*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(debug_data->device);
273*61046927SAndroid Build Coastguard Worker    struct radv_instance *instance = radv_physical_device_instance(pdev);
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker    static const VkDebugReportFlagsEXT vk_flags[] = {
276*61046927SAndroid Build Coastguard Worker       [ACO_COMPILER_DEBUG_LEVEL_ERROR] = VK_DEBUG_REPORT_ERROR_BIT_EXT,
277*61046927SAndroid Build Coastguard Worker    };
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker    /* VK_DEBUG_REPORT_DEBUG_BIT_EXT specifies diagnostic information
280*61046927SAndroid Build Coastguard Worker     * from the implementation and layers.
281*61046927SAndroid Build Coastguard Worker     */
282*61046927SAndroid Build Coastguard Worker    vk_debug_report(&instance->vk, vk_flags[level] | VK_DEBUG_REPORT_DEBUG_BIT_EXT, NULL, 0, 0, "radv", message);
283*61046927SAndroid Build Coastguard Worker }
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker /* If the shader doesn't have an index=1 output, then assume that it meant for a location=1 to be used. This works on
286*61046927SAndroid Build Coastguard Worker  * some older hardware because the MRT1 target is used for both location=1 and index=1, but GFX11 works differently.
287*61046927SAndroid Build Coastguard Worker  */
288*61046927SAndroid Build Coastguard Worker static void
fix_dual_src_mrt1_export(nir_shader * nir)289*61046927SAndroid Build Coastguard Worker fix_dual_src_mrt1_export(nir_shader *nir)
290*61046927SAndroid Build Coastguard Worker {
291*61046927SAndroid Build Coastguard Worker    nir_foreach_shader_out_variable (var, nir) {
292*61046927SAndroid Build Coastguard Worker       if (var->data.location == FRAG_RESULT_DATA0 && var->data.index == 1)
293*61046927SAndroid Build Coastguard Worker          return;
294*61046927SAndroid Build Coastguard Worker    }
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker    nir_variable *loc1_var = nir_find_variable_with_location(nir, nir_var_shader_out, FRAG_RESULT_DATA1);
297*61046927SAndroid Build Coastguard Worker    if (loc1_var) {
298*61046927SAndroid Build Coastguard Worker       loc1_var->data.location = FRAG_RESULT_DATA0;
299*61046927SAndroid Build Coastguard Worker       loc1_var->data.index = 1;
300*61046927SAndroid Build Coastguard Worker    }
301*61046927SAndroid Build Coastguard Worker }
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker nir_shader *
radv_shader_spirv_to_nir(struct radv_device * device,const struct radv_shader_stage * stage,const struct radv_spirv_to_nir_options * options,bool is_internal)304*61046927SAndroid Build Coastguard Worker radv_shader_spirv_to_nir(struct radv_device *device, const struct radv_shader_stage *stage,
305*61046927SAndroid Build Coastguard Worker                          const struct radv_spirv_to_nir_options *options, bool is_internal)
306*61046927SAndroid Build Coastguard Worker {
307*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
308*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
309*61046927SAndroid Build Coastguard Worker    unsigned subgroup_size = 64, ballot_bit_size = 64;
310*61046927SAndroid Build Coastguard Worker    const unsigned required_subgroup_size = stage->key.subgroup_required_size * 32;
311*61046927SAndroid Build Coastguard Worker    if (required_subgroup_size) {
312*61046927SAndroid Build Coastguard Worker       /* Only compute/mesh/task shaders currently support requiring a
313*61046927SAndroid Build Coastguard Worker        * specific subgroup size.
314*61046927SAndroid Build Coastguard Worker        */
315*61046927SAndroid Build Coastguard Worker       assert(stage->stage >= MESA_SHADER_COMPUTE);
316*61046927SAndroid Build Coastguard Worker       subgroup_size = required_subgroup_size;
317*61046927SAndroid Build Coastguard Worker       ballot_bit_size = required_subgroup_size;
318*61046927SAndroid Build Coastguard Worker    }
319*61046927SAndroid Build Coastguard Worker 
320*61046927SAndroid Build Coastguard Worker    nir_shader *nir;
321*61046927SAndroid Build Coastguard Worker 
322*61046927SAndroid Build Coastguard Worker    if (stage->internal_nir) {
323*61046927SAndroid Build Coastguard Worker       /* Some things such as our meta clear/blit code will give us a NIR
324*61046927SAndroid Build Coastguard Worker        * shader directly.  In that case, we just ignore the SPIR-V entirely
325*61046927SAndroid Build Coastguard Worker        * and just use the NIR shader.  We don't want to alter meta and RT
326*61046927SAndroid Build Coastguard Worker        * shaders IR directly, so clone it first. */
327*61046927SAndroid Build Coastguard Worker       nir = nir_shader_clone(NULL, stage->internal_nir);
328*61046927SAndroid Build Coastguard Worker       nir_validate_shader(nir, "in internal shader");
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker       assert(exec_list_length(&nir->functions) == 1);
331*61046927SAndroid Build Coastguard Worker    } else {
332*61046927SAndroid Build Coastguard Worker       uint32_t *spirv = (uint32_t *)stage->spirv.data;
333*61046927SAndroid Build Coastguard Worker       assert(stage->spirv.size % 4 == 0);
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker       bool dump_meta = instance->debug_flags & RADV_DEBUG_DUMP_META_SHADERS;
336*61046927SAndroid Build Coastguard Worker       if ((instance->debug_flags & RADV_DEBUG_DUMP_SPIRV) && (!is_internal || dump_meta))
337*61046927SAndroid Build Coastguard Worker          spirv_print_asm(stderr, (const uint32_t *)stage->spirv.data, stage->spirv.size / 4);
338*61046927SAndroid Build Coastguard Worker 
339*61046927SAndroid Build Coastguard Worker       uint32_t num_spec_entries = 0;
340*61046927SAndroid Build Coastguard Worker       struct nir_spirv_specialization *spec_entries = vk_spec_info_to_nir_spirv(stage->spec_info, &num_spec_entries);
341*61046927SAndroid Build Coastguard Worker       struct radv_shader_debug_data spirv_debug_data = {
342*61046927SAndroid Build Coastguard Worker          .device = device,
343*61046927SAndroid Build Coastguard Worker          .object = stage->spirv.object,
344*61046927SAndroid Build Coastguard Worker       };
345*61046927SAndroid Build Coastguard Worker       const struct spirv_capabilities spirv_caps =
346*61046927SAndroid Build Coastguard Worker          vk_physical_device_get_spirv_capabilities(device->vk.physical);
347*61046927SAndroid Build Coastguard Worker       const struct spirv_to_nir_options spirv_options = {
348*61046927SAndroid Build Coastguard Worker          .amd_gcn_shader = true,
349*61046927SAndroid Build Coastguard Worker          .amd_shader_ballot = true,
350*61046927SAndroid Build Coastguard Worker          .amd_shader_explicit_vertex_parameter = true,
351*61046927SAndroid Build Coastguard Worker          .amd_trinary_minmax = true,
352*61046927SAndroid Build Coastguard Worker          .capabilities = &spirv_caps,
353*61046927SAndroid Build Coastguard Worker          .ubo_addr_format = nir_address_format_vec2_index_32bit_offset,
354*61046927SAndroid Build Coastguard Worker          .ssbo_addr_format = nir_address_format_vec2_index_32bit_offset,
355*61046927SAndroid Build Coastguard Worker          .phys_ssbo_addr_format = nir_address_format_64bit_global,
356*61046927SAndroid Build Coastguard Worker          .push_const_addr_format = nir_address_format_logical,
357*61046927SAndroid Build Coastguard Worker          .shared_addr_format = nir_address_format_32bit_offset,
358*61046927SAndroid Build Coastguard Worker          .constant_addr_format = nir_address_format_64bit_global,
359*61046927SAndroid Build Coastguard Worker          .debug =
360*61046927SAndroid Build Coastguard Worker             {
361*61046927SAndroid Build Coastguard Worker                .func = radv_spirv_nir_debug,
362*61046927SAndroid Build Coastguard Worker                .private_data = &spirv_debug_data,
363*61046927SAndroid Build Coastguard Worker             },
364*61046927SAndroid Build Coastguard Worker          .force_tex_non_uniform = pdev->cache_key.tex_non_uniform,
365*61046927SAndroid Build Coastguard Worker          .force_ssbo_non_uniform = pdev->cache_key.ssbo_non_uniform,
366*61046927SAndroid Build Coastguard Worker       };
367*61046927SAndroid Build Coastguard Worker       nir = spirv_to_nir(spirv, stage->spirv.size / 4, spec_entries, num_spec_entries, stage->stage, stage->entrypoint,
368*61046927SAndroid Build Coastguard Worker                          &spirv_options, &pdev->nir_options[stage->stage]);
369*61046927SAndroid Build Coastguard Worker       nir->info.internal |= is_internal;
370*61046927SAndroid Build Coastguard Worker       assert(nir->info.stage == stage->stage);
371*61046927SAndroid Build Coastguard Worker       nir_validate_shader(nir, "after spirv_to_nir");
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker       free(spec_entries);
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker       radv_device_associate_nir(device, nir);
376*61046927SAndroid Build Coastguard Worker 
377*61046927SAndroid Build Coastguard Worker       /* TODO: This can be removed once GCM (which is more general) is used. */
378*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_reuse_constants);
379*61046927SAndroid Build Coastguard Worker 
380*61046927SAndroid Build Coastguard Worker       const struct nir_lower_sysvals_to_varyings_options sysvals_to_varyings = {
381*61046927SAndroid Build Coastguard Worker          .point_coord = true,
382*61046927SAndroid Build Coastguard Worker       };
383*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, nir_lower_sysvals_to_varyings, &sysvals_to_varyings);
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker       /* We have to lower away local constant initializers right before we
386*61046927SAndroid Build Coastguard Worker        * inline functions.  That way they get properly initialized at the top
387*61046927SAndroid Build Coastguard Worker        * of the function and not at the top of its caller.
388*61046927SAndroid Build Coastguard Worker        */
389*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_variable_initializers, nir_var_function_temp);
390*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_returns);
391*61046927SAndroid Build Coastguard Worker       bool progress = false;
392*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_inline_functions);
393*61046927SAndroid Build Coastguard Worker       if (progress) {
394*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, nir_opt_copy_prop_vars);
395*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, nir_copy_prop);
396*61046927SAndroid Build Coastguard Worker       }
397*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_deref);
398*61046927SAndroid Build Coastguard Worker 
399*61046927SAndroid Build Coastguard Worker       /* Pick off the single entrypoint that we want */
400*61046927SAndroid Build Coastguard Worker       nir_remove_non_entrypoints(nir);
401*61046927SAndroid Build Coastguard Worker 
402*61046927SAndroid Build Coastguard Worker       /* Make sure we lower constant initializers on output variables so that
403*61046927SAndroid Build Coastguard Worker        * nir_remove_dead_variables below sees the corresponding stores
404*61046927SAndroid Build Coastguard Worker        */
405*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_variable_initializers, nir_var_shader_out);
406*61046927SAndroid Build Coastguard Worker 
407*61046927SAndroid Build Coastguard Worker       /* Now that we've deleted all but the main function, we can go ahead and
408*61046927SAndroid Build Coastguard Worker        * lower the rest of the constant initializers.
409*61046927SAndroid Build Coastguard Worker        */
410*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_variable_initializers, ~0);
411*61046927SAndroid Build Coastguard Worker 
412*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, radv_nir_lower_cooperative_matrix, subgroup_size);
413*61046927SAndroid Build Coastguard Worker 
414*61046927SAndroid Build Coastguard Worker       /* Split member structs.  We do this before lower_io_to_temporaries so that
415*61046927SAndroid Build Coastguard Worker        * it doesn't lower system values to temporaries by accident.
416*61046927SAndroid Build Coastguard Worker        */
417*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_split_var_copies);
418*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_split_per_member_structs);
419*61046927SAndroid Build Coastguard Worker 
420*61046927SAndroid Build Coastguard Worker       if (nir->info.stage == MESA_SHADER_FRAGMENT)
421*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, nir_lower_io_to_vector, nir_var_shader_out);
422*61046927SAndroid Build Coastguard Worker       if (nir->info.stage == MESA_SHADER_FRAGMENT)
423*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, nir_lower_input_attachments,
424*61046927SAndroid Build Coastguard Worker                   &(nir_input_attachment_options){
425*61046927SAndroid Build Coastguard Worker                      .use_fragcoord_sysval = true,
426*61046927SAndroid Build Coastguard Worker                      .use_layer_id_sysval = false,
427*61046927SAndroid Build Coastguard Worker                   });
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker       nir_remove_dead_variables_options dead_vars_opts = {
430*61046927SAndroid Build Coastguard Worker          .can_remove_var = nir_vk_is_not_xfb_output,
431*61046927SAndroid Build Coastguard Worker       };
432*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_remove_dead_variables,
433*61046927SAndroid Build Coastguard Worker                nir_var_shader_in | nir_var_shader_out | nir_var_system_value | nir_var_mem_shared, &dead_vars_opts);
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker       if (nir->info.stage == MESA_SHADER_FRAGMENT && options->fix_dual_src_mrt1_export)
436*61046927SAndroid Build Coastguard Worker          fix_dual_src_mrt1_export(nir);
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker       /* Variables can make nir_propagate_invariant more conservative
439*61046927SAndroid Build Coastguard Worker        * than it needs to be.
440*61046927SAndroid Build Coastguard Worker        */
441*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_global_vars_to_local);
442*61046927SAndroid Build Coastguard Worker 
443*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_vars_to_ssa);
444*61046927SAndroid Build Coastguard Worker 
445*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_propagate_invariant, pdev->cache_key.invariant_geom);
446*61046927SAndroid Build Coastguard Worker 
447*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_clip_cull_distance_arrays);
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker       if (nir->info.stage == MESA_SHADER_VERTEX || nir->info.stage == MESA_SHADER_TESS_EVAL ||
450*61046927SAndroid Build Coastguard Worker           nir->info.stage == MESA_SHADER_GEOMETRY)
451*61046927SAndroid Build Coastguard Worker          NIR_PASS_V(nir, nir_shader_gather_xfb_info);
452*61046927SAndroid Build Coastguard Worker 
453*61046927SAndroid Build Coastguard Worker       nir_lower_doubles_options lower_doubles = nir->options->lower_doubles_options;
454*61046927SAndroid Build Coastguard Worker 
455*61046927SAndroid Build Coastguard Worker       if (pdev->info.gfx_level == GFX6) {
456*61046927SAndroid Build Coastguard Worker          /* GFX6 doesn't support v_floor_f64 and the precision
457*61046927SAndroid Build Coastguard Worker           * of v_fract_f64 which is used to implement 64-bit
458*61046927SAndroid Build Coastguard Worker           * floor is less than what Vulkan requires.
459*61046927SAndroid Build Coastguard Worker           */
460*61046927SAndroid Build Coastguard Worker          lower_doubles |= nir_lower_dfloor;
461*61046927SAndroid Build Coastguard Worker       }
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_doubles, NULL, lower_doubles);
464*61046927SAndroid Build Coastguard Worker 
465*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, ac_nir_lower_sin_cos);
466*61046927SAndroid Build Coastguard Worker    }
467*61046927SAndroid Build Coastguard Worker 
468*61046927SAndroid Build Coastguard Worker    if (options && options->lower_view_index_to_device_index)
469*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_view_index_to_device_index);
470*61046927SAndroid Build Coastguard Worker 
471*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_system_values);
472*61046927SAndroid Build Coastguard Worker    nir_lower_compute_system_values_options csv_options = {
473*61046927SAndroid Build Coastguard Worker       /* Mesh shaders run as NGG which can implement local_invocation_index from
474*61046927SAndroid Build Coastguard Worker        * the wave ID in merged_wave_info, but they don't have local_invocation_ids on GFX10.3.
475*61046927SAndroid Build Coastguard Worker        */
476*61046927SAndroid Build Coastguard Worker       .lower_cs_local_id_to_index = nir->info.stage == MESA_SHADER_MESH && !pdev->mesh_fast_launch_2,
477*61046927SAndroid Build Coastguard Worker       .lower_local_invocation_index = nir->info.stage == MESA_SHADER_COMPUTE &&
478*61046927SAndroid Build Coastguard Worker                                       ((nir->info.workgroup_size[0] == 1) + (nir->info.workgroup_size[1] == 1) +
479*61046927SAndroid Build Coastguard Worker                                        (nir->info.workgroup_size[2] == 1)) == 2,
480*61046927SAndroid Build Coastguard Worker    };
481*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_compute_system_values, &csv_options);
482*61046927SAndroid Build Coastguard Worker 
483*61046927SAndroid Build Coastguard Worker    /* Vulkan uses the separate-shader linking model */
484*61046927SAndroid Build Coastguard Worker    nir->info.separate_shader = true;
485*61046927SAndroid Build Coastguard Worker 
486*61046927SAndroid Build Coastguard Worker    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker    if (nir->info.ray_queries > 0) {
489*61046927SAndroid Build Coastguard Worker       /* Lower shared variables early to prevent the over allocation of shared memory in
490*61046927SAndroid Build Coastguard Worker        * radv_nir_lower_ray_queries.  */
491*61046927SAndroid Build Coastguard Worker       if (nir->info.stage == MESA_SHADER_COMPUTE) {
492*61046927SAndroid Build Coastguard Worker          if (!nir->info.shared_memory_explicit_layout)
493*61046927SAndroid Build Coastguard Worker             NIR_PASS(_, nir, nir_lower_vars_to_explicit_types, nir_var_mem_shared, shared_var_info);
494*61046927SAndroid Build Coastguard Worker 
495*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_shared, nir_address_format_32bit_offset);
496*61046927SAndroid Build Coastguard Worker       }
497*61046927SAndroid Build Coastguard Worker 
498*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_ray_queries);
499*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_opt_ray_query_ranges);
500*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, radv_nir_lower_ray_queries, device);
501*61046927SAndroid Build Coastguard Worker    }
502*61046927SAndroid Build Coastguard Worker 
503*61046927SAndroid Build Coastguard Worker    nir_lower_tex_options tex_options = {
504*61046927SAndroid Build Coastguard Worker       .lower_txp = ~0,
505*61046927SAndroid Build Coastguard Worker       .lower_txf_offset = true,
506*61046927SAndroid Build Coastguard Worker       .lower_tg4_offsets = true,
507*61046927SAndroid Build Coastguard Worker       .lower_txs_cube_array = true,
508*61046927SAndroid Build Coastguard Worker       .lower_to_fragment_fetch_amd = pdev->use_fmask,
509*61046927SAndroid Build Coastguard Worker       .lower_lod_zero_width = true,
510*61046927SAndroid Build Coastguard Worker       .lower_invalid_implicit_lod = true,
511*61046927SAndroid Build Coastguard Worker       .lower_1d = pdev->info.gfx_level == GFX9,
512*61046927SAndroid Build Coastguard Worker    };
513*61046927SAndroid Build Coastguard Worker 
514*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_tex, &tex_options);
515*61046927SAndroid Build Coastguard Worker 
516*61046927SAndroid Build Coastguard Worker    static const nir_lower_image_options image_options = {
517*61046927SAndroid Build Coastguard Worker       .lower_cube_size = true,
518*61046927SAndroid Build Coastguard Worker    };
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_image, &image_options);
521*61046927SAndroid Build Coastguard Worker 
522*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_vars_to_ssa);
523*61046927SAndroid Build Coastguard Worker 
524*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_VERTEX || nir->info.stage == MESA_SHADER_GEOMETRY ||
525*61046927SAndroid Build Coastguard Worker        nir->info.stage == MESA_SHADER_FRAGMENT) {
526*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, nir_lower_io_to_temporaries, nir_shader_get_entrypoint(nir), true, true);
527*61046927SAndroid Build Coastguard Worker    } else if (nir->info.stage == MESA_SHADER_TESS_EVAL) {
528*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, nir_lower_io_to_temporaries, nir_shader_get_entrypoint(nir), true, false);
529*61046927SAndroid Build Coastguard Worker    }
530*61046927SAndroid Build Coastguard Worker 
531*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_split_var_copies);
532*61046927SAndroid Build Coastguard Worker 
533*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_global_vars_to_local);
534*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_remove_dead_variables, nir_var_function_temp, NULL);
535*61046927SAndroid Build Coastguard Worker 
536*61046927SAndroid Build Coastguard Worker    bool gfx7minus = pdev->info.gfx_level <= GFX7;
537*61046927SAndroid Build Coastguard Worker    bool has_inverse_ballot = true;
538*61046927SAndroid Build Coastguard Worker    bool use_llvm = radv_use_llvm_for_stage(pdev, nir->info.stage);
539*61046927SAndroid Build Coastguard Worker #if AMD_LLVM_AVAILABLE
540*61046927SAndroid Build Coastguard Worker    has_inverse_ballot = !use_llvm || LLVM_VERSION_MAJOR >= 17;
541*61046927SAndroid Build Coastguard Worker #endif
542*61046927SAndroid Build Coastguard Worker 
543*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_subgroups,
544*61046927SAndroid Build Coastguard Worker             &(struct nir_lower_subgroups_options){
545*61046927SAndroid Build Coastguard Worker                .subgroup_size = subgroup_size,
546*61046927SAndroid Build Coastguard Worker                .ballot_bit_size = ballot_bit_size,
547*61046927SAndroid Build Coastguard Worker                .ballot_components = 1,
548*61046927SAndroid Build Coastguard Worker                .lower_to_scalar = 1,
549*61046927SAndroid Build Coastguard Worker                .lower_subgroup_masks = 1,
550*61046927SAndroid Build Coastguard Worker                .lower_relative_shuffle = 1,
551*61046927SAndroid Build Coastguard Worker                .lower_rotate_to_shuffle = use_llvm,
552*61046927SAndroid Build Coastguard Worker                .lower_shuffle_to_32bit = 1,
553*61046927SAndroid Build Coastguard Worker                .lower_vote_eq = 1,
554*61046927SAndroid Build Coastguard Worker                .lower_vote_bool_eq = 1,
555*61046927SAndroid Build Coastguard Worker                .lower_quad_broadcast_dynamic = 1,
556*61046927SAndroid Build Coastguard Worker                .lower_quad_broadcast_dynamic_to_const = gfx7minus,
557*61046927SAndroid Build Coastguard Worker                .lower_shuffle_to_swizzle_amd = 1,
558*61046927SAndroid Build Coastguard Worker                .lower_ballot_bit_count_to_mbcnt_amd = 1,
559*61046927SAndroid Build Coastguard Worker                .lower_inverse_ballot = !has_inverse_ballot,
560*61046927SAndroid Build Coastguard Worker                .lower_boolean_reduce = !use_llvm,
561*61046927SAndroid Build Coastguard Worker                .lower_boolean_shuffle = true,
562*61046927SAndroid Build Coastguard Worker             });
563*61046927SAndroid Build Coastguard Worker 
564*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_load_const_to_scalar);
565*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_opt_shrink_stores, !instance->drirc.disable_shrink_image_store);
566*61046927SAndroid Build Coastguard Worker 
567*61046927SAndroid Build Coastguard Worker    if (!stage->key.optimisations_disabled)
568*61046927SAndroid Build Coastguard Worker       radv_optimize_nir(nir, false);
569*61046927SAndroid Build Coastguard Worker 
570*61046927SAndroid Build Coastguard Worker    /* We call nir_lower_var_copies() after the first radv_optimize_nir()
571*61046927SAndroid Build Coastguard Worker     * to remove any copies introduced by nir_opt_find_array_copies().
572*61046927SAndroid Build Coastguard Worker     */
573*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_var_copies);
574*61046927SAndroid Build Coastguard Worker 
575*61046927SAndroid Build Coastguard Worker    unsigned lower_flrp = (nir->options->lower_flrp16 ? 16 : 0) | (nir->options->lower_flrp32 ? 32 : 0) |
576*61046927SAndroid Build Coastguard Worker                          (nir->options->lower_flrp64 ? 64 : 0);
577*61046927SAndroid Build Coastguard Worker    if (lower_flrp != 0) {
578*61046927SAndroid Build Coastguard Worker       bool progress = false;
579*61046927SAndroid Build Coastguard Worker       NIR_PASS(progress, nir, nir_lower_flrp, lower_flrp, false /* always precise */);
580*61046927SAndroid Build Coastguard Worker       if (progress)
581*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, nir_opt_constant_folding);
582*61046927SAndroid Build Coastguard Worker    }
583*61046927SAndroid Build Coastguard Worker 
584*61046927SAndroid Build Coastguard Worker    const nir_opt_access_options opt_access_options = {
585*61046927SAndroid Build Coastguard Worker       .is_vulkan = true,
586*61046927SAndroid Build Coastguard Worker    };
587*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_opt_access, &opt_access_options);
588*61046927SAndroid Build Coastguard Worker 
589*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_push_const, nir_address_format_32bit_offset);
590*61046927SAndroid Build Coastguard Worker 
591*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_ubo | nir_var_mem_ssbo,
592*61046927SAndroid Build Coastguard Worker             nir_address_format_vec2_index_32bit_offset);
593*61046927SAndroid Build Coastguard Worker 
594*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, radv_nir_lower_intrinsics_early, options && options->lower_view_index_to_zero);
595*61046927SAndroid Build Coastguard Worker 
596*61046927SAndroid Build Coastguard Worker    /* Lower deref operations for compute shared memory. */
597*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_COMPUTE || nir->info.stage == MESA_SHADER_TASK ||
598*61046927SAndroid Build Coastguard Worker        nir->info.stage == MESA_SHADER_MESH) {
599*61046927SAndroid Build Coastguard Worker       nir_variable_mode var_modes = nir_var_mem_shared;
600*61046927SAndroid Build Coastguard Worker 
601*61046927SAndroid Build Coastguard Worker       if (nir->info.stage == MESA_SHADER_TASK || nir->info.stage == MESA_SHADER_MESH)
602*61046927SAndroid Build Coastguard Worker          var_modes |= nir_var_mem_task_payload;
603*61046927SAndroid Build Coastguard Worker 
604*61046927SAndroid Build Coastguard Worker       if (!nir->info.shared_memory_explicit_layout)
605*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, nir_lower_vars_to_explicit_types, var_modes, shared_var_info);
606*61046927SAndroid Build Coastguard Worker       else if (var_modes & ~nir_var_mem_shared)
607*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, nir_lower_vars_to_explicit_types, var_modes & ~nir_var_mem_shared, shared_var_info);
608*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, nir_lower_explicit_io, var_modes, nir_address_format_32bit_offset);
609*61046927SAndroid Build Coastguard Worker 
610*61046927SAndroid Build Coastguard Worker       if (nir->info.zero_initialize_shared_memory && nir->info.shared_size > 0) {
611*61046927SAndroid Build Coastguard Worker          const unsigned chunk_size = 16; /* max single store size */
612*61046927SAndroid Build Coastguard Worker          const unsigned shared_size = ALIGN(nir->info.shared_size, chunk_size);
613*61046927SAndroid Build Coastguard Worker          NIR_PASS(_, nir, nir_zero_initialize_shared_memory, shared_size, chunk_size);
614*61046927SAndroid Build Coastguard Worker       }
615*61046927SAndroid Build Coastguard Worker    }
616*61046927SAndroid Build Coastguard Worker 
617*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_global | nir_var_mem_constant, nir_address_format_64bit_global);
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker    /* Lower large variables that are always constant with load_constant
620*61046927SAndroid Build Coastguard Worker     * intrinsics, which get turned into PC-relative loads from a data
621*61046927SAndroid Build Coastguard Worker     * section next to the shader.
622*61046927SAndroid Build Coastguard Worker     */
623*61046927SAndroid Build Coastguard Worker    NIR_PASS(_, nir, nir_opt_large_constants, glsl_get_natural_size_align_bytes, 16);
624*61046927SAndroid Build Coastguard Worker 
625*61046927SAndroid Build Coastguard Worker    /* Lower primitive shading rate to match HW requirements. */
626*61046927SAndroid Build Coastguard Worker    if ((nir->info.stage == MESA_SHADER_VERTEX || nir->info.stage == MESA_SHADER_GEOMETRY ||
627*61046927SAndroid Build Coastguard Worker         nir->info.stage == MESA_SHADER_MESH) &&
628*61046927SAndroid Build Coastguard Worker        nir->info.outputs_written & BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_SHADING_RATE)) {
629*61046927SAndroid Build Coastguard Worker       /* Lower primitive shading rate to match HW requirements. */
630*61046927SAndroid Build Coastguard Worker       NIR_PASS(_, nir, radv_nir_lower_primitive_shading_rate, pdev->info.gfx_level);
631*61046927SAndroid Build Coastguard Worker    }
632*61046927SAndroid Build Coastguard Worker 
633*61046927SAndroid Build Coastguard Worker    /* Indirect lowering must be called after the radv_optimize_nir() loop
634*61046927SAndroid Build Coastguard Worker     * has been called at least once. Otherwise indirect lowering can
635*61046927SAndroid Build Coastguard Worker     * bloat the instruction count of the loop and cause it to be
636*61046927SAndroid Build Coastguard Worker     * considered too large for unrolling.
637*61046927SAndroid Build Coastguard Worker     */
638*61046927SAndroid Build Coastguard Worker    if (ac_nir_lower_indirect_derefs(nir, pdev->info.gfx_level) && !stage->key.optimisations_disabled &&
639*61046927SAndroid Build Coastguard Worker        nir->info.stage != MESA_SHADER_COMPUTE) {
640*61046927SAndroid Build Coastguard Worker       /* Optimize the lowered code before the linking optimizations. */
641*61046927SAndroid Build Coastguard Worker       radv_optimize_nir(nir, false);
642*61046927SAndroid Build Coastguard Worker    }
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker    return nir;
645*61046927SAndroid Build Coastguard Worker }
646*61046927SAndroid Build Coastguard Worker 
647*61046927SAndroid Build Coastguard Worker bool
radv_consider_culling(const struct radv_physical_device * pdev,struct nir_shader * nir,uint64_t ps_inputs_read,unsigned num_vertices_per_primitive,const struct radv_shader_info * info)648*61046927SAndroid Build Coastguard Worker radv_consider_culling(const struct radv_physical_device *pdev, struct nir_shader *nir, uint64_t ps_inputs_read,
649*61046927SAndroid Build Coastguard Worker                       unsigned num_vertices_per_primitive, const struct radv_shader_info *info)
650*61046927SAndroid Build Coastguard Worker {
651*61046927SAndroid Build Coastguard Worker    /* Culling doesn't make sense for meta shaders. */
652*61046927SAndroid Build Coastguard Worker    if (is_meta_shader(nir))
653*61046927SAndroid Build Coastguard Worker       return false;
654*61046927SAndroid Build Coastguard Worker 
655*61046927SAndroid Build Coastguard Worker    /* We don't support culling with multiple viewports yet. */
656*61046927SAndroid Build Coastguard Worker    if (nir->info.outputs_written & (VARYING_BIT_VIEWPORT | VARYING_BIT_VIEWPORT_MASK))
657*61046927SAndroid Build Coastguard Worker       return false;
658*61046927SAndroid Build Coastguard Worker 
659*61046927SAndroid Build Coastguard Worker    /* We don't support culling with vertex shader prologs. */
660*61046927SAndroid Build Coastguard Worker    if (info->vs.has_prolog)
661*61046927SAndroid Build Coastguard Worker       return false;
662*61046927SAndroid Build Coastguard Worker 
663*61046927SAndroid Build Coastguard Worker    if (!pdev->use_ngg_culling)
664*61046927SAndroid Build Coastguard Worker       return false;
665*61046927SAndroid Build Coastguard Worker 
666*61046927SAndroid Build Coastguard Worker    /* Shader based culling efficiency can depend on PS throughput.
667*61046927SAndroid Build Coastguard Worker     * Estimate an upper limit for PS input param count based on GPU info.
668*61046927SAndroid Build Coastguard Worker     */
669*61046927SAndroid Build Coastguard Worker    unsigned max_ps_params = 8;
670*61046927SAndroid Build Coastguard Worker 
671*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX10_3 && pdev->info.has_dedicated_vram)
672*61046927SAndroid Build Coastguard Worker       max_ps_params = 12; /* GFX10.3 and newer discrete GPUs. */
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker    /* TODO: consider other heuristics here, such as PS execution time */
675*61046927SAndroid Build Coastguard Worker    if (util_bitcount64(ps_inputs_read & ~VARYING_BIT_POS) > max_ps_params)
676*61046927SAndroid Build Coastguard Worker       return false;
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker    /* Only triangle culling is supported. */
679*61046927SAndroid Build Coastguard Worker    if (num_vertices_per_primitive != 3)
680*61046927SAndroid Build Coastguard Worker       return false;
681*61046927SAndroid Build Coastguard Worker 
682*61046927SAndroid Build Coastguard Worker    /* When the shader writes memory, it is difficult to guarantee correctness.
683*61046927SAndroid Build Coastguard Worker     * Future work:
684*61046927SAndroid Build Coastguard Worker     * - if only write-only SSBOs are used
685*61046927SAndroid Build Coastguard Worker     * - if we can prove that non-position outputs don't rely on memory stores
686*61046927SAndroid Build Coastguard Worker     * then may be okay to keep the memory stores in the 1st shader part, and delete them from the 2nd.
687*61046927SAndroid Build Coastguard Worker     */
688*61046927SAndroid Build Coastguard Worker    if (nir->info.writes_memory)
689*61046927SAndroid Build Coastguard Worker       return false;
690*61046927SAndroid Build Coastguard Worker 
691*61046927SAndroid Build Coastguard Worker    /* When the shader relies on the subgroup invocation ID, we'd break it, because the ID changes after the culling.
692*61046927SAndroid Build Coastguard Worker     * Future work: try to save this to LDS and reload, but it can still be broken in subtle ways.
693*61046927SAndroid Build Coastguard Worker     */
694*61046927SAndroid Build Coastguard Worker    if (BITSET_TEST(nir->info.system_values_read, SYSTEM_VALUE_SUBGROUP_INVOCATION))
695*61046927SAndroid Build Coastguard Worker       return false;
696*61046927SAndroid Build Coastguard Worker 
697*61046927SAndroid Build Coastguard Worker    /* When re-using values that depend on subgroup operations, we'd break convergence guarantees.
698*61046927SAndroid Build Coastguard Worker     * Since we only re-use uniform values, the only subgroup operations we really care about are
699*61046927SAndroid Build Coastguard Worker     * ballot, reductions and vote intrinsics.
700*61046927SAndroid Build Coastguard Worker     */
701*61046927SAndroid Build Coastguard Worker    if (nir->info.maximally_reconverges && nir->info.uses_wide_subgroup_intrinsics)
702*61046927SAndroid Build Coastguard Worker       return false;
703*61046927SAndroid Build Coastguard Worker 
704*61046927SAndroid Build Coastguard Worker    return true;
705*61046927SAndroid Build Coastguard Worker }
706*61046927SAndroid Build Coastguard Worker 
707*61046927SAndroid Build Coastguard Worker void
radv_lower_ngg(struct radv_device * device,struct radv_shader_stage * ngg_stage,const struct radv_graphics_state_key * gfx_state)708*61046927SAndroid Build Coastguard Worker radv_lower_ngg(struct radv_device *device, struct radv_shader_stage *ngg_stage,
709*61046927SAndroid Build Coastguard Worker                const struct radv_graphics_state_key *gfx_state)
710*61046927SAndroid Build Coastguard Worker {
711*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
712*61046927SAndroid Build Coastguard Worker    const struct radv_shader_info *info = &ngg_stage->info;
713*61046927SAndroid Build Coastguard Worker    nir_shader *nir = ngg_stage->nir;
714*61046927SAndroid Build Coastguard Worker 
715*61046927SAndroid Build Coastguard Worker    assert(nir->info.stage == MESA_SHADER_VERTEX || nir->info.stage == MESA_SHADER_TESS_EVAL ||
716*61046927SAndroid Build Coastguard Worker           nir->info.stage == MESA_SHADER_GEOMETRY || nir->info.stage == MESA_SHADER_MESH);
717*61046927SAndroid Build Coastguard Worker 
718*61046927SAndroid Build Coastguard Worker    unsigned num_vertices_per_prim = 3;
719*61046927SAndroid Build Coastguard Worker 
720*61046927SAndroid Build Coastguard Worker    /* Get the number of vertices per input primitive */
721*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_TESS_EVAL) {
722*61046927SAndroid Build Coastguard Worker       if (nir->info.tess.point_mode)
723*61046927SAndroid Build Coastguard Worker          num_vertices_per_prim = 1;
724*61046927SAndroid Build Coastguard Worker       else if (nir->info.tess._primitive_mode == TESS_PRIMITIVE_ISOLINES)
725*61046927SAndroid Build Coastguard Worker          num_vertices_per_prim = 2;
726*61046927SAndroid Build Coastguard Worker 
727*61046927SAndroid Build Coastguard Worker       /* Manually mark the primitive ID used, so the shader can repack it. */
728*61046927SAndroid Build Coastguard Worker       if (info->outinfo.export_prim_id)
729*61046927SAndroid Build Coastguard Worker          BITSET_SET(nir->info.system_values_read, SYSTEM_VALUE_PRIMITIVE_ID);
730*61046927SAndroid Build Coastguard Worker 
731*61046927SAndroid Build Coastguard Worker    } else if (nir->info.stage == MESA_SHADER_VERTEX) {
732*61046927SAndroid Build Coastguard Worker       num_vertices_per_prim = radv_get_num_vertices_per_prim(gfx_state);
733*61046927SAndroid Build Coastguard Worker 
734*61046927SAndroid Build Coastguard Worker       /* Manually mark the instance ID used, so the shader can repack it. */
735*61046927SAndroid Build Coastguard Worker       if (gfx_state->vi.instance_rate_inputs)
736*61046927SAndroid Build Coastguard Worker          BITSET_SET(nir->info.system_values_read, SYSTEM_VALUE_INSTANCE_ID);
737*61046927SAndroid Build Coastguard Worker 
738*61046927SAndroid Build Coastguard Worker    } else if (nir->info.stage == MESA_SHADER_GEOMETRY) {
739*61046927SAndroid Build Coastguard Worker       num_vertices_per_prim = nir->info.gs.vertices_in;
740*61046927SAndroid Build Coastguard Worker    } else if (nir->info.stage == MESA_SHADER_MESH) {
741*61046927SAndroid Build Coastguard Worker       if (nir->info.mesh.primitive_type == MESA_PRIM_POINTS)
742*61046927SAndroid Build Coastguard Worker          num_vertices_per_prim = 1;
743*61046927SAndroid Build Coastguard Worker       else if (nir->info.mesh.primitive_type == MESA_PRIM_LINES)
744*61046927SAndroid Build Coastguard Worker          num_vertices_per_prim = 2;
745*61046927SAndroid Build Coastguard Worker       else
746*61046927SAndroid Build Coastguard Worker          assert(nir->info.mesh.primitive_type == MESA_PRIM_TRIANGLES);
747*61046927SAndroid Build Coastguard Worker    } else {
748*61046927SAndroid Build Coastguard Worker       unreachable("NGG needs to be VS, TES or GS.");
749*61046927SAndroid Build Coastguard Worker    }
750*61046927SAndroid Build Coastguard Worker 
751*61046927SAndroid Build Coastguard Worker    if (nir->info.stage != MESA_SHADER_MESH)
752*61046927SAndroid Build Coastguard Worker       nir->info.shared_size = info->ngg_info.lds_size;
753*61046927SAndroid Build Coastguard Worker 
754*61046927SAndroid Build Coastguard Worker    ac_nir_lower_ngg_options options = {0};
755*61046927SAndroid Build Coastguard Worker    options.family = pdev->info.family;
756*61046927SAndroid Build Coastguard Worker    options.gfx_level = pdev->info.gfx_level;
757*61046927SAndroid Build Coastguard Worker    options.max_workgroup_size = info->workgroup_size;
758*61046927SAndroid Build Coastguard Worker    options.wave_size = info->wave_size;
759*61046927SAndroid Build Coastguard Worker    options.clip_cull_dist_mask = info->outinfo.clip_dist_mask | info->outinfo.cull_dist_mask;
760*61046927SAndroid Build Coastguard Worker    options.vs_output_param_offset = info->outinfo.vs_output_param_offset;
761*61046927SAndroid Build Coastguard Worker    options.has_param_exports = info->outinfo.param_exports || info->outinfo.prim_param_exports;
762*61046927SAndroid Build Coastguard Worker    options.can_cull = nir->info.stage != MESA_SHADER_GEOMETRY && info->has_ngg_culling;
763*61046927SAndroid Build Coastguard Worker    options.disable_streamout = !pdev->use_ngg_streamout;
764*61046927SAndroid Build Coastguard Worker    options.has_gen_prim_query = info->has_prim_query;
765*61046927SAndroid Build Coastguard Worker    options.has_xfb_prim_query = info->has_xfb_query;
766*61046927SAndroid Build Coastguard Worker    options.has_gs_invocations_query = pdev->info.gfx_level < GFX11;
767*61046927SAndroid Build Coastguard Worker    options.has_gs_primitives_query = pdev->info.gfx_level < GFX11;
768*61046927SAndroid Build Coastguard Worker    options.force_vrs = info->force_vrs_per_vertex;
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker    if (nir->info.stage == MESA_SHADER_VERTEX || nir->info.stage == MESA_SHADER_TESS_EVAL) {
771*61046927SAndroid Build Coastguard Worker       assert(info->is_ngg);
772*61046927SAndroid Build Coastguard Worker 
773*61046927SAndroid Build Coastguard Worker       if (info->has_ngg_culling)
774*61046927SAndroid Build Coastguard Worker          radv_optimize_nir_algebraic(nir, false, false);
775*61046927SAndroid Build Coastguard Worker 
776*61046927SAndroid Build Coastguard Worker       options.num_vertices_per_primitive = num_vertices_per_prim;
777*61046927SAndroid Build Coastguard Worker       options.early_prim_export = info->has_ngg_early_prim_export;
778*61046927SAndroid Build Coastguard Worker       options.passthrough = info->is_ngg_passthrough;
779*61046927SAndroid Build Coastguard Worker       options.export_primitive_id = info->outinfo.export_prim_id;
780*61046927SAndroid Build Coastguard Worker       options.instance_rate_inputs = gfx_state->vi.instance_rate_inputs << VERT_ATTRIB_GENERIC0;
781*61046927SAndroid Build Coastguard Worker 
782*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, ac_nir_lower_ngg_nogs, &options);
783*61046927SAndroid Build Coastguard Worker 
784*61046927SAndroid Build Coastguard Worker       /* Increase ESGS ring size so the LLVM binary contains the correct LDS size. */
785*61046927SAndroid Build Coastguard Worker       ngg_stage->info.ngg_info.esgs_ring_size = nir->info.shared_size;
786*61046927SAndroid Build Coastguard Worker    } else if (nir->info.stage == MESA_SHADER_GEOMETRY) {
787*61046927SAndroid Build Coastguard Worker       assert(info->is_ngg);
788*61046927SAndroid Build Coastguard Worker 
789*61046927SAndroid Build Coastguard Worker       options.gs_out_vtx_bytes = info->gs.gsvs_vertex_size;
790*61046927SAndroid Build Coastguard Worker 
791*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, ac_nir_lower_ngg_gs, &options);
792*61046927SAndroid Build Coastguard Worker    } else if (nir->info.stage == MESA_SHADER_MESH) {
793*61046927SAndroid Build Coastguard Worker       /* ACO aligns the workgroup size to the wave size. */
794*61046927SAndroid Build Coastguard Worker       unsigned hw_workgroup_size = ALIGN(info->workgroup_size, info->wave_size);
795*61046927SAndroid Build Coastguard Worker 
796*61046927SAndroid Build Coastguard Worker       bool scratch_ring = false;
797*61046927SAndroid Build Coastguard Worker       NIR_PASS_V(nir, ac_nir_lower_ngg_ms, options.gfx_level, options.clip_cull_dist_mask,
798*61046927SAndroid Build Coastguard Worker                  options.vs_output_param_offset, options.has_param_exports, &scratch_ring, info->wave_size,
799*61046927SAndroid Build Coastguard Worker                  hw_workgroup_size, gfx_state->has_multiview_view_index, info->ms.has_query, pdev->mesh_fast_launch_2);
800*61046927SAndroid Build Coastguard Worker       ngg_stage->info.ms.needs_ms_scratch_ring = scratch_ring;
801*61046927SAndroid Build Coastguard Worker    } else {
802*61046927SAndroid Build Coastguard Worker       unreachable("invalid SW stage passed to radv_lower_ngg");
803*61046927SAndroid Build Coastguard Worker    }
804*61046927SAndroid Build Coastguard Worker }
805*61046927SAndroid Build Coastguard Worker 
806*61046927SAndroid Build Coastguard Worker static unsigned
get_size_class(unsigned size,bool round_up)807*61046927SAndroid Build Coastguard Worker get_size_class(unsigned size, bool round_up)
808*61046927SAndroid Build Coastguard Worker {
809*61046927SAndroid Build Coastguard Worker    size = round_up ? util_logbase2_ceil(size) : util_logbase2(size);
810*61046927SAndroid Build Coastguard Worker    unsigned size_class = MAX2(size, RADV_SHADER_ALLOC_MIN_SIZE_CLASS) - RADV_SHADER_ALLOC_MIN_SIZE_CLASS;
811*61046927SAndroid Build Coastguard Worker    return MIN2(size_class, RADV_SHADER_ALLOC_NUM_FREE_LISTS - 1);
812*61046927SAndroid Build Coastguard Worker }
813*61046927SAndroid Build Coastguard Worker 
814*61046927SAndroid Build Coastguard Worker static void
remove_hole(struct radv_shader_free_list * free_list,union radv_shader_arena_block * hole)815*61046927SAndroid Build Coastguard Worker remove_hole(struct radv_shader_free_list *free_list, union radv_shader_arena_block *hole)
816*61046927SAndroid Build Coastguard Worker {
817*61046927SAndroid Build Coastguard Worker    unsigned size_class = get_size_class(hole->size, false);
818*61046927SAndroid Build Coastguard Worker    list_del(&hole->freelist);
819*61046927SAndroid Build Coastguard Worker    if (list_is_empty(&free_list->free_lists[size_class]))
820*61046927SAndroid Build Coastguard Worker       free_list->size_mask &= ~(1u << size_class);
821*61046927SAndroid Build Coastguard Worker }
822*61046927SAndroid Build Coastguard Worker 
823*61046927SAndroid Build Coastguard Worker static void
add_hole(struct radv_shader_free_list * free_list,union radv_shader_arena_block * hole)824*61046927SAndroid Build Coastguard Worker add_hole(struct radv_shader_free_list *free_list, union radv_shader_arena_block *hole)
825*61046927SAndroid Build Coastguard Worker {
826*61046927SAndroid Build Coastguard Worker    unsigned size_class = get_size_class(hole->size, false);
827*61046927SAndroid Build Coastguard Worker    list_addtail(&hole->freelist, &free_list->free_lists[size_class]);
828*61046927SAndroid Build Coastguard Worker    free_list->size_mask |= 1u << size_class;
829*61046927SAndroid Build Coastguard Worker }
830*61046927SAndroid Build Coastguard Worker 
831*61046927SAndroid Build Coastguard Worker static union radv_shader_arena_block *
alloc_block_obj(struct radv_device * device)832*61046927SAndroid Build Coastguard Worker alloc_block_obj(struct radv_device *device)
833*61046927SAndroid Build Coastguard Worker {
834*61046927SAndroid Build Coastguard Worker    if (!list_is_empty(&device->shader_block_obj_pool)) {
835*61046927SAndroid Build Coastguard Worker       union radv_shader_arena_block *block =
836*61046927SAndroid Build Coastguard Worker          list_first_entry(&device->shader_block_obj_pool, union radv_shader_arena_block, pool);
837*61046927SAndroid Build Coastguard Worker       list_del(&block->pool);
838*61046927SAndroid Build Coastguard Worker       return block;
839*61046927SAndroid Build Coastguard Worker    }
840*61046927SAndroid Build Coastguard Worker 
841*61046927SAndroid Build Coastguard Worker    return malloc(sizeof(union radv_shader_arena_block));
842*61046927SAndroid Build Coastguard Worker }
843*61046927SAndroid Build Coastguard Worker 
844*61046927SAndroid Build Coastguard Worker static void
free_block_obj(struct radv_device * device,union radv_shader_arena_block * block)845*61046927SAndroid Build Coastguard Worker free_block_obj(struct radv_device *device, union radv_shader_arena_block *block)
846*61046927SAndroid Build Coastguard Worker {
847*61046927SAndroid Build Coastguard Worker    list_del(&block->pool);
848*61046927SAndroid Build Coastguard Worker    list_add(&block->pool, &device->shader_block_obj_pool);
849*61046927SAndroid Build Coastguard Worker }
850*61046927SAndroid Build Coastguard Worker 
851*61046927SAndroid Build Coastguard Worker VkResult
radv_shader_wait_for_upload(struct radv_device * device,uint64_t seq)852*61046927SAndroid Build Coastguard Worker radv_shader_wait_for_upload(struct radv_device *device, uint64_t seq)
853*61046927SAndroid Build Coastguard Worker {
854*61046927SAndroid Build Coastguard Worker    if (!seq)
855*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
856*61046927SAndroid Build Coastguard Worker 
857*61046927SAndroid Build Coastguard Worker    const VkSemaphoreWaitInfo wait_info = {
858*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
859*61046927SAndroid Build Coastguard Worker       .pSemaphores = &device->shader_upload_sem,
860*61046927SAndroid Build Coastguard Worker       .semaphoreCount = 1,
861*61046927SAndroid Build Coastguard Worker       .pValues = &seq,
862*61046927SAndroid Build Coastguard Worker    };
863*61046927SAndroid Build Coastguard Worker    return device->vk.dispatch_table.WaitSemaphores(radv_device_to_handle(device), &wait_info, UINT64_MAX);
864*61046927SAndroid Build Coastguard Worker }
865*61046927SAndroid Build Coastguard Worker 
866*61046927SAndroid Build Coastguard Worker static struct radv_shader_arena *
radv_create_shader_arena(struct radv_device * device,struct radv_shader_free_list * free_list,unsigned min_size,unsigned arena_size,bool replayable,uint64_t replay_va)867*61046927SAndroid Build Coastguard Worker radv_create_shader_arena(struct radv_device *device, struct radv_shader_free_list *free_list, unsigned min_size,
868*61046927SAndroid Build Coastguard Worker                          unsigned arena_size, bool replayable, uint64_t replay_va)
869*61046927SAndroid Build Coastguard Worker {
870*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
871*61046927SAndroid Build Coastguard Worker    union radv_shader_arena_block *alloc = NULL;
872*61046927SAndroid Build Coastguard Worker    struct radv_shader_arena *arena = calloc(1, sizeof(struct radv_shader_arena));
873*61046927SAndroid Build Coastguard Worker    if (!arena)
874*61046927SAndroid Build Coastguard Worker       goto fail;
875*61046927SAndroid Build Coastguard Worker 
876*61046927SAndroid Build Coastguard Worker    if (!arena_size)
877*61046927SAndroid Build Coastguard Worker       arena_size = MAX2(
878*61046927SAndroid Build Coastguard Worker          RADV_SHADER_ALLOC_MIN_ARENA_SIZE << MIN2(RADV_SHADER_ALLOC_MAX_ARENA_SIZE_SHIFT, device->shader_arena_shift),
879*61046927SAndroid Build Coastguard Worker          min_size);
880*61046927SAndroid Build Coastguard Worker    arena->size = arena_size;
881*61046927SAndroid Build Coastguard Worker 
882*61046927SAndroid Build Coastguard Worker    enum radeon_bo_flag flags = RADEON_FLAG_NO_INTERPROCESS_SHARING | RADEON_FLAG_32BIT;
883*61046927SAndroid Build Coastguard Worker    if (device->shader_use_invisible_vram)
884*61046927SAndroid Build Coastguard Worker       flags |= RADEON_FLAG_NO_CPU_ACCESS;
885*61046927SAndroid Build Coastguard Worker    else
886*61046927SAndroid Build Coastguard Worker       flags |= (pdev->info.cpdma_prefetch_writes_memory ? 0 : RADEON_FLAG_READ_ONLY);
887*61046927SAndroid Build Coastguard Worker 
888*61046927SAndroid Build Coastguard Worker    if (replayable)
889*61046927SAndroid Build Coastguard Worker       flags |= RADEON_FLAG_REPLAYABLE;
890*61046927SAndroid Build Coastguard Worker 
891*61046927SAndroid Build Coastguard Worker    /* vkCmdUpdatePipelineIndirectBufferNV() can be called on any queue supporting transfer
892*61046927SAndroid Build Coastguard Worker     * operations and it's not required to call it on the same queue as DGC execute. To make sure the
893*61046927SAndroid Build Coastguard Worker     * compute shader BO is part of the DGC execute submission, force all shaders to be local BOs.
894*61046927SAndroid Build Coastguard Worker     */
895*61046927SAndroid Build Coastguard Worker    if (device->vk.enabled_features.deviceGeneratedComputePipelines)
896*61046927SAndroid Build Coastguard Worker       flags |= RADEON_FLAG_PREFER_LOCAL_BO;
897*61046927SAndroid Build Coastguard Worker 
898*61046927SAndroid Build Coastguard Worker    VkResult result;
899*61046927SAndroid Build Coastguard Worker    result = radv_bo_create(device, NULL, arena_size, RADV_SHADER_ALLOC_ALIGNMENT, RADEON_DOMAIN_VRAM, flags,
900*61046927SAndroid Build Coastguard Worker                            RADV_BO_PRIORITY_SHADER, replay_va, true, &arena->bo);
901*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
902*61046927SAndroid Build Coastguard Worker       goto fail;
903*61046927SAndroid Build Coastguard Worker 
904*61046927SAndroid Build Coastguard Worker    list_inithead(&arena->entries);
905*61046927SAndroid Build Coastguard Worker    alloc = alloc_block_obj(device);
906*61046927SAndroid Build Coastguard Worker    if (!alloc)
907*61046927SAndroid Build Coastguard Worker       goto fail;
908*61046927SAndroid Build Coastguard Worker 
909*61046927SAndroid Build Coastguard Worker    list_inithead(&alloc->freelist);
910*61046927SAndroid Build Coastguard Worker    alloc->arena = arena;
911*61046927SAndroid Build Coastguard Worker    alloc->offset = 0;
912*61046927SAndroid Build Coastguard Worker    alloc->size = arena_size;
913*61046927SAndroid Build Coastguard Worker    list_addtail(&alloc->list, &arena->entries);
914*61046927SAndroid Build Coastguard Worker    if (free_list)
915*61046927SAndroid Build Coastguard Worker       add_hole(free_list, alloc);
916*61046927SAndroid Build Coastguard Worker 
917*61046927SAndroid Build Coastguard Worker    if (!(flags & RADEON_FLAG_NO_CPU_ACCESS)) {
918*61046927SAndroid Build Coastguard Worker       arena->ptr = (char *)radv_buffer_map(device->ws, arena->bo);
919*61046927SAndroid Build Coastguard Worker       if (!arena->ptr)
920*61046927SAndroid Build Coastguard Worker          goto fail;
921*61046927SAndroid Build Coastguard Worker    }
922*61046927SAndroid Build Coastguard Worker 
923*61046927SAndroid Build Coastguard Worker    if (replay_va)
924*61046927SAndroid Build Coastguard Worker       arena->type = RADV_SHADER_ARENA_REPLAYED;
925*61046927SAndroid Build Coastguard Worker    else if (replayable)
926*61046927SAndroid Build Coastguard Worker       arena->type = RADV_SHADER_ARENA_REPLAYABLE;
927*61046927SAndroid Build Coastguard Worker    else
928*61046927SAndroid Build Coastguard Worker       arena->type = RADV_SHADER_ARENA_DEFAULT;
929*61046927SAndroid Build Coastguard Worker 
930*61046927SAndroid Build Coastguard Worker    return arena;
931*61046927SAndroid Build Coastguard Worker 
932*61046927SAndroid Build Coastguard Worker fail:
933*61046927SAndroid Build Coastguard Worker    if (alloc)
934*61046927SAndroid Build Coastguard Worker       free_block_obj(device, alloc);
935*61046927SAndroid Build Coastguard Worker    if (arena && arena->bo)
936*61046927SAndroid Build Coastguard Worker       radv_bo_destroy(device, NULL, arena->bo);
937*61046927SAndroid Build Coastguard Worker    free(arena);
938*61046927SAndroid Build Coastguard Worker    return NULL;
939*61046927SAndroid Build Coastguard Worker }
940*61046927SAndroid Build Coastguard Worker 
941*61046927SAndroid Build Coastguard Worker /* Inserts a block at an arbitrary place into a hole, splitting the hole as needed */
942*61046927SAndroid Build Coastguard Worker static union radv_shader_arena_block *
insert_block(struct radv_device * device,union radv_shader_arena_block * hole,uint32_t offset_in_hole,uint32_t size,struct radv_shader_free_list * free_list)943*61046927SAndroid Build Coastguard Worker insert_block(struct radv_device *device, union radv_shader_arena_block *hole, uint32_t offset_in_hole, uint32_t size,
944*61046927SAndroid Build Coastguard Worker              struct radv_shader_free_list *free_list)
945*61046927SAndroid Build Coastguard Worker {
946*61046927SAndroid Build Coastguard Worker    uint32_t hole_begin = hole->offset;
947*61046927SAndroid Build Coastguard Worker    uint32_t hole_end = hole->offset + hole->size;
948*61046927SAndroid Build Coastguard Worker 
949*61046927SAndroid Build Coastguard Worker    /* The block might not lie exactly at the beginning or end
950*61046927SAndroid Build Coastguard Worker     * of the hole. Resize the hole to fit the block exactly,
951*61046927SAndroid Build Coastguard Worker     * and insert new holes before (left_hole) or after (right_hole) as needed.
952*61046927SAndroid Build Coastguard Worker     * left_hole or right_hole are skipped if the allocation lies exactly at the
953*61046927SAndroid Build Coastguard Worker     * beginning or end of the hole to avoid 0-sized holes. */
954*61046927SAndroid Build Coastguard Worker    union radv_shader_arena_block *left_hole = NULL;
955*61046927SAndroid Build Coastguard Worker    union radv_shader_arena_block *right_hole = NULL;
956*61046927SAndroid Build Coastguard Worker 
957*61046927SAndroid Build Coastguard Worker    if (offset_in_hole) {
958*61046927SAndroid Build Coastguard Worker       left_hole = alloc_block_obj(device);
959*61046927SAndroid Build Coastguard Worker       if (!left_hole)
960*61046927SAndroid Build Coastguard Worker          return NULL;
961*61046927SAndroid Build Coastguard Worker       list_inithead(&left_hole->freelist);
962*61046927SAndroid Build Coastguard Worker       left_hole->arena = hole->arena;
963*61046927SAndroid Build Coastguard Worker       left_hole->offset = hole->offset;
964*61046927SAndroid Build Coastguard Worker       left_hole->size = offset_in_hole;
965*61046927SAndroid Build Coastguard Worker 
966*61046927SAndroid Build Coastguard Worker       if (free_list)
967*61046927SAndroid Build Coastguard Worker          add_hole(free_list, left_hole);
968*61046927SAndroid Build Coastguard Worker    }
969*61046927SAndroid Build Coastguard Worker 
970*61046927SAndroid Build Coastguard Worker    if (hole->size > offset_in_hole + size) {
971*61046927SAndroid Build Coastguard Worker       right_hole = alloc_block_obj(device);
972*61046927SAndroid Build Coastguard Worker       if (!right_hole) {
973*61046927SAndroid Build Coastguard Worker          free(left_hole);
974*61046927SAndroid Build Coastguard Worker          return NULL;
975*61046927SAndroid Build Coastguard Worker       }
976*61046927SAndroid Build Coastguard Worker       list_inithead(&right_hole->freelist);
977*61046927SAndroid Build Coastguard Worker       right_hole->arena = hole->arena;
978*61046927SAndroid Build Coastguard Worker       right_hole->offset = hole_begin + offset_in_hole + size;
979*61046927SAndroid Build Coastguard Worker       right_hole->size = hole_end - right_hole->offset;
980*61046927SAndroid Build Coastguard Worker 
981*61046927SAndroid Build Coastguard Worker       if (free_list)
982*61046927SAndroid Build Coastguard Worker          add_hole(free_list, right_hole);
983*61046927SAndroid Build Coastguard Worker    }
984*61046927SAndroid Build Coastguard Worker 
985*61046927SAndroid Build Coastguard Worker    if (left_hole) {
986*61046927SAndroid Build Coastguard Worker       hole->offset += left_hole->size;
987*61046927SAndroid Build Coastguard Worker       hole->size -= left_hole->size;
988*61046927SAndroid Build Coastguard Worker 
989*61046927SAndroid Build Coastguard Worker       list_addtail(&left_hole->list, &hole->list);
990*61046927SAndroid Build Coastguard Worker    }
991*61046927SAndroid Build Coastguard Worker    if (right_hole) {
992*61046927SAndroid Build Coastguard Worker       hole->size -= right_hole->size;
993*61046927SAndroid Build Coastguard Worker 
994*61046927SAndroid Build Coastguard Worker       list_add(&right_hole->list, &hole->list);
995*61046927SAndroid Build Coastguard Worker    }
996*61046927SAndroid Build Coastguard Worker 
997*61046927SAndroid Build Coastguard Worker    if (free_list)
998*61046927SAndroid Build Coastguard Worker       remove_hole(free_list, hole);
999*61046927SAndroid Build Coastguard Worker    return hole;
1000*61046927SAndroid Build Coastguard Worker }
1001*61046927SAndroid Build Coastguard Worker 
1002*61046927SAndroid Build Coastguard Worker /* Segregated fit allocator, implementing a good-fit allocation policy.
1003*61046927SAndroid Build Coastguard Worker  *
1004*61046927SAndroid Build Coastguard Worker  * This is an variation of sequential fit allocation with several lists of free blocks ("holes")
1005*61046927SAndroid Build Coastguard Worker  * instead of one. Each list of holes only contains holes of a certain range of sizes, so holes that
1006*61046927SAndroid Build Coastguard Worker  * are too small can easily be ignored while allocating. Because this also ignores holes that are
1007*61046927SAndroid Build Coastguard Worker  * larger than necessary (approximating best-fit allocation), this could be described as a
1008*61046927SAndroid Build Coastguard Worker  * "good-fit" allocator.
1009*61046927SAndroid Build Coastguard Worker  *
1010*61046927SAndroid Build Coastguard Worker  * Typically, shaders are allocated and only free'd when the device is destroyed. For this pattern,
1011*61046927SAndroid Build Coastguard Worker  * this should allocate blocks for shaders fast and with no fragmentation, while still allowing
1012*61046927SAndroid Build Coastguard Worker  * free'd memory to be re-used.
1013*61046927SAndroid Build Coastguard Worker  */
1014*61046927SAndroid Build Coastguard Worker union radv_shader_arena_block *
radv_alloc_shader_memory(struct radv_device * device,uint32_t size,bool replayable,void * ptr)1015*61046927SAndroid Build Coastguard Worker radv_alloc_shader_memory(struct radv_device *device, uint32_t size, bool replayable, void *ptr)
1016*61046927SAndroid Build Coastguard Worker {
1017*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1018*61046927SAndroid Build Coastguard Worker 
1019*61046927SAndroid Build Coastguard Worker    size = ac_align_shader_binary_for_prefetch(&pdev->info, size);
1020*61046927SAndroid Build Coastguard Worker    size = align(size, RADV_SHADER_ALLOC_ALIGNMENT);
1021*61046927SAndroid Build Coastguard Worker 
1022*61046927SAndroid Build Coastguard Worker    mtx_lock(&device->shader_arena_mutex);
1023*61046927SAndroid Build Coastguard Worker 
1024*61046927SAndroid Build Coastguard Worker    struct radv_shader_free_list *free_list = replayable ? &device->capture_replay_free_list : &device->shader_free_list;
1025*61046927SAndroid Build Coastguard Worker 
1026*61046927SAndroid Build Coastguard Worker    /* Try to use an existing hole. Unless the shader is very large, this should only have to look
1027*61046927SAndroid Build Coastguard Worker     * at the first one available.
1028*61046927SAndroid Build Coastguard Worker     */
1029*61046927SAndroid Build Coastguard Worker    unsigned free_list_mask = BITFIELD_MASK(RADV_SHADER_ALLOC_NUM_FREE_LISTS);
1030*61046927SAndroid Build Coastguard Worker    unsigned size_class = ffs(free_list->size_mask & (free_list_mask << get_size_class(size, true)));
1031*61046927SAndroid Build Coastguard Worker    if (size_class) {
1032*61046927SAndroid Build Coastguard Worker       size_class--;
1033*61046927SAndroid Build Coastguard Worker 
1034*61046927SAndroid Build Coastguard Worker       list_for_each_entry (union radv_shader_arena_block, hole, &free_list->free_lists[size_class], freelist) {
1035*61046927SAndroid Build Coastguard Worker          if (hole->size < size)
1036*61046927SAndroid Build Coastguard Worker             continue;
1037*61046927SAndroid Build Coastguard Worker 
1038*61046927SAndroid Build Coastguard Worker          assert(hole->offset % RADV_SHADER_ALLOC_ALIGNMENT == 0);
1039*61046927SAndroid Build Coastguard Worker 
1040*61046927SAndroid Build Coastguard Worker          if (size == hole->size) {
1041*61046927SAndroid Build Coastguard Worker             remove_hole(free_list, hole);
1042*61046927SAndroid Build Coastguard Worker             hole->freelist.next = ptr;
1043*61046927SAndroid Build Coastguard Worker             mtx_unlock(&device->shader_arena_mutex);
1044*61046927SAndroid Build Coastguard Worker             return hole;
1045*61046927SAndroid Build Coastguard Worker          } else {
1046*61046927SAndroid Build Coastguard Worker             union radv_shader_arena_block *alloc = alloc_block_obj(device);
1047*61046927SAndroid Build Coastguard Worker             if (!alloc) {
1048*61046927SAndroid Build Coastguard Worker                mtx_unlock(&device->shader_arena_mutex);
1049*61046927SAndroid Build Coastguard Worker                return NULL;
1050*61046927SAndroid Build Coastguard Worker             }
1051*61046927SAndroid Build Coastguard Worker             list_addtail(&alloc->list, &hole->list);
1052*61046927SAndroid Build Coastguard Worker             alloc->freelist.prev = NULL;
1053*61046927SAndroid Build Coastguard Worker             alloc->freelist.next = ptr;
1054*61046927SAndroid Build Coastguard Worker             alloc->arena = hole->arena;
1055*61046927SAndroid Build Coastguard Worker             alloc->offset = hole->offset;
1056*61046927SAndroid Build Coastguard Worker             alloc->size = size;
1057*61046927SAndroid Build Coastguard Worker 
1058*61046927SAndroid Build Coastguard Worker             remove_hole(free_list, hole);
1059*61046927SAndroid Build Coastguard Worker             hole->offset += size;
1060*61046927SAndroid Build Coastguard Worker             hole->size -= size;
1061*61046927SAndroid Build Coastguard Worker             add_hole(free_list, hole);
1062*61046927SAndroid Build Coastguard Worker 
1063*61046927SAndroid Build Coastguard Worker             mtx_unlock(&device->shader_arena_mutex);
1064*61046927SAndroid Build Coastguard Worker             return alloc;
1065*61046927SAndroid Build Coastguard Worker          }
1066*61046927SAndroid Build Coastguard Worker       }
1067*61046927SAndroid Build Coastguard Worker    }
1068*61046927SAndroid Build Coastguard Worker 
1069*61046927SAndroid Build Coastguard Worker    struct radv_shader_arena *arena = radv_create_shader_arena(device, free_list, size, 0, replayable, 0);
1070*61046927SAndroid Build Coastguard Worker    union radv_shader_arena_block *alloc = NULL;
1071*61046927SAndroid Build Coastguard Worker    if (!arena)
1072*61046927SAndroid Build Coastguard Worker       goto fail;
1073*61046927SAndroid Build Coastguard Worker 
1074*61046927SAndroid Build Coastguard Worker    alloc =
1075*61046927SAndroid Build Coastguard Worker       insert_block(device, list_entry(arena->entries.next, union radv_shader_arena_block, list), 0, size, free_list);
1076*61046927SAndroid Build Coastguard Worker    alloc->freelist.prev = NULL;
1077*61046927SAndroid Build Coastguard Worker    alloc->freelist.next = ptr;
1078*61046927SAndroid Build Coastguard Worker 
1079*61046927SAndroid Build Coastguard Worker    ++device->shader_arena_shift;
1080*61046927SAndroid Build Coastguard Worker    list_addtail(&arena->list, &device->shader_arenas);
1081*61046927SAndroid Build Coastguard Worker 
1082*61046927SAndroid Build Coastguard Worker    mtx_unlock(&device->shader_arena_mutex);
1083*61046927SAndroid Build Coastguard Worker    return alloc;
1084*61046927SAndroid Build Coastguard Worker 
1085*61046927SAndroid Build Coastguard Worker fail:
1086*61046927SAndroid Build Coastguard Worker    mtx_unlock(&device->shader_arena_mutex);
1087*61046927SAndroid Build Coastguard Worker    free(alloc);
1088*61046927SAndroid Build Coastguard Worker    if (arena) {
1089*61046927SAndroid Build Coastguard Worker       free(arena->list.next);
1090*61046927SAndroid Build Coastguard Worker       radv_bo_destroy(device, NULL, arena->bo);
1091*61046927SAndroid Build Coastguard Worker    }
1092*61046927SAndroid Build Coastguard Worker    free(arena);
1093*61046927SAndroid Build Coastguard Worker    return NULL;
1094*61046927SAndroid Build Coastguard Worker }
1095*61046927SAndroid Build Coastguard Worker 
1096*61046927SAndroid Build Coastguard Worker static union radv_shader_arena_block *
get_hole(struct radv_shader_arena * arena,struct list_head * head)1097*61046927SAndroid Build Coastguard Worker get_hole(struct radv_shader_arena *arena, struct list_head *head)
1098*61046927SAndroid Build Coastguard Worker {
1099*61046927SAndroid Build Coastguard Worker    if (head == &arena->entries)
1100*61046927SAndroid Build Coastguard Worker       return NULL;
1101*61046927SAndroid Build Coastguard Worker 
1102*61046927SAndroid Build Coastguard Worker    union radv_shader_arena_block *hole = list_entry(head, union radv_shader_arena_block, list);
1103*61046927SAndroid Build Coastguard Worker    return hole->freelist.prev ? hole : NULL;
1104*61046927SAndroid Build Coastguard Worker }
1105*61046927SAndroid Build Coastguard Worker 
1106*61046927SAndroid Build Coastguard Worker void
radv_free_shader_memory(struct radv_device * device,union radv_shader_arena_block * alloc)1107*61046927SAndroid Build Coastguard Worker radv_free_shader_memory(struct radv_device *device, union radv_shader_arena_block *alloc)
1108*61046927SAndroid Build Coastguard Worker {
1109*61046927SAndroid Build Coastguard Worker    mtx_lock(&device->shader_arena_mutex);
1110*61046927SAndroid Build Coastguard Worker 
1111*61046927SAndroid Build Coastguard Worker    union radv_shader_arena_block *hole_prev = get_hole(alloc->arena, alloc->list.prev);
1112*61046927SAndroid Build Coastguard Worker    union radv_shader_arena_block *hole_next = get_hole(alloc->arena, alloc->list.next);
1113*61046927SAndroid Build Coastguard Worker 
1114*61046927SAndroid Build Coastguard Worker    union radv_shader_arena_block *hole = alloc;
1115*61046927SAndroid Build Coastguard Worker 
1116*61046927SAndroid Build Coastguard Worker    struct radv_shader_free_list *free_list;
1117*61046927SAndroid Build Coastguard Worker 
1118*61046927SAndroid Build Coastguard Worker    switch (alloc->arena->type) {
1119*61046927SAndroid Build Coastguard Worker    case RADV_SHADER_ARENA_DEFAULT:
1120*61046927SAndroid Build Coastguard Worker       free_list = &device->shader_free_list;
1121*61046927SAndroid Build Coastguard Worker       break;
1122*61046927SAndroid Build Coastguard Worker    case RADV_SHADER_ARENA_REPLAYABLE:
1123*61046927SAndroid Build Coastguard Worker       free_list = &device->capture_replay_free_list;
1124*61046927SAndroid Build Coastguard Worker       break;
1125*61046927SAndroid Build Coastguard Worker    case RADV_SHADER_ARENA_REPLAYED:
1126*61046927SAndroid Build Coastguard Worker       free_list = NULL;
1127*61046927SAndroid Build Coastguard Worker       break;
1128*61046927SAndroid Build Coastguard Worker    default:
1129*61046927SAndroid Build Coastguard Worker       unreachable("invalid shader arena type");
1130*61046927SAndroid Build Coastguard Worker    }
1131*61046927SAndroid Build Coastguard Worker 
1132*61046927SAndroid Build Coastguard Worker    /* merge with previous hole */
1133*61046927SAndroid Build Coastguard Worker    if (hole_prev) {
1134*61046927SAndroid Build Coastguard Worker       if (free_list)
1135*61046927SAndroid Build Coastguard Worker          remove_hole(free_list, hole_prev);
1136*61046927SAndroid Build Coastguard Worker 
1137*61046927SAndroid Build Coastguard Worker       hole_prev->size += hole->size;
1138*61046927SAndroid Build Coastguard Worker       free_block_obj(device, hole);
1139*61046927SAndroid Build Coastguard Worker 
1140*61046927SAndroid Build Coastguard Worker       hole = hole_prev;
1141*61046927SAndroid Build Coastguard Worker    }
1142*61046927SAndroid Build Coastguard Worker 
1143*61046927SAndroid Build Coastguard Worker    /* merge with next hole */
1144*61046927SAndroid Build Coastguard Worker    if (hole_next) {
1145*61046927SAndroid Build Coastguard Worker       if (free_list)
1146*61046927SAndroid Build Coastguard Worker          remove_hole(free_list, hole_next);
1147*61046927SAndroid Build Coastguard Worker 
1148*61046927SAndroid Build Coastguard Worker       hole_next->offset -= hole->size;
1149*61046927SAndroid Build Coastguard Worker       hole_next->size += hole->size;
1150*61046927SAndroid Build Coastguard Worker       free_block_obj(device, hole);
1151*61046927SAndroid Build Coastguard Worker 
1152*61046927SAndroid Build Coastguard Worker       hole = hole_next;
1153*61046927SAndroid Build Coastguard Worker    }
1154*61046927SAndroid Build Coastguard Worker 
1155*61046927SAndroid Build Coastguard Worker    if (list_is_singular(&hole->list)) {
1156*61046927SAndroid Build Coastguard Worker       struct radv_shader_arena *arena = hole->arena;
1157*61046927SAndroid Build Coastguard Worker       free_block_obj(device, hole);
1158*61046927SAndroid Build Coastguard Worker 
1159*61046927SAndroid Build Coastguard Worker       radv_bo_destroy(device, NULL, arena->bo);
1160*61046927SAndroid Build Coastguard Worker       list_del(&arena->list);
1161*61046927SAndroid Build Coastguard Worker 
1162*61046927SAndroid Build Coastguard Worker       if (device->capture_replay_arena_vas) {
1163*61046927SAndroid Build Coastguard Worker          struct hash_entry *arena_entry = NULL;
1164*61046927SAndroid Build Coastguard Worker          hash_table_foreach (device->capture_replay_arena_vas->table, entry) {
1165*61046927SAndroid Build Coastguard Worker             if (entry->data == arena) {
1166*61046927SAndroid Build Coastguard Worker                arena_entry = entry;
1167*61046927SAndroid Build Coastguard Worker                break;
1168*61046927SAndroid Build Coastguard Worker             }
1169*61046927SAndroid Build Coastguard Worker          }
1170*61046927SAndroid Build Coastguard Worker          _mesa_hash_table_remove(device->capture_replay_arena_vas->table, arena_entry);
1171*61046927SAndroid Build Coastguard Worker       }
1172*61046927SAndroid Build Coastguard Worker 
1173*61046927SAndroid Build Coastguard Worker       free(arena);
1174*61046927SAndroid Build Coastguard Worker    } else if (free_list) {
1175*61046927SAndroid Build Coastguard Worker       add_hole(free_list, hole);
1176*61046927SAndroid Build Coastguard Worker    }
1177*61046927SAndroid Build Coastguard Worker 
1178*61046927SAndroid Build Coastguard Worker    mtx_unlock(&device->shader_arena_mutex);
1179*61046927SAndroid Build Coastguard Worker }
1180*61046927SAndroid Build Coastguard Worker 
1181*61046927SAndroid Build Coastguard Worker union radv_shader_arena_block *
radv_replay_shader_arena_block(struct radv_device * device,const struct radv_serialized_shader_arena_block * src,void * ptr)1182*61046927SAndroid Build Coastguard Worker radv_replay_shader_arena_block(struct radv_device *device, const struct radv_serialized_shader_arena_block *src,
1183*61046927SAndroid Build Coastguard Worker                                void *ptr)
1184*61046927SAndroid Build Coastguard Worker {
1185*61046927SAndroid Build Coastguard Worker    mtx_lock(&device->shader_arena_mutex);
1186*61046927SAndroid Build Coastguard Worker 
1187*61046927SAndroid Build Coastguard Worker    union radv_shader_arena_block *ret_block = NULL;
1188*61046927SAndroid Build Coastguard Worker 
1189*61046927SAndroid Build Coastguard Worker    uint64_t va = src->arena_va;
1190*61046927SAndroid Build Coastguard Worker    void *data = _mesa_hash_table_u64_search(device->capture_replay_arena_vas, va);
1191*61046927SAndroid Build Coastguard Worker 
1192*61046927SAndroid Build Coastguard Worker    if (!data) {
1193*61046927SAndroid Build Coastguard Worker       struct radv_shader_arena *arena = radv_create_shader_arena(device, NULL, 0, src->arena_size, true, src->arena_va);
1194*61046927SAndroid Build Coastguard Worker       if (!arena)
1195*61046927SAndroid Build Coastguard Worker          goto out;
1196*61046927SAndroid Build Coastguard Worker 
1197*61046927SAndroid Build Coastguard Worker       _mesa_hash_table_u64_insert(device->capture_replay_arena_vas, src->arena_va, arena);
1198*61046927SAndroid Build Coastguard Worker       list_addtail(&arena->list, &device->shader_arenas);
1199*61046927SAndroid Build Coastguard Worker       data = arena;
1200*61046927SAndroid Build Coastguard Worker    }
1201*61046927SAndroid Build Coastguard Worker 
1202*61046927SAndroid Build Coastguard Worker    uint32_t block_begin = src->offset;
1203*61046927SAndroid Build Coastguard Worker    uint32_t block_end = src->offset + src->size;
1204*61046927SAndroid Build Coastguard Worker 
1205*61046927SAndroid Build Coastguard Worker    struct radv_shader_arena *arena = data;
1206*61046927SAndroid Build Coastguard Worker    list_for_each_entry (union radv_shader_arena_block, hole, &arena->entries, list) {
1207*61046927SAndroid Build Coastguard Worker       /* Only consider holes, not allocated shaders */
1208*61046927SAndroid Build Coastguard Worker       if (!hole->freelist.prev)
1209*61046927SAndroid Build Coastguard Worker          continue;
1210*61046927SAndroid Build Coastguard Worker 
1211*61046927SAndroid Build Coastguard Worker       uint32_t hole_begin = hole->offset;
1212*61046927SAndroid Build Coastguard Worker       uint32_t hole_end = hole->offset + hole->size;
1213*61046927SAndroid Build Coastguard Worker 
1214*61046927SAndroid Build Coastguard Worker       if (hole_end < block_end)
1215*61046927SAndroid Build Coastguard Worker          continue;
1216*61046927SAndroid Build Coastguard Worker 
1217*61046927SAndroid Build Coastguard Worker       /* If another allocated block overlaps the current replay block, allocation is impossible */
1218*61046927SAndroid Build Coastguard Worker       if (hole_begin > block_begin)
1219*61046927SAndroid Build Coastguard Worker          goto out;
1220*61046927SAndroid Build Coastguard Worker 
1221*61046927SAndroid Build Coastguard Worker       union radv_shader_arena_block *block = insert_block(device, hole, block_begin - hole_begin, src->size, NULL);
1222*61046927SAndroid Build Coastguard Worker       if (!block)
1223*61046927SAndroid Build Coastguard Worker          goto out;
1224*61046927SAndroid Build Coastguard Worker 
1225*61046927SAndroid Build Coastguard Worker       block->freelist.prev = NULL;
1226*61046927SAndroid Build Coastguard Worker       block->freelist.next = ptr;
1227*61046927SAndroid Build Coastguard Worker 
1228*61046927SAndroid Build Coastguard Worker       ret_block = hole;
1229*61046927SAndroid Build Coastguard Worker       break;
1230*61046927SAndroid Build Coastguard Worker    }
1231*61046927SAndroid Build Coastguard Worker 
1232*61046927SAndroid Build Coastguard Worker out:
1233*61046927SAndroid Build Coastguard Worker    mtx_unlock(&device->shader_arena_mutex);
1234*61046927SAndroid Build Coastguard Worker    return ret_block;
1235*61046927SAndroid Build Coastguard Worker }
1236*61046927SAndroid Build Coastguard Worker 
1237*61046927SAndroid Build Coastguard Worker void
radv_init_shader_arenas(struct radv_device * device)1238*61046927SAndroid Build Coastguard Worker radv_init_shader_arenas(struct radv_device *device)
1239*61046927SAndroid Build Coastguard Worker {
1240*61046927SAndroid Build Coastguard Worker    mtx_init(&device->shader_arena_mutex, mtx_plain);
1241*61046927SAndroid Build Coastguard Worker 
1242*61046927SAndroid Build Coastguard Worker    device->shader_free_list.size_mask = 0;
1243*61046927SAndroid Build Coastguard Worker    device->capture_replay_free_list.size_mask = 0;
1244*61046927SAndroid Build Coastguard Worker 
1245*61046927SAndroid Build Coastguard Worker    list_inithead(&device->shader_arenas);
1246*61046927SAndroid Build Coastguard Worker    list_inithead(&device->shader_block_obj_pool);
1247*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < RADV_SHADER_ALLOC_NUM_FREE_LISTS; i++) {
1248*61046927SAndroid Build Coastguard Worker       list_inithead(&device->shader_free_list.free_lists[i]);
1249*61046927SAndroid Build Coastguard Worker       list_inithead(&device->capture_replay_free_list.free_lists[i]);
1250*61046927SAndroid Build Coastguard Worker    }
1251*61046927SAndroid Build Coastguard Worker }
1252*61046927SAndroid Build Coastguard Worker 
1253*61046927SAndroid Build Coastguard Worker void
radv_destroy_shader_arenas(struct radv_device * device)1254*61046927SAndroid Build Coastguard Worker radv_destroy_shader_arenas(struct radv_device *device)
1255*61046927SAndroid Build Coastguard Worker {
1256*61046927SAndroid Build Coastguard Worker    list_for_each_entry_safe (union radv_shader_arena_block, block, &device->shader_block_obj_pool, pool)
1257*61046927SAndroid Build Coastguard Worker       free(block);
1258*61046927SAndroid Build Coastguard Worker 
1259*61046927SAndroid Build Coastguard Worker    list_for_each_entry_safe (struct radv_shader_arena, arena, &device->shader_arenas, list) {
1260*61046927SAndroid Build Coastguard Worker       radv_bo_destroy(device, NULL, arena->bo);
1261*61046927SAndroid Build Coastguard Worker       free(arena);
1262*61046927SAndroid Build Coastguard Worker    }
1263*61046927SAndroid Build Coastguard Worker    mtx_destroy(&device->shader_arena_mutex);
1264*61046927SAndroid Build Coastguard Worker }
1265*61046927SAndroid Build Coastguard Worker 
1266*61046927SAndroid Build Coastguard Worker VkResult
radv_init_shader_upload_queue(struct radv_device * device)1267*61046927SAndroid Build Coastguard Worker radv_init_shader_upload_queue(struct radv_device *device)
1268*61046927SAndroid Build Coastguard Worker {
1269*61046927SAndroid Build Coastguard Worker    if (!device->shader_use_invisible_vram)
1270*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
1271*61046927SAndroid Build Coastguard Worker 
1272*61046927SAndroid Build Coastguard Worker    VkDevice vk_device = radv_device_to_handle(device);
1273*61046927SAndroid Build Coastguard Worker    struct radeon_winsys *ws = device->ws;
1274*61046927SAndroid Build Coastguard Worker 
1275*61046927SAndroid Build Coastguard Worker    const struct vk_device_dispatch_table *disp = &device->vk.dispatch_table;
1276*61046927SAndroid Build Coastguard Worker    VkResult result = VK_SUCCESS;
1277*61046927SAndroid Build Coastguard Worker 
1278*61046927SAndroid Build Coastguard Worker    result = ws->ctx_create(ws, RADEON_CTX_PRIORITY_MEDIUM, &device->shader_upload_hw_ctx);
1279*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
1280*61046927SAndroid Build Coastguard Worker       return result;
1281*61046927SAndroid Build Coastguard Worker    mtx_init(&device->shader_upload_hw_ctx_mutex, mtx_plain);
1282*61046927SAndroid Build Coastguard Worker 
1283*61046927SAndroid Build Coastguard Worker    mtx_init(&device->shader_dma_submission_list_mutex, mtx_plain);
1284*61046927SAndroid Build Coastguard Worker    cnd_init(&device->shader_dma_submission_list_cond);
1285*61046927SAndroid Build Coastguard Worker    list_inithead(&device->shader_dma_submissions);
1286*61046927SAndroid Build Coastguard Worker 
1287*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < RADV_SHADER_UPLOAD_CS_COUNT; i++) {
1288*61046927SAndroid Build Coastguard Worker       struct radv_shader_dma_submission *submission = calloc(1, sizeof(struct radv_shader_dma_submission));
1289*61046927SAndroid Build Coastguard Worker       submission->cs = ws->cs_create(ws, AMD_IP_SDMA, false);
1290*61046927SAndroid Build Coastguard Worker       if (!submission->cs)
1291*61046927SAndroid Build Coastguard Worker          return VK_ERROR_OUT_OF_DEVICE_MEMORY;
1292*61046927SAndroid Build Coastguard Worker       list_addtail(&submission->list, &device->shader_dma_submissions);
1293*61046927SAndroid Build Coastguard Worker    }
1294*61046927SAndroid Build Coastguard Worker 
1295*61046927SAndroid Build Coastguard Worker    const VkSemaphoreTypeCreateInfo sem_type = {
1296*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
1297*61046927SAndroid Build Coastguard Worker       .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
1298*61046927SAndroid Build Coastguard Worker       .initialValue = 0,
1299*61046927SAndroid Build Coastguard Worker    };
1300*61046927SAndroid Build Coastguard Worker    const VkSemaphoreCreateInfo sem_create = {
1301*61046927SAndroid Build Coastguard Worker       .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
1302*61046927SAndroid Build Coastguard Worker       .pNext = &sem_type,
1303*61046927SAndroid Build Coastguard Worker    };
1304*61046927SAndroid Build Coastguard Worker    result = disp->CreateSemaphore(vk_device, &sem_create, NULL, &device->shader_upload_sem);
1305*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
1306*61046927SAndroid Build Coastguard Worker       return result;
1307*61046927SAndroid Build Coastguard Worker 
1308*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1309*61046927SAndroid Build Coastguard Worker }
1310*61046927SAndroid Build Coastguard Worker 
1311*61046927SAndroid Build Coastguard Worker void
radv_destroy_shader_upload_queue(struct radv_device * device)1312*61046927SAndroid Build Coastguard Worker radv_destroy_shader_upload_queue(struct radv_device *device)
1313*61046927SAndroid Build Coastguard Worker {
1314*61046927SAndroid Build Coastguard Worker    if (!device->shader_use_invisible_vram)
1315*61046927SAndroid Build Coastguard Worker       return;
1316*61046927SAndroid Build Coastguard Worker 
1317*61046927SAndroid Build Coastguard Worker    struct vk_device_dispatch_table *disp = &device->vk.dispatch_table;
1318*61046927SAndroid Build Coastguard Worker    struct radeon_winsys *ws = device->ws;
1319*61046927SAndroid Build Coastguard Worker 
1320*61046927SAndroid Build Coastguard Worker    /* Upload queue should be idle assuming that pipelines are not leaked */
1321*61046927SAndroid Build Coastguard Worker    if (device->shader_upload_sem)
1322*61046927SAndroid Build Coastguard Worker       disp->DestroySemaphore(radv_device_to_handle(device), device->shader_upload_sem, NULL);
1323*61046927SAndroid Build Coastguard Worker 
1324*61046927SAndroid Build Coastguard Worker    list_for_each_entry_safe (struct radv_shader_dma_submission, submission, &device->shader_dma_submissions, list) {
1325*61046927SAndroid Build Coastguard Worker       if (submission->cs)
1326*61046927SAndroid Build Coastguard Worker          ws->cs_destroy(submission->cs);
1327*61046927SAndroid Build Coastguard Worker       if (submission->bo)
1328*61046927SAndroid Build Coastguard Worker          radv_bo_destroy(device, NULL, submission->bo);
1329*61046927SAndroid Build Coastguard Worker       list_del(&submission->list);
1330*61046927SAndroid Build Coastguard Worker       free(submission);
1331*61046927SAndroid Build Coastguard Worker    }
1332*61046927SAndroid Build Coastguard Worker 
1333*61046927SAndroid Build Coastguard Worker    cnd_destroy(&device->shader_dma_submission_list_cond);
1334*61046927SAndroid Build Coastguard Worker    mtx_destroy(&device->shader_dma_submission_list_mutex);
1335*61046927SAndroid Build Coastguard Worker 
1336*61046927SAndroid Build Coastguard Worker    if (device->shader_upload_hw_ctx) {
1337*61046927SAndroid Build Coastguard Worker       mtx_destroy(&device->shader_upload_hw_ctx_mutex);
1338*61046927SAndroid Build Coastguard Worker       ws->ctx_destroy(device->shader_upload_hw_ctx);
1339*61046927SAndroid Build Coastguard Worker    }
1340*61046927SAndroid Build Coastguard Worker }
1341*61046927SAndroid Build Coastguard Worker 
1342*61046927SAndroid Build Coastguard Worker static bool
radv_should_use_wgp_mode(const struct radv_device * device,gl_shader_stage stage,const struct radv_shader_info * info)1343*61046927SAndroid Build Coastguard Worker radv_should_use_wgp_mode(const struct radv_device *device, gl_shader_stage stage, const struct radv_shader_info *info)
1344*61046927SAndroid Build Coastguard Worker {
1345*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1346*61046927SAndroid Build Coastguard Worker    enum amd_gfx_level chip = pdev->info.gfx_level;
1347*61046927SAndroid Build Coastguard Worker    switch (stage) {
1348*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_COMPUTE:
1349*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_CTRL:
1350*61046927SAndroid Build Coastguard Worker       return chip >= GFX10;
1351*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_GEOMETRY:
1352*61046927SAndroid Build Coastguard Worker       return chip == GFX10 || (chip >= GFX10_3 && !info->is_ngg);
1353*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_VERTEX:
1354*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_EVAL:
1355*61046927SAndroid Build Coastguard Worker       return chip == GFX10 && info->is_ngg;
1356*61046927SAndroid Build Coastguard Worker    default:
1357*61046927SAndroid Build Coastguard Worker       return false;
1358*61046927SAndroid Build Coastguard Worker    }
1359*61046927SAndroid Build Coastguard Worker }
1360*61046927SAndroid Build Coastguard Worker 
1361*61046927SAndroid Build Coastguard Worker #if defined(USE_LIBELF)
1362*61046927SAndroid Build Coastguard Worker static bool
radv_open_rtld_binary(struct radv_device * device,const struct radv_shader_binary * binary,struct ac_rtld_binary * rtld_binary)1363*61046927SAndroid Build Coastguard Worker radv_open_rtld_binary(struct radv_device *device, const struct radv_shader_binary *binary,
1364*61046927SAndroid Build Coastguard Worker                       struct ac_rtld_binary *rtld_binary)
1365*61046927SAndroid Build Coastguard Worker {
1366*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1367*61046927SAndroid Build Coastguard Worker    const char *elf_data = (const char *)((struct radv_shader_binary_rtld *)binary)->data;
1368*61046927SAndroid Build Coastguard Worker    size_t elf_size = ((struct radv_shader_binary_rtld *)binary)->elf_size;
1369*61046927SAndroid Build Coastguard Worker    struct ac_rtld_symbol lds_symbols[3];
1370*61046927SAndroid Build Coastguard Worker    unsigned num_lds_symbols = 0;
1371*61046927SAndroid Build Coastguard Worker 
1372*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX9 && (binary->info.stage == MESA_SHADER_GEOMETRY || binary->info.is_ngg)) {
1373*61046927SAndroid Build Coastguard Worker       struct ac_rtld_symbol *sym = &lds_symbols[num_lds_symbols++];
1374*61046927SAndroid Build Coastguard Worker       sym->name = "esgs_ring";
1375*61046927SAndroid Build Coastguard Worker       sym->size = binary->info.ngg_info.esgs_ring_size;
1376*61046927SAndroid Build Coastguard Worker       sym->align = 64 * 1024;
1377*61046927SAndroid Build Coastguard Worker    }
1378*61046927SAndroid Build Coastguard Worker 
1379*61046927SAndroid Build Coastguard Worker    if (binary->info.is_ngg && binary->info.stage == MESA_SHADER_GEOMETRY) {
1380*61046927SAndroid Build Coastguard Worker       struct ac_rtld_symbol *sym = &lds_symbols[num_lds_symbols++];
1381*61046927SAndroid Build Coastguard Worker       sym->name = "ngg_emit";
1382*61046927SAndroid Build Coastguard Worker       sym->size = binary->info.ngg_info.ngg_emit_size * 4;
1383*61046927SAndroid Build Coastguard Worker       sym->align = 4;
1384*61046927SAndroid Build Coastguard Worker 
1385*61046927SAndroid Build Coastguard Worker       sym = &lds_symbols[num_lds_symbols++];
1386*61046927SAndroid Build Coastguard Worker       sym->name = "ngg_scratch";
1387*61046927SAndroid Build Coastguard Worker       sym->size = 8;
1388*61046927SAndroid Build Coastguard Worker       sym->align = 4;
1389*61046927SAndroid Build Coastguard Worker    }
1390*61046927SAndroid Build Coastguard Worker 
1391*61046927SAndroid Build Coastguard Worker    struct ac_rtld_open_info open_info = {
1392*61046927SAndroid Build Coastguard Worker       .info = &pdev->info,
1393*61046927SAndroid Build Coastguard Worker       .shader_type = binary->info.stage,
1394*61046927SAndroid Build Coastguard Worker       .wave_size = binary->info.wave_size,
1395*61046927SAndroid Build Coastguard Worker       .num_parts = 1,
1396*61046927SAndroid Build Coastguard Worker       .elf_ptrs = &elf_data,
1397*61046927SAndroid Build Coastguard Worker       .elf_sizes = &elf_size,
1398*61046927SAndroid Build Coastguard Worker       .num_shared_lds_symbols = num_lds_symbols,
1399*61046927SAndroid Build Coastguard Worker       .shared_lds_symbols = lds_symbols,
1400*61046927SAndroid Build Coastguard Worker    };
1401*61046927SAndroid Build Coastguard Worker 
1402*61046927SAndroid Build Coastguard Worker    return ac_rtld_open(rtld_binary, open_info);
1403*61046927SAndroid Build Coastguard Worker }
1404*61046927SAndroid Build Coastguard Worker #endif
1405*61046927SAndroid Build Coastguard Worker 
1406*61046927SAndroid Build Coastguard Worker static void
radv_precompute_registers_hw_vs(struct radv_device * device,struct radv_shader_binary * binary)1407*61046927SAndroid Build Coastguard Worker radv_precompute_registers_hw_vs(struct radv_device *device, struct radv_shader_binary *binary)
1408*61046927SAndroid Build Coastguard Worker {
1409*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1410*61046927SAndroid Build Coastguard Worker    struct radv_shader_info *info = &binary->info;
1411*61046927SAndroid Build Coastguard Worker 
1412*61046927SAndroid Build Coastguard Worker    /* VS is required to export at least one param. */
1413*61046927SAndroid Build Coastguard Worker    const uint32_t nparams = MAX2(info->outinfo.param_exports, 1);
1414*61046927SAndroid Build Coastguard Worker    info->regs.spi_vs_out_config = S_0286C4_VS_EXPORT_COUNT(nparams - 1);
1415*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX10) {
1416*61046927SAndroid Build Coastguard Worker       info->regs.spi_vs_out_config |= S_0286C4_NO_PC_EXPORT(info->outinfo.param_exports == 0);
1417*61046927SAndroid Build Coastguard Worker    }
1418*61046927SAndroid Build Coastguard Worker 
1419*61046927SAndroid Build Coastguard Worker    info->regs.spi_shader_pos_format =
1420*61046927SAndroid Build Coastguard Worker       S_02870C_POS0_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) |
1421*61046927SAndroid Build Coastguard Worker       S_02870C_POS1_EXPORT_FORMAT(info->outinfo.pos_exports > 1 ? V_02870C_SPI_SHADER_4COMP
1422*61046927SAndroid Build Coastguard Worker                                                                 : V_02870C_SPI_SHADER_NONE) |
1423*61046927SAndroid Build Coastguard Worker       S_02870C_POS2_EXPORT_FORMAT(info->outinfo.pos_exports > 2 ? V_02870C_SPI_SHADER_4COMP
1424*61046927SAndroid Build Coastguard Worker                                                                 : V_02870C_SPI_SHADER_NONE) |
1425*61046927SAndroid Build Coastguard Worker       S_02870C_POS3_EXPORT_FORMAT(info->outinfo.pos_exports > 3 ? V_02870C_SPI_SHADER_4COMP : V_02870C_SPI_SHADER_NONE);
1426*61046927SAndroid Build Coastguard Worker 
1427*61046927SAndroid Build Coastguard Worker    const bool misc_vec_ena = info->outinfo.writes_pointsize || info->outinfo.writes_layer ||
1428*61046927SAndroid Build Coastguard Worker                              info->outinfo.writes_viewport_index || info->outinfo.writes_primitive_shading_rate;
1429*61046927SAndroid Build Coastguard Worker    const unsigned clip_dist_mask = info->outinfo.clip_dist_mask;
1430*61046927SAndroid Build Coastguard Worker    const unsigned cull_dist_mask = info->outinfo.cull_dist_mask;
1431*61046927SAndroid Build Coastguard Worker    const unsigned total_mask = clip_dist_mask | cull_dist_mask;
1432*61046927SAndroid Build Coastguard Worker 
1433*61046927SAndroid Build Coastguard Worker    info->regs.pa_cl_vs_out_cntl =
1434*61046927SAndroid Build Coastguard Worker       S_02881C_USE_VTX_POINT_SIZE(info->outinfo.writes_pointsize) |
1435*61046927SAndroid Build Coastguard Worker       S_02881C_USE_VTX_RENDER_TARGET_INDX(info->outinfo.writes_layer) |
1436*61046927SAndroid Build Coastguard Worker       S_02881C_USE_VTX_VIEWPORT_INDX(info->outinfo.writes_viewport_index) |
1437*61046927SAndroid Build Coastguard Worker       S_02881C_USE_VTX_VRS_RATE(info->outinfo.writes_primitive_shading_rate) |
1438*61046927SAndroid Build Coastguard Worker       S_02881C_VS_OUT_MISC_VEC_ENA(misc_vec_ena) |
1439*61046927SAndroid Build Coastguard Worker       S_02881C_VS_OUT_MISC_SIDE_BUS_ENA(misc_vec_ena ||
1440*61046927SAndroid Build Coastguard Worker                                         (pdev->info.gfx_level >= GFX10_3 && info->outinfo.pos_exports > 1)) |
1441*61046927SAndroid Build Coastguard Worker       S_02881C_VS_OUT_CCDIST0_VEC_ENA((total_mask & 0x0f) != 0) |
1442*61046927SAndroid Build Coastguard Worker       S_02881C_VS_OUT_CCDIST1_VEC_ENA((total_mask & 0xf0) != 0) | total_mask << 8 | clip_dist_mask;
1443*61046927SAndroid Build Coastguard Worker 
1444*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level <= GFX8)
1445*61046927SAndroid Build Coastguard Worker       info->regs.vs.vgt_reuse_off = info->outinfo.writes_viewport_index;
1446*61046927SAndroid Build Coastguard Worker 
1447*61046927SAndroid Build Coastguard Worker    unsigned late_alloc_wave64, cu_mask;
1448*61046927SAndroid Build Coastguard Worker    ac_compute_late_alloc(&pdev->info, false, false, binary->config.scratch_bytes_per_wave > 0, &late_alloc_wave64,
1449*61046927SAndroid Build Coastguard Worker                          &cu_mask);
1450*61046927SAndroid Build Coastguard Worker 
1451*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX7) {
1452*61046927SAndroid Build Coastguard Worker       info->regs.vs.spi_shader_pgm_rsrc3_vs =
1453*61046927SAndroid Build Coastguard Worker          ac_apply_cu_en(S_00B118_CU_EN(cu_mask) | S_00B118_WAVE_LIMIT(0x3F), C_00B118_CU_EN, 0, &pdev->info);
1454*61046927SAndroid Build Coastguard Worker       info->regs.vs.spi_shader_late_alloc_vs = S_00B11C_LIMIT(late_alloc_wave64);
1455*61046927SAndroid Build Coastguard Worker 
1456*61046927SAndroid Build Coastguard Worker       if (pdev->info.gfx_level >= GFX10) {
1457*61046927SAndroid Build Coastguard Worker          const uint32_t oversub_pc_lines = late_alloc_wave64 ? pdev->info.pc_lines / 4 : 0;
1458*61046927SAndroid Build Coastguard Worker 
1459*61046927SAndroid Build Coastguard Worker          info->regs.ge_pc_alloc =
1460*61046927SAndroid Build Coastguard Worker             S_030980_OVERSUB_EN(oversub_pc_lines > 0) | S_030980_NUM_PC_LINES(oversub_pc_lines - 1);
1461*61046927SAndroid Build Coastguard Worker 
1462*61046927SAndroid Build Coastguard Worker          /* Required programming for tessellation (legacy pipeline only). */
1463*61046927SAndroid Build Coastguard Worker          if (binary->info.stage == MESA_SHADER_TESS_EVAL) {
1464*61046927SAndroid Build Coastguard Worker             info->regs.vgt_gs_onchip_cntl = S_028A44_ES_VERTS_PER_SUBGRP(250) | S_028A44_GS_PRIMS_PER_SUBGRP(126) |
1465*61046927SAndroid Build Coastguard Worker                                             S_028A44_GS_INST_PRIMS_IN_SUBGRP(126);
1466*61046927SAndroid Build Coastguard Worker          }
1467*61046927SAndroid Build Coastguard Worker       }
1468*61046927SAndroid Build Coastguard Worker    }
1469*61046927SAndroid Build Coastguard Worker }
1470*61046927SAndroid Build Coastguard Worker 
1471*61046927SAndroid Build Coastguard Worker static void
radv_precompute_registers_hw_gs(struct radv_device * device,struct radv_shader_binary * binary)1472*61046927SAndroid Build Coastguard Worker radv_precompute_registers_hw_gs(struct radv_device *device, struct radv_shader_binary *binary)
1473*61046927SAndroid Build Coastguard Worker {
1474*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1475*61046927SAndroid Build Coastguard Worker    struct radv_shader_info *info = &binary->info;
1476*61046927SAndroid Build Coastguard Worker 
1477*61046927SAndroid Build Coastguard Worker    info->regs.gs.vgt_esgs_ring_itemsize = info->gs_ring_info.esgs_itemsize;
1478*61046927SAndroid Build Coastguard Worker 
1479*61046927SAndroid Build Coastguard Worker    info->regs.gs.vgt_gs_max_prims_per_subgroup =
1480*61046927SAndroid Build Coastguard Worker       S_028A94_MAX_PRIMS_PER_SUBGROUP(info->gs_ring_info.gs_inst_prims_in_subgroup);
1481*61046927SAndroid Build Coastguard Worker 
1482*61046927SAndroid Build Coastguard Worker    info->regs.vgt_gs_onchip_cntl = S_028A44_ES_VERTS_PER_SUBGRP(info->gs_ring_info.es_verts_per_subgroup) |
1483*61046927SAndroid Build Coastguard Worker                                    S_028A44_GS_PRIMS_PER_SUBGRP(info->gs_ring_info.gs_prims_per_subgroup) |
1484*61046927SAndroid Build Coastguard Worker                                    S_028A44_GS_INST_PRIMS_IN_SUBGRP(info->gs_ring_info.gs_inst_prims_in_subgroup);
1485*61046927SAndroid Build Coastguard Worker 
1486*61046927SAndroid Build Coastguard Worker    const uint32_t gs_max_out_vertices = info->gs.vertices_out;
1487*61046927SAndroid Build Coastguard Worker    const uint8_t max_stream = info->gs.max_stream;
1488*61046927SAndroid Build Coastguard Worker    const uint8_t *num_components = info->gs.num_stream_output_components;
1489*61046927SAndroid Build Coastguard Worker 
1490*61046927SAndroid Build Coastguard Worker    uint32_t offset = num_components[0] * gs_max_out_vertices;
1491*61046927SAndroid Build Coastguard Worker    info->regs.gs.vgt_gsvs_ring_offset[0] = offset;
1492*61046927SAndroid Build Coastguard Worker 
1493*61046927SAndroid Build Coastguard Worker    if (max_stream >= 1)
1494*61046927SAndroid Build Coastguard Worker       offset += num_components[1] * gs_max_out_vertices;
1495*61046927SAndroid Build Coastguard Worker    info->regs.gs.vgt_gsvs_ring_offset[1] = offset;
1496*61046927SAndroid Build Coastguard Worker 
1497*61046927SAndroid Build Coastguard Worker    if (max_stream >= 2)
1498*61046927SAndroid Build Coastguard Worker       offset += num_components[2] * gs_max_out_vertices;
1499*61046927SAndroid Build Coastguard Worker    info->regs.gs.vgt_gsvs_ring_offset[2] = offset;
1500*61046927SAndroid Build Coastguard Worker 
1501*61046927SAndroid Build Coastguard Worker    if (max_stream >= 3)
1502*61046927SAndroid Build Coastguard Worker       offset += num_components[3] * gs_max_out_vertices;
1503*61046927SAndroid Build Coastguard Worker    info->regs.gs.vgt_gsvs_ring_itemsize = offset;
1504*61046927SAndroid Build Coastguard Worker 
1505*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < 4; i++)
1506*61046927SAndroid Build Coastguard Worker       info->regs.gs.vgt_gs_vert_itemsize[i] = (max_stream >= i) ? num_components[i] : 0;
1507*61046927SAndroid Build Coastguard Worker 
1508*61046927SAndroid Build Coastguard Worker    const uint32_t gs_num_invocations = info->gs.invocations;
1509*61046927SAndroid Build Coastguard Worker    info->regs.gs.vgt_gs_instance_cnt =
1510*61046927SAndroid Build Coastguard Worker       S_028B90_CNT(MIN2(gs_num_invocations, 127)) | S_028B90_ENABLE(gs_num_invocations > 0);
1511*61046927SAndroid Build Coastguard Worker 
1512*61046927SAndroid Build Coastguard Worker    info->regs.spi_shader_pgm_rsrc3_gs =
1513*61046927SAndroid Build Coastguard Worker       ac_apply_cu_en(S_00B21C_CU_EN(0xffff) | S_00B21C_WAVE_LIMIT(0x3F), C_00B21C_CU_EN, 0, &pdev->info);
1514*61046927SAndroid Build Coastguard Worker 
1515*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX10) {
1516*61046927SAndroid Build Coastguard Worker       info->regs.spi_shader_pgm_rsrc4_gs =
1517*61046927SAndroid Build Coastguard Worker          ac_apply_cu_en(S_00B204_CU_EN_GFX10(0xffff) | S_00B204_SPI_SHADER_LATE_ALLOC_GS_GFX10(0), C_00B204_CU_EN_GFX10,
1518*61046927SAndroid Build Coastguard Worker                         16, &pdev->info);
1519*61046927SAndroid Build Coastguard Worker    }
1520*61046927SAndroid Build Coastguard Worker 
1521*61046927SAndroid Build Coastguard Worker    info->regs.vgt_gs_max_vert_out = info->gs.vertices_out;
1522*61046927SAndroid Build Coastguard Worker }
1523*61046927SAndroid Build Coastguard Worker 
1524*61046927SAndroid Build Coastguard Worker void
radv_precompute_registers_hw_ngg(struct radv_device * device,const struct ac_shader_config * config,struct radv_shader_info * info)1525*61046927SAndroid Build Coastguard Worker radv_precompute_registers_hw_ngg(struct radv_device *device, const struct ac_shader_config *config,
1526*61046927SAndroid Build Coastguard Worker                                  struct radv_shader_info *info)
1527*61046927SAndroid Build Coastguard Worker {
1528*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1529*61046927SAndroid Build Coastguard Worker 
1530*61046927SAndroid Build Coastguard Worker    const bool no_pc_export = info->outinfo.param_exports == 0 && info->outinfo.prim_param_exports == 0;
1531*61046927SAndroid Build Coastguard Worker    const unsigned num_prim_params = info->outinfo.prim_param_exports;
1532*61046927SAndroid Build Coastguard Worker 
1533*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX12) {
1534*61046927SAndroid Build Coastguard Worker       unsigned num_params = info->outinfo.param_exports;
1535*61046927SAndroid Build Coastguard Worker 
1536*61046927SAndroid Build Coastguard Worker       /* Since there is no alloc/dealloc mechanism for the 12-bit ordered IDs, they can wrap
1537*61046927SAndroid Build Coastguard Worker        * around if there are more than 2^12 workgroups, causing 2 workgroups to get the same
1538*61046927SAndroid Build Coastguard Worker        * ordered ID, which would break the streamout algorithm.
1539*61046927SAndroid Build Coastguard Worker        * The recommended solution is to use the alloc/dealloc mechanism of the attribute ring,
1540*61046927SAndroid Build Coastguard Worker        * which is enough to limit the range of ordered IDs that can be in flight.
1541*61046927SAndroid Build Coastguard Worker        */
1542*61046927SAndroid Build Coastguard Worker       if (info->so.num_outputs) {
1543*61046927SAndroid Build Coastguard Worker          num_params = MAX2(num_params, 8);
1544*61046927SAndroid Build Coastguard Worker       } else {
1545*61046927SAndroid Build Coastguard Worker          num_params = MAX2(num_params, 1);
1546*61046927SAndroid Build Coastguard Worker       }
1547*61046927SAndroid Build Coastguard Worker 
1548*61046927SAndroid Build Coastguard Worker       info->regs.spi_vs_out_config = S_00B0C4_VS_EXPORT_COUNT(num_params - 1) |
1549*61046927SAndroid Build Coastguard Worker                                      S_00B0C4_PRIM_EXPORT_COUNT(num_prim_params) | S_00B0C4_NO_PC_EXPORT(no_pc_export);
1550*61046927SAndroid Build Coastguard Worker 
1551*61046927SAndroid Build Coastguard Worker       info->regs.spi_shader_pgm_rsrc4_gs =
1552*61046927SAndroid Build Coastguard Worker          S_00B220_SPI_SHADER_LATE_ALLOC_GS(127) | S_00B220_GLG_FORCE_DISABLE(1) | S_00B220_WAVE_LIMIT(0x3ff);
1553*61046927SAndroid Build Coastguard Worker    } else {
1554*61046927SAndroid Build Coastguard Worker       const unsigned num_params = MAX2(info->outinfo.param_exports, 1);
1555*61046927SAndroid Build Coastguard Worker 
1556*61046927SAndroid Build Coastguard Worker       info->regs.spi_vs_out_config = S_0286C4_VS_EXPORT_COUNT(num_params - 1) |
1557*61046927SAndroid Build Coastguard Worker                                      S_0286C4_PRIM_EXPORT_COUNT(num_prim_params) | S_0286C4_NO_PC_EXPORT(no_pc_export);
1558*61046927SAndroid Build Coastguard Worker 
1559*61046927SAndroid Build Coastguard Worker       unsigned late_alloc_wave64, cu_mask;
1560*61046927SAndroid Build Coastguard Worker       ac_compute_late_alloc(&pdev->info, true, info->has_ngg_culling, config->scratch_bytes_per_wave > 0,
1561*61046927SAndroid Build Coastguard Worker                             &late_alloc_wave64, &cu_mask);
1562*61046927SAndroid Build Coastguard Worker 
1563*61046927SAndroid Build Coastguard Worker       info->regs.spi_shader_pgm_rsrc3_gs =
1564*61046927SAndroid Build Coastguard Worker          ac_apply_cu_en(S_00B21C_CU_EN(cu_mask) | S_00B21C_WAVE_LIMIT(0x3F), C_00B21C_CU_EN, 0, &pdev->info);
1565*61046927SAndroid Build Coastguard Worker 
1566*61046927SAndroid Build Coastguard Worker       if (pdev->info.gfx_level >= GFX11) {
1567*61046927SAndroid Build Coastguard Worker          info->regs.spi_shader_pgm_rsrc4_gs =
1568*61046927SAndroid Build Coastguard Worker             ac_apply_cu_en(S_00B204_CU_EN_GFX11(0x1) | S_00B204_SPI_SHADER_LATE_ALLOC_GS_GFX10(late_alloc_wave64),
1569*61046927SAndroid Build Coastguard Worker                            C_00B204_CU_EN_GFX11, 16, &pdev->info);
1570*61046927SAndroid Build Coastguard Worker       } else {
1571*61046927SAndroid Build Coastguard Worker          info->regs.spi_shader_pgm_rsrc4_gs =
1572*61046927SAndroid Build Coastguard Worker             ac_apply_cu_en(S_00B204_CU_EN_GFX10(0xffff) | S_00B204_SPI_SHADER_LATE_ALLOC_GS_GFX10(late_alloc_wave64),
1573*61046927SAndroid Build Coastguard Worker                            C_00B204_CU_EN_GFX10, 16, &pdev->info);
1574*61046927SAndroid Build Coastguard Worker       }
1575*61046927SAndroid Build Coastguard Worker 
1576*61046927SAndroid Build Coastguard Worker       uint32_t oversub_pc_lines = late_alloc_wave64 ? pdev->info.pc_lines / 4 : 0;
1577*61046927SAndroid Build Coastguard Worker       if (info->has_ngg_culling) {
1578*61046927SAndroid Build Coastguard Worker          unsigned oversub_factor = 2;
1579*61046927SAndroid Build Coastguard Worker 
1580*61046927SAndroid Build Coastguard Worker          if (info->outinfo.param_exports > 4)
1581*61046927SAndroid Build Coastguard Worker             oversub_factor = 4;
1582*61046927SAndroid Build Coastguard Worker          else if (info->outinfo.param_exports > 2)
1583*61046927SAndroid Build Coastguard Worker             oversub_factor = 3;
1584*61046927SAndroid Build Coastguard Worker 
1585*61046927SAndroid Build Coastguard Worker          oversub_pc_lines *= oversub_factor;
1586*61046927SAndroid Build Coastguard Worker       }
1587*61046927SAndroid Build Coastguard Worker 
1588*61046927SAndroid Build Coastguard Worker       info->regs.ge_pc_alloc = S_030980_OVERSUB_EN(oversub_pc_lines > 0) | S_030980_NUM_PC_LINES(oversub_pc_lines - 1);
1589*61046927SAndroid Build Coastguard Worker    }
1590*61046927SAndroid Build Coastguard Worker 
1591*61046927SAndroid Build Coastguard Worker    unsigned idx_format = V_028708_SPI_SHADER_1COMP;
1592*61046927SAndroid Build Coastguard Worker    if (info->outinfo.writes_layer_per_primitive || info->outinfo.writes_viewport_index_per_primitive ||
1593*61046927SAndroid Build Coastguard Worker        info->outinfo.writes_primitive_shading_rate_per_primitive)
1594*61046927SAndroid Build Coastguard Worker       idx_format = V_028708_SPI_SHADER_2COMP;
1595*61046927SAndroid Build Coastguard Worker 
1596*61046927SAndroid Build Coastguard Worker    info->regs.ngg.spi_shader_idx_format = S_028708_IDX0_EXPORT_FORMAT(idx_format);
1597*61046927SAndroid Build Coastguard Worker 
1598*61046927SAndroid Build Coastguard Worker    info->regs.spi_shader_pos_format =
1599*61046927SAndroid Build Coastguard Worker       S_02870C_POS0_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) |
1600*61046927SAndroid Build Coastguard Worker       S_02870C_POS1_EXPORT_FORMAT(info->outinfo.pos_exports > 1 ? V_02870C_SPI_SHADER_4COMP
1601*61046927SAndroid Build Coastguard Worker                                                                 : V_02870C_SPI_SHADER_NONE) |
1602*61046927SAndroid Build Coastguard Worker       S_02870C_POS2_EXPORT_FORMAT(info->outinfo.pos_exports > 2 ? V_02870C_SPI_SHADER_4COMP
1603*61046927SAndroid Build Coastguard Worker                                                                 : V_02870C_SPI_SHADER_NONE) |
1604*61046927SAndroid Build Coastguard Worker       S_02870C_POS3_EXPORT_FORMAT(info->outinfo.pos_exports > 3 ? V_02870C_SPI_SHADER_4COMP : V_02870C_SPI_SHADER_NONE);
1605*61046927SAndroid Build Coastguard Worker 
1606*61046927SAndroid Build Coastguard Worker    const bool misc_vec_ena = info->outinfo.writes_pointsize || info->outinfo.writes_layer ||
1607*61046927SAndroid Build Coastguard Worker                              info->outinfo.writes_viewport_index || info->outinfo.writes_primitive_shading_rate;
1608*61046927SAndroid Build Coastguard Worker    const unsigned clip_dist_mask = info->outinfo.clip_dist_mask;
1609*61046927SAndroid Build Coastguard Worker    const unsigned cull_dist_mask = info->outinfo.cull_dist_mask;
1610*61046927SAndroid Build Coastguard Worker    const unsigned total_mask = clip_dist_mask | cull_dist_mask;
1611*61046927SAndroid Build Coastguard Worker 
1612*61046927SAndroid Build Coastguard Worker    info->regs.pa_cl_vs_out_cntl =
1613*61046927SAndroid Build Coastguard Worker       S_02881C_USE_VTX_POINT_SIZE(info->outinfo.writes_pointsize) |
1614*61046927SAndroid Build Coastguard Worker       S_02881C_USE_VTX_RENDER_TARGET_INDX(info->outinfo.writes_layer) |
1615*61046927SAndroid Build Coastguard Worker       S_02881C_USE_VTX_VIEWPORT_INDX(info->outinfo.writes_viewport_index) |
1616*61046927SAndroid Build Coastguard Worker       S_02881C_USE_VTX_VRS_RATE(info->outinfo.writes_primitive_shading_rate) |
1617*61046927SAndroid Build Coastguard Worker       S_02881C_VS_OUT_MISC_VEC_ENA(misc_vec_ena) |
1618*61046927SAndroid Build Coastguard Worker       S_02881C_VS_OUT_MISC_SIDE_BUS_ENA(misc_vec_ena ||
1619*61046927SAndroid Build Coastguard Worker                                         (pdev->info.gfx_level >= GFX10_3 && info->outinfo.pos_exports > 1)) |
1620*61046927SAndroid Build Coastguard Worker       S_02881C_VS_OUT_CCDIST0_VEC_ENA((total_mask & 0x0f) != 0) |
1621*61046927SAndroid Build Coastguard Worker       S_02881C_VS_OUT_CCDIST1_VEC_ENA((total_mask & 0xf0) != 0) | total_mask << 8 | clip_dist_mask;
1622*61046927SAndroid Build Coastguard Worker 
1623*61046927SAndroid Build Coastguard Worker    info->regs.ngg.vgt_primitiveid_en = S_028A84_NGG_DISABLE_PROVOK_REUSE(info->outinfo.export_prim_id);
1624*61046927SAndroid Build Coastguard Worker 
1625*61046927SAndroid Build Coastguard Worker    const uint32_t gs_num_invocations = info->stage == MESA_SHADER_GEOMETRY ? info->gs.invocations : 1;
1626*61046927SAndroid Build Coastguard Worker 
1627*61046927SAndroid Build Coastguard Worker    info->regs.ngg.ge_max_output_per_subgroup = S_0287FC_MAX_VERTS_PER_SUBGROUP(info->ngg_info.max_out_verts);
1628*61046927SAndroid Build Coastguard Worker 
1629*61046927SAndroid Build Coastguard Worker    info->regs.ngg.ge_ngg_subgrp_cntl =
1630*61046927SAndroid Build Coastguard Worker       S_028B4C_PRIM_AMP_FACTOR(info->ngg_info.prim_amp_factor) | S_028B4C_THDS_PER_SUBGRP(0); /* for fast launch */
1631*61046927SAndroid Build Coastguard Worker 
1632*61046927SAndroid Build Coastguard Worker    info->regs.vgt_gs_instance_cnt =
1633*61046927SAndroid Build Coastguard Worker       S_028B90_CNT(gs_num_invocations) | S_028B90_ENABLE(gs_num_invocations > 1) |
1634*61046927SAndroid Build Coastguard Worker       S_028B90_EN_MAX_VERT_OUT_PER_GS_INSTANCE(info->ngg_info.max_vert_out_per_gs_instance);
1635*61046927SAndroid Build Coastguard Worker 
1636*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX11) {
1637*61046927SAndroid Build Coastguard Worker       /* This should be <= 252 for performance on Gfx11. 256 works too but is slower. */
1638*61046927SAndroid Build Coastguard Worker       const uint32_t max_prim_grp_size = pdev->info.gfx_level >= GFX12 ? 256 : 252;
1639*61046927SAndroid Build Coastguard Worker 
1640*61046927SAndroid Build Coastguard Worker       info->regs.ngg.ge_cntl = S_03096C_PRIMS_PER_SUBGRP(info->ngg_info.max_gsprims) |
1641*61046927SAndroid Build Coastguard Worker                                S_03096C_VERTS_PER_SUBGRP(info->ngg_info.hw_max_esverts) |
1642*61046927SAndroid Build Coastguard Worker                                S_03096C_PRIM_GRP_SIZE_GFX11(max_prim_grp_size) |
1643*61046927SAndroid Build Coastguard Worker                                S_03096C_DIS_PG_SIZE_ADJUST_FOR_STRIP(pdev->info.gfx_level >= GFX12);
1644*61046927SAndroid Build Coastguard Worker    } else {
1645*61046927SAndroid Build Coastguard Worker       info->regs.ngg.ge_cntl = S_03096C_PRIM_GRP_SIZE_GFX10(info->ngg_info.max_gsprims) |
1646*61046927SAndroid Build Coastguard Worker                                S_03096C_VERT_GRP_SIZE(info->ngg_info.hw_max_esverts);
1647*61046927SAndroid Build Coastguard Worker 
1648*61046927SAndroid Build Coastguard Worker       info->regs.vgt_gs_onchip_cntl = S_028A44_ES_VERTS_PER_SUBGRP(info->ngg_info.hw_max_esverts) |
1649*61046927SAndroid Build Coastguard Worker                                       S_028A44_GS_PRIMS_PER_SUBGRP(info->ngg_info.max_gsprims) |
1650*61046927SAndroid Build Coastguard Worker                                       S_028A44_GS_INST_PRIMS_IN_SUBGRP(info->ngg_info.max_gsprims * gs_num_invocations);
1651*61046927SAndroid Build Coastguard Worker    }
1652*61046927SAndroid Build Coastguard Worker 
1653*61046927SAndroid Build Coastguard Worker 
1654*61046927SAndroid Build Coastguard Worker    info->regs.vgt_gs_max_vert_out = info->gs.vertices_out;
1655*61046927SAndroid Build Coastguard Worker }
1656*61046927SAndroid Build Coastguard Worker 
1657*61046927SAndroid Build Coastguard Worker static void
radv_precompute_registers_hw_ms(struct radv_device * device,struct radv_shader_binary * binary)1658*61046927SAndroid Build Coastguard Worker radv_precompute_registers_hw_ms(struct radv_device *device, struct radv_shader_binary *binary)
1659*61046927SAndroid Build Coastguard Worker {
1660*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1661*61046927SAndroid Build Coastguard Worker    struct radv_shader_info *info = &binary->info;
1662*61046927SAndroid Build Coastguard Worker 
1663*61046927SAndroid Build Coastguard Worker    radv_precompute_registers_hw_ngg(device, &binary->config, &binary->info);
1664*61046927SAndroid Build Coastguard Worker 
1665*61046927SAndroid Build Coastguard Worker    info->regs.vgt_gs_max_vert_out = pdev->mesh_fast_launch_2 ? info->ngg_info.max_out_verts : info->workgroup_size;
1666*61046927SAndroid Build Coastguard Worker 
1667*61046927SAndroid Build Coastguard Worker    info->regs.ms.spi_shader_gs_meshlet_dim = S_00B2B0_MESHLET_NUM_THREAD_X(info->cs.block_size[0] - 1) |
1668*61046927SAndroid Build Coastguard Worker                                              S_00B2B0_MESHLET_NUM_THREAD_Y(info->cs.block_size[1] - 1) |
1669*61046927SAndroid Build Coastguard Worker                                              S_00B2B0_MESHLET_NUM_THREAD_Z(info->cs.block_size[2] - 1) |
1670*61046927SAndroid Build Coastguard Worker                                              S_00B2B0_MESHLET_THREADGROUP_SIZE(info->workgroup_size - 1);
1671*61046927SAndroid Build Coastguard Worker 
1672*61046927SAndroid Build Coastguard Worker    info->regs.ms.spi_shader_gs_meshlet_exp_alloc =
1673*61046927SAndroid Build Coastguard Worker       S_00B2B4_MAX_EXP_VERTS(info->ngg_info.max_out_verts) | S_00B2B4_MAX_EXP_PRIMS(info->ngg_info.prim_amp_factor);
1674*61046927SAndroid Build Coastguard Worker }
1675*61046927SAndroid Build Coastguard Worker 
1676*61046927SAndroid Build Coastguard Worker static void
radv_precompute_registers_hw_fs(struct radv_device * device,struct radv_shader_binary * binary)1677*61046927SAndroid Build Coastguard Worker radv_precompute_registers_hw_fs(struct radv_device *device, struct radv_shader_binary *binary)
1678*61046927SAndroid Build Coastguard Worker {
1679*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1680*61046927SAndroid Build Coastguard Worker    struct radv_shader_info *info = &binary->info;
1681*61046927SAndroid Build Coastguard Worker 
1682*61046927SAndroid Build Coastguard Worker    unsigned conservative_z_export = V_02880C_EXPORT_ANY_Z;
1683*61046927SAndroid Build Coastguard Worker    if (info->ps.depth_layout == FRAG_DEPTH_LAYOUT_GREATER)
1684*61046927SAndroid Build Coastguard Worker       conservative_z_export = V_02880C_EXPORT_GREATER_THAN_Z;
1685*61046927SAndroid Build Coastguard Worker    else if (info->ps.depth_layout == FRAG_DEPTH_LAYOUT_LESS)
1686*61046927SAndroid Build Coastguard Worker       conservative_z_export = V_02880C_EXPORT_LESS_THAN_Z;
1687*61046927SAndroid Build Coastguard Worker 
1688*61046927SAndroid Build Coastguard Worker    const unsigned z_order =
1689*61046927SAndroid Build Coastguard Worker       info->ps.early_fragment_test || !info->ps.writes_memory ? V_02880C_EARLY_Z_THEN_LATE_Z : V_02880C_LATE_Z;
1690*61046927SAndroid Build Coastguard Worker 
1691*61046927SAndroid Build Coastguard Worker    /* It shouldn't be needed to export gl_SampleMask when MSAA is disabled, but this appears to break Project Cars
1692*61046927SAndroid Build Coastguard Worker     * (DXVK). See https://bugs.freedesktop.org/show_bug.cgi?id=109401
1693*61046927SAndroid Build Coastguard Worker     */
1694*61046927SAndroid Build Coastguard Worker    const bool mask_export_enable = info->ps.writes_sample_mask;
1695*61046927SAndroid Build Coastguard Worker    const bool disable_rbplus = pdev->info.has_rbplus && !pdev->info.rbplus_allowed;
1696*61046927SAndroid Build Coastguard Worker 
1697*61046927SAndroid Build Coastguard Worker    info->regs.ps.db_shader_control =
1698*61046927SAndroid Build Coastguard Worker       S_02880C_Z_EXPORT_ENABLE(info->ps.writes_z) | S_02880C_STENCIL_TEST_VAL_EXPORT_ENABLE(info->ps.writes_stencil) |
1699*61046927SAndroid Build Coastguard Worker       S_02880C_KILL_ENABLE(info->ps.can_discard) | S_02880C_MASK_EXPORT_ENABLE(mask_export_enable) |
1700*61046927SAndroid Build Coastguard Worker       S_02880C_CONSERVATIVE_Z_EXPORT(conservative_z_export) | S_02880C_Z_ORDER(z_order) |
1701*61046927SAndroid Build Coastguard Worker       S_02880C_DEPTH_BEFORE_SHADER(info->ps.early_fragment_test) |
1702*61046927SAndroid Build Coastguard Worker       S_02880C_PRE_SHADER_DEPTH_COVERAGE_ENABLE(info->ps.post_depth_coverage) |
1703*61046927SAndroid Build Coastguard Worker       S_02880C_EXEC_ON_HIER_FAIL(info->ps.writes_memory) | S_02880C_EXEC_ON_NOOP(info->ps.writes_memory) |
1704*61046927SAndroid Build Coastguard Worker       S_02880C_DUAL_QUAD_DISABLE(disable_rbplus) | S_02880C_PRIMITIVE_ORDERED_PIXEL_SHADER(info->ps.pops);
1705*61046927SAndroid Build Coastguard Worker 
1706*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX12) {
1707*61046927SAndroid Build Coastguard Worker       info->regs.ps.spi_ps_in_control = S_028640_PS_W32_EN(info->wave_size == 32);
1708*61046927SAndroid Build Coastguard Worker       info->regs.ps.spi_gs_out_config_ps = S_00B0C4_NUM_INTERP(info->ps.num_interp);
1709*61046927SAndroid Build Coastguard Worker 
1710*61046927SAndroid Build Coastguard Worker       info->regs.ps.pa_sc_hisz_control = S_028BBC_ROUND(2); /* required minimum value */
1711*61046927SAndroid Build Coastguard Worker       if (info->ps.depth_layout == FRAG_DEPTH_LAYOUT_GREATER)
1712*61046927SAndroid Build Coastguard Worker          info->regs.ps.pa_sc_hisz_control |= S_028BBC_CONSERVATIVE_Z_EXPORT(V_028BBC_EXPORT_GREATER_THAN_Z);
1713*61046927SAndroid Build Coastguard Worker       else if (info->ps.depth_layout == FRAG_DEPTH_LAYOUT_LESS)
1714*61046927SAndroid Build Coastguard Worker          info->regs.ps.pa_sc_hisz_control |= S_028BBC_CONSERVATIVE_Z_EXPORT(V_028BBC_EXPORT_LESS_THAN_Z);
1715*61046927SAndroid Build Coastguard Worker    } else {
1716*61046927SAndroid Build Coastguard Worker       /* GFX11 workaround when there are no PS inputs but LDS is used. */
1717*61046927SAndroid Build Coastguard Worker       const bool param_gen = pdev->info.gfx_level == GFX11 && !info->ps.num_interp && binary->config.lds_size;
1718*61046927SAndroid Build Coastguard Worker 
1719*61046927SAndroid Build Coastguard Worker       info->regs.ps.spi_ps_in_control = S_0286D8_NUM_INTERP(info->ps.num_interp) |
1720*61046927SAndroid Build Coastguard Worker                                         S_0286D8_NUM_PRIM_INTERP(info->ps.num_prim_interp) |
1721*61046927SAndroid Build Coastguard Worker                                         S_0286D8_PS_W32_EN(info->wave_size == 32) | S_0286D8_PARAM_GEN(param_gen);
1722*61046927SAndroid Build Coastguard Worker 
1723*61046927SAndroid Build Coastguard Worker       if (pdev->info.gfx_level >= GFX9 && pdev->info.gfx_level < GFX11)
1724*61046927SAndroid Build Coastguard Worker          info->regs.ps.pa_sc_shader_control = S_028C40_LOAD_COLLISION_WAVEID(info->ps.pops);
1725*61046927SAndroid Build Coastguard Worker    }
1726*61046927SAndroid Build Coastguard Worker 
1727*61046927SAndroid Build Coastguard Worker    info->regs.ps.spi_shader_z_format = ac_get_spi_shader_z_format(
1728*61046927SAndroid Build Coastguard Worker       info->ps.writes_z, info->ps.writes_stencil, info->ps.writes_sample_mask, info->ps.writes_mrt0_alpha);
1729*61046927SAndroid Build Coastguard Worker }
1730*61046927SAndroid Build Coastguard Worker 
1731*61046927SAndroid Build Coastguard Worker static void
radv_precompute_registers_hw_cs(struct radv_device * device,struct radv_shader_binary * binary)1732*61046927SAndroid Build Coastguard Worker radv_precompute_registers_hw_cs(struct radv_device *device, struct radv_shader_binary *binary)
1733*61046927SAndroid Build Coastguard Worker {
1734*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1735*61046927SAndroid Build Coastguard Worker    struct radv_shader_info *info = &binary->info;
1736*61046927SAndroid Build Coastguard Worker 
1737*61046927SAndroid Build Coastguard Worker    info->regs.cs.compute_resource_limits = radv_get_compute_resource_limits(pdev, info);
1738*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX12) {
1739*61046927SAndroid Build Coastguard Worker       info->regs.cs.compute_num_thread_x = S_00B81C_NUM_THREAD_FULL_GFX12(info->cs.block_size[0]);
1740*61046927SAndroid Build Coastguard Worker       info->regs.cs.compute_num_thread_y = S_00B820_NUM_THREAD_FULL_GFX12(info->cs.block_size[1]);
1741*61046927SAndroid Build Coastguard Worker    } else {
1742*61046927SAndroid Build Coastguard Worker       info->regs.cs.compute_num_thread_x = S_00B81C_NUM_THREAD_FULL_GFX6(info->cs.block_size[0]);
1743*61046927SAndroid Build Coastguard Worker       info->regs.cs.compute_num_thread_y = S_00B820_NUM_THREAD_FULL_GFX6(info->cs.block_size[1]);
1744*61046927SAndroid Build Coastguard Worker    }
1745*61046927SAndroid Build Coastguard Worker    info->regs.cs.compute_num_thread_z = S_00B824_NUM_THREAD_FULL(info->cs.block_size[2]);
1746*61046927SAndroid Build Coastguard Worker }
1747*61046927SAndroid Build Coastguard Worker 
1748*61046927SAndroid Build Coastguard Worker static void
radv_precompute_registers_pgm(const struct radv_device * device,struct radv_shader_info * info)1749*61046927SAndroid Build Coastguard Worker radv_precompute_registers_pgm(const struct radv_device *device, struct radv_shader_info *info)
1750*61046927SAndroid Build Coastguard Worker {
1751*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1752*61046927SAndroid Build Coastguard Worker    const enum amd_gfx_level gfx_level = pdev->info.gfx_level;
1753*61046927SAndroid Build Coastguard Worker    enum ac_hw_stage hw_stage = radv_select_hw_stage(info, gfx_level);
1754*61046927SAndroid Build Coastguard Worker 
1755*61046927SAndroid Build Coastguard Worker    /* Special case for merged shaders compiled separately with ESO on GFX9+. */
1756*61046927SAndroid Build Coastguard Worker    if (info->merged_shader_compiled_separately) {
1757*61046927SAndroid Build Coastguard Worker       if (info->stage == MESA_SHADER_VERTEX && info->next_stage == MESA_SHADER_TESS_CTRL) {
1758*61046927SAndroid Build Coastguard Worker          hw_stage = AC_HW_HULL_SHADER;
1759*61046927SAndroid Build Coastguard Worker       } else if ((info->stage == MESA_SHADER_VERTEX || info->stage == MESA_SHADER_TESS_EVAL) &&
1760*61046927SAndroid Build Coastguard Worker                  info->next_stage == MESA_SHADER_GEOMETRY) {
1761*61046927SAndroid Build Coastguard Worker          hw_stage = info->is_ngg ? AC_HW_NEXT_GEN_GEOMETRY_SHADER : AC_HW_LEGACY_GEOMETRY_SHADER;
1762*61046927SAndroid Build Coastguard Worker       }
1763*61046927SAndroid Build Coastguard Worker    }
1764*61046927SAndroid Build Coastguard Worker 
1765*61046927SAndroid Build Coastguard Worker    switch (hw_stage) {
1766*61046927SAndroid Build Coastguard Worker    case AC_HW_NEXT_GEN_GEOMETRY_SHADER:
1767*61046927SAndroid Build Coastguard Worker       assert(gfx_level >= GFX10);
1768*61046927SAndroid Build Coastguard Worker       if (gfx_level >= GFX12) {
1769*61046927SAndroid Build Coastguard Worker          info->regs.pgm_lo = R_00B224_SPI_SHADER_PGM_LO_ES;
1770*61046927SAndroid Build Coastguard Worker       } else {
1771*61046927SAndroid Build Coastguard Worker          info->regs.pgm_lo = R_00B320_SPI_SHADER_PGM_LO_ES;
1772*61046927SAndroid Build Coastguard Worker       }
1773*61046927SAndroid Build Coastguard Worker 
1774*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc1 = R_00B228_SPI_SHADER_PGM_RSRC1_GS;
1775*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc2 = R_00B22C_SPI_SHADER_PGM_RSRC2_GS;
1776*61046927SAndroid Build Coastguard Worker       break;
1777*61046927SAndroid Build Coastguard Worker    case AC_HW_LEGACY_GEOMETRY_SHADER:
1778*61046927SAndroid Build Coastguard Worker       assert(gfx_level < GFX11);
1779*61046927SAndroid Build Coastguard Worker       if (gfx_level >= GFX10) {
1780*61046927SAndroid Build Coastguard Worker          info->regs.pgm_lo = R_00B320_SPI_SHADER_PGM_LO_ES;
1781*61046927SAndroid Build Coastguard Worker       } else if (gfx_level >= GFX9) {
1782*61046927SAndroid Build Coastguard Worker          info->regs.pgm_lo = R_00B210_SPI_SHADER_PGM_LO_ES;
1783*61046927SAndroid Build Coastguard Worker       } else {
1784*61046927SAndroid Build Coastguard Worker          info->regs.pgm_lo = R_00B220_SPI_SHADER_PGM_LO_GS;
1785*61046927SAndroid Build Coastguard Worker       }
1786*61046927SAndroid Build Coastguard Worker 
1787*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc1 = R_00B228_SPI_SHADER_PGM_RSRC1_GS;
1788*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc2 = R_00B22C_SPI_SHADER_PGM_RSRC2_GS;
1789*61046927SAndroid Build Coastguard Worker       break;
1790*61046927SAndroid Build Coastguard Worker    case AC_HW_EXPORT_SHADER:
1791*61046927SAndroid Build Coastguard Worker       assert(gfx_level < GFX9);
1792*61046927SAndroid Build Coastguard Worker       info->regs.pgm_lo = R_00B320_SPI_SHADER_PGM_LO_ES;
1793*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc1 = R_00B328_SPI_SHADER_PGM_RSRC1_ES;
1794*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc2 = R_00B32C_SPI_SHADER_PGM_RSRC2_ES;
1795*61046927SAndroid Build Coastguard Worker       break;
1796*61046927SAndroid Build Coastguard Worker    case AC_HW_LOCAL_SHADER:
1797*61046927SAndroid Build Coastguard Worker       assert(gfx_level < GFX9);
1798*61046927SAndroid Build Coastguard Worker       info->regs.pgm_lo = R_00B520_SPI_SHADER_PGM_LO_LS;
1799*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc1 = R_00B528_SPI_SHADER_PGM_RSRC1_LS;
1800*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc2 = R_00B52C_SPI_SHADER_PGM_RSRC2_LS;
1801*61046927SAndroid Build Coastguard Worker       break;
1802*61046927SAndroid Build Coastguard Worker    case AC_HW_HULL_SHADER:
1803*61046927SAndroid Build Coastguard Worker       if (gfx_level >= GFX12) {
1804*61046927SAndroid Build Coastguard Worker          info->regs.pgm_lo = R_00B424_SPI_SHADER_PGM_LO_LS;
1805*61046927SAndroid Build Coastguard Worker       } else if (gfx_level >= GFX10) {
1806*61046927SAndroid Build Coastguard Worker          info->regs.pgm_lo = R_00B520_SPI_SHADER_PGM_LO_LS;
1807*61046927SAndroid Build Coastguard Worker       } else if (gfx_level >= GFX9) {
1808*61046927SAndroid Build Coastguard Worker          info->regs.pgm_lo = R_00B410_SPI_SHADER_PGM_LO_LS;
1809*61046927SAndroid Build Coastguard Worker       } else {
1810*61046927SAndroid Build Coastguard Worker          info->regs.pgm_lo = R_00B420_SPI_SHADER_PGM_LO_HS;
1811*61046927SAndroid Build Coastguard Worker       }
1812*61046927SAndroid Build Coastguard Worker 
1813*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc1 = R_00B428_SPI_SHADER_PGM_RSRC1_HS;
1814*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc2 = R_00B42C_SPI_SHADER_PGM_RSRC2_HS;
1815*61046927SAndroid Build Coastguard Worker       break;
1816*61046927SAndroid Build Coastguard Worker    case AC_HW_VERTEX_SHADER:
1817*61046927SAndroid Build Coastguard Worker       assert(gfx_level < GFX11);
1818*61046927SAndroid Build Coastguard Worker       info->regs.pgm_lo = R_00B120_SPI_SHADER_PGM_LO_VS;
1819*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc1 = R_00B128_SPI_SHADER_PGM_RSRC1_VS;
1820*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc2 = R_00B12C_SPI_SHADER_PGM_RSRC2_VS;
1821*61046927SAndroid Build Coastguard Worker       break;
1822*61046927SAndroid Build Coastguard Worker    case AC_HW_PIXEL_SHADER:
1823*61046927SAndroid Build Coastguard Worker       info->regs.pgm_lo = R_00B020_SPI_SHADER_PGM_LO_PS;
1824*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc1 = R_00B028_SPI_SHADER_PGM_RSRC1_PS;
1825*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc2 = R_00B02C_SPI_SHADER_PGM_RSRC2_PS;
1826*61046927SAndroid Build Coastguard Worker       break;
1827*61046927SAndroid Build Coastguard Worker    case AC_HW_COMPUTE_SHADER:
1828*61046927SAndroid Build Coastguard Worker       info->regs.pgm_lo = R_00B830_COMPUTE_PGM_LO;
1829*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc1 = R_00B848_COMPUTE_PGM_RSRC1;
1830*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc2 = R_00B84C_COMPUTE_PGM_RSRC2;
1831*61046927SAndroid Build Coastguard Worker       info->regs.pgm_rsrc3 = R_00B8A0_COMPUTE_PGM_RSRC3;
1832*61046927SAndroid Build Coastguard Worker       break;
1833*61046927SAndroid Build Coastguard Worker    default:
1834*61046927SAndroid Build Coastguard Worker       unreachable("invalid hw stage");
1835*61046927SAndroid Build Coastguard Worker       break;
1836*61046927SAndroid Build Coastguard Worker    }
1837*61046927SAndroid Build Coastguard Worker }
1838*61046927SAndroid Build Coastguard Worker 
1839*61046927SAndroid Build Coastguard Worker static void
radv_precompute_registers(struct radv_device * device,struct radv_shader_binary * binary)1840*61046927SAndroid Build Coastguard Worker radv_precompute_registers(struct radv_device *device, struct radv_shader_binary *binary)
1841*61046927SAndroid Build Coastguard Worker {
1842*61046927SAndroid Build Coastguard Worker    struct radv_shader_info *info = &binary->info;
1843*61046927SAndroid Build Coastguard Worker 
1844*61046927SAndroid Build Coastguard Worker    radv_precompute_registers_pgm(device, info);
1845*61046927SAndroid Build Coastguard Worker 
1846*61046927SAndroid Build Coastguard Worker    switch (info->stage) {
1847*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_VERTEX:
1848*61046927SAndroid Build Coastguard Worker       if (!info->vs.as_ls && !info->vs.as_es) {
1849*61046927SAndroid Build Coastguard Worker          if (info->is_ngg) {
1850*61046927SAndroid Build Coastguard Worker             radv_precompute_registers_hw_ngg(device, &binary->config, &binary->info);
1851*61046927SAndroid Build Coastguard Worker          } else {
1852*61046927SAndroid Build Coastguard Worker             radv_precompute_registers_hw_vs(device, binary);
1853*61046927SAndroid Build Coastguard Worker          }
1854*61046927SAndroid Build Coastguard Worker       }
1855*61046927SAndroid Build Coastguard Worker       break;
1856*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_EVAL:
1857*61046927SAndroid Build Coastguard Worker       if (!info->tes.as_es) {
1858*61046927SAndroid Build Coastguard Worker          if (info->is_ngg) {
1859*61046927SAndroid Build Coastguard Worker             radv_precompute_registers_hw_ngg(device, &binary->config, &binary->info);
1860*61046927SAndroid Build Coastguard Worker          } else {
1861*61046927SAndroid Build Coastguard Worker             radv_precompute_registers_hw_vs(device, binary);
1862*61046927SAndroid Build Coastguard Worker          }
1863*61046927SAndroid Build Coastguard Worker       }
1864*61046927SAndroid Build Coastguard Worker       break;
1865*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_GEOMETRY:
1866*61046927SAndroid Build Coastguard Worker       if (info->is_ngg) {
1867*61046927SAndroid Build Coastguard Worker          radv_precompute_registers_hw_ngg(device, &binary->config, &binary->info);
1868*61046927SAndroid Build Coastguard Worker       } else {
1869*61046927SAndroid Build Coastguard Worker          radv_precompute_registers_hw_gs(device, binary);
1870*61046927SAndroid Build Coastguard Worker       }
1871*61046927SAndroid Build Coastguard Worker       break;
1872*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_MESH:
1873*61046927SAndroid Build Coastguard Worker       radv_precompute_registers_hw_ms(device, binary);
1874*61046927SAndroid Build Coastguard Worker       break;
1875*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_FRAGMENT:
1876*61046927SAndroid Build Coastguard Worker       radv_precompute_registers_hw_fs(device, binary);
1877*61046927SAndroid Build Coastguard Worker       break;
1878*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_COMPUTE:
1879*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TASK:
1880*61046927SAndroid Build Coastguard Worker       radv_precompute_registers_hw_cs(device, binary);
1881*61046927SAndroid Build Coastguard Worker       break;
1882*61046927SAndroid Build Coastguard Worker    default:
1883*61046927SAndroid Build Coastguard Worker       break;
1884*61046927SAndroid Build Coastguard Worker    }
1885*61046927SAndroid Build Coastguard Worker }
1886*61046927SAndroid Build Coastguard Worker 
1887*61046927SAndroid Build Coastguard Worker static bool
radv_mem_ordered(const struct radv_physical_device * pdev)1888*61046927SAndroid Build Coastguard Worker radv_mem_ordered(const struct radv_physical_device *pdev)
1889*61046927SAndroid Build Coastguard Worker {
1890*61046927SAndroid Build Coastguard Worker    return pdev->info.gfx_level >= GFX10 && pdev->info.gfx_level < GFX12;
1891*61046927SAndroid Build Coastguard Worker }
1892*61046927SAndroid Build Coastguard Worker 
1893*61046927SAndroid Build Coastguard Worker static bool
radv_postprocess_binary_config(struct radv_device * device,struct radv_shader_binary * binary,const struct radv_shader_args * args)1894*61046927SAndroid Build Coastguard Worker radv_postprocess_binary_config(struct radv_device *device, struct radv_shader_binary *binary,
1895*61046927SAndroid Build Coastguard Worker                                const struct radv_shader_args *args)
1896*61046927SAndroid Build Coastguard Worker {
1897*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
1898*61046927SAndroid Build Coastguard Worker    struct ac_shader_config *config = &binary->config;
1899*61046927SAndroid Build Coastguard Worker 
1900*61046927SAndroid Build Coastguard Worker    if (binary->type == RADV_BINARY_TYPE_RTLD) {
1901*61046927SAndroid Build Coastguard Worker #if !defined(USE_LIBELF)
1902*61046927SAndroid Build Coastguard Worker       return false;
1903*61046927SAndroid Build Coastguard Worker #else
1904*61046927SAndroid Build Coastguard Worker       struct ac_rtld_binary rtld_binary = {0};
1905*61046927SAndroid Build Coastguard Worker 
1906*61046927SAndroid Build Coastguard Worker       if (!radv_open_rtld_binary(device, binary, &rtld_binary)) {
1907*61046927SAndroid Build Coastguard Worker          return false;
1908*61046927SAndroid Build Coastguard Worker       }
1909*61046927SAndroid Build Coastguard Worker 
1910*61046927SAndroid Build Coastguard Worker       if (!ac_rtld_read_config(&pdev->info, &rtld_binary, config)) {
1911*61046927SAndroid Build Coastguard Worker          ac_rtld_close(&rtld_binary);
1912*61046927SAndroid Build Coastguard Worker          return false;
1913*61046927SAndroid Build Coastguard Worker       }
1914*61046927SAndroid Build Coastguard Worker 
1915*61046927SAndroid Build Coastguard Worker       if (rtld_binary.lds_size > 0) {
1916*61046927SAndroid Build Coastguard Worker          unsigned encode_granularity = pdev->info.lds_encode_granularity;
1917*61046927SAndroid Build Coastguard Worker          config->lds_size = DIV_ROUND_UP(rtld_binary.lds_size, encode_granularity);
1918*61046927SAndroid Build Coastguard Worker       }
1919*61046927SAndroid Build Coastguard Worker       if (!config->lds_size && binary->info.stage == MESA_SHADER_TESS_CTRL) {
1920*61046927SAndroid Build Coastguard Worker          /* This is used for reporting LDS statistics */
1921*61046927SAndroid Build Coastguard Worker          config->lds_size = binary->info.tcs.num_lds_blocks;
1922*61046927SAndroid Build Coastguard Worker       }
1923*61046927SAndroid Build Coastguard Worker 
1924*61046927SAndroid Build Coastguard Worker       assert(!binary->info.has_ngg_culling || config->lds_size);
1925*61046927SAndroid Build Coastguard Worker       ac_rtld_close(&rtld_binary);
1926*61046927SAndroid Build Coastguard Worker #endif
1927*61046927SAndroid Build Coastguard Worker    }
1928*61046927SAndroid Build Coastguard Worker 
1929*61046927SAndroid Build Coastguard Worker    const struct radv_shader_info *info = &binary->info;
1930*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage = binary->info.stage;
1931*61046927SAndroid Build Coastguard Worker    bool scratch_enabled = config->scratch_bytes_per_wave > 0;
1932*61046927SAndroid Build Coastguard Worker    bool trap_enabled = !!device->trap_handler_shader;
1933*61046927SAndroid Build Coastguard Worker    unsigned vgpr_comp_cnt = 0;
1934*61046927SAndroid Build Coastguard Worker    unsigned num_input_vgprs = args->ac.num_vgprs_used;
1935*61046927SAndroid Build Coastguard Worker 
1936*61046927SAndroid Build Coastguard Worker    if (stage == MESA_SHADER_FRAGMENT) {
1937*61046927SAndroid Build Coastguard Worker       num_input_vgprs = ac_get_fs_input_vgpr_cnt(config, NULL);
1938*61046927SAndroid Build Coastguard Worker    }
1939*61046927SAndroid Build Coastguard Worker 
1940*61046927SAndroid Build Coastguard Worker    unsigned num_vgprs = MAX2(config->num_vgprs, num_input_vgprs);
1941*61046927SAndroid Build Coastguard Worker    /* +2 for the ring offsets, +3 for scratch wave offset and VCC */
1942*61046927SAndroid Build Coastguard Worker    unsigned num_sgprs = MAX2(config->num_sgprs, args->ac.num_sgprs_used + 2 + 3);
1943*61046927SAndroid Build Coastguard Worker    unsigned num_shared_vgprs = config->num_shared_vgprs;
1944*61046927SAndroid Build Coastguard Worker    /* shared VGPRs are introduced in Navi and are allocated in blocks of 8 (RDNA ref 3.6.5) */
1945*61046927SAndroid Build Coastguard Worker    assert((pdev->info.gfx_level >= GFX10 && num_shared_vgprs % 8 == 0) ||
1946*61046927SAndroid Build Coastguard Worker           (pdev->info.gfx_level < GFX10 && num_shared_vgprs == 0));
1947*61046927SAndroid Build Coastguard Worker    unsigned num_shared_vgpr_blocks = num_shared_vgprs / 8;
1948*61046927SAndroid Build Coastguard Worker    unsigned excp_en = 0;
1949*61046927SAndroid Build Coastguard Worker 
1950*61046927SAndroid Build Coastguard Worker    config->num_vgprs = num_vgprs;
1951*61046927SAndroid Build Coastguard Worker    config->num_sgprs = num_sgprs;
1952*61046927SAndroid Build Coastguard Worker    config->num_shared_vgprs = num_shared_vgprs;
1953*61046927SAndroid Build Coastguard Worker 
1954*61046927SAndroid Build Coastguard Worker    config->rsrc2 = S_00B12C_USER_SGPR(args->num_user_sgprs) | S_00B12C_SCRATCH_EN(scratch_enabled) |
1955*61046927SAndroid Build Coastguard Worker                    S_00B12C_TRAP_PRESENT(trap_enabled);
1956*61046927SAndroid Build Coastguard Worker 
1957*61046927SAndroid Build Coastguard Worker    if (trap_enabled) {
1958*61046927SAndroid Build Coastguard Worker       /* Configure the shader exceptions like memory violation, etc.
1959*61046927SAndroid Build Coastguard Worker        * TODO: Enable (and validate) more exceptions.
1960*61046927SAndroid Build Coastguard Worker        */
1961*61046927SAndroid Build Coastguard Worker       excp_en = 1 << 8; /* mem_viol */
1962*61046927SAndroid Build Coastguard Worker    }
1963*61046927SAndroid Build Coastguard Worker 
1964*61046927SAndroid Build Coastguard Worker    if (!pdev->use_ngg_streamout) {
1965*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B12C_SO_BASE0_EN(!!info->so.strides[0]) | S_00B12C_SO_BASE1_EN(!!info->so.strides[1]) |
1966*61046927SAndroid Build Coastguard Worker                        S_00B12C_SO_BASE2_EN(!!info->so.strides[2]) | S_00B12C_SO_BASE3_EN(!!info->so.strides[3]) |
1967*61046927SAndroid Build Coastguard Worker                        S_00B12C_SO_EN(!!info->so.num_outputs);
1968*61046927SAndroid Build Coastguard Worker    }
1969*61046927SAndroid Build Coastguard Worker 
1970*61046927SAndroid Build Coastguard Worker    config->rsrc1 = S_00B848_VGPRS((num_vgprs - 1) / (info->wave_size == 32 ? 8 : 4)) |
1971*61046927SAndroid Build Coastguard Worker                    S_00B848_DX10_CLAMP(pdev->info.gfx_level < GFX12) | S_00B848_FLOAT_MODE(config->float_mode);
1972*61046927SAndroid Build Coastguard Worker 
1973*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX10) {
1974*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B22C_USER_SGPR_MSB_GFX10(args->num_user_sgprs >> 5);
1975*61046927SAndroid Build Coastguard Worker    } else {
1976*61046927SAndroid Build Coastguard Worker       config->rsrc1 |= S_00B228_SGPRS((num_sgprs - 1) / 8);
1977*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B22C_USER_SGPR_MSB_GFX9(args->num_user_sgprs >> 5);
1978*61046927SAndroid Build Coastguard Worker    }
1979*61046927SAndroid Build Coastguard Worker 
1980*61046927SAndroid Build Coastguard Worker    gl_shader_stage es_stage = MESA_SHADER_NONE;
1981*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX9) {
1982*61046927SAndroid Build Coastguard Worker       es_stage = stage == MESA_SHADER_GEOMETRY ? info->gs.es_type : stage;
1983*61046927SAndroid Build Coastguard Worker    }
1984*61046927SAndroid Build Coastguard Worker 
1985*61046927SAndroid Build Coastguard Worker    if (info->merged_shader_compiled_separately) {
1986*61046927SAndroid Build Coastguard Worker       /* Update the stage for merged shaders compiled separately with ESO on GFX9+. */
1987*61046927SAndroid Build Coastguard Worker       if (stage == MESA_SHADER_VERTEX && info->vs.as_ls) {
1988*61046927SAndroid Build Coastguard Worker          stage = MESA_SHADER_TESS_CTRL;
1989*61046927SAndroid Build Coastguard Worker       } else if (stage == MESA_SHADER_VERTEX && info->vs.as_es) {
1990*61046927SAndroid Build Coastguard Worker          es_stage = MESA_SHADER_VERTEX;
1991*61046927SAndroid Build Coastguard Worker          stage = MESA_SHADER_GEOMETRY;
1992*61046927SAndroid Build Coastguard Worker       } else if (stage == MESA_SHADER_TESS_EVAL && info->tes.as_es) {
1993*61046927SAndroid Build Coastguard Worker          es_stage = MESA_SHADER_TESS_EVAL;
1994*61046927SAndroid Build Coastguard Worker          stage = MESA_SHADER_GEOMETRY;
1995*61046927SAndroid Build Coastguard Worker       }
1996*61046927SAndroid Build Coastguard Worker    }
1997*61046927SAndroid Build Coastguard Worker 
1998*61046927SAndroid Build Coastguard Worker    bool wgp_mode = radv_should_use_wgp_mode(device, stage, info);
1999*61046927SAndroid Build Coastguard Worker 
2000*61046927SAndroid Build Coastguard Worker    switch (stage) {
2001*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_EVAL:
2002*61046927SAndroid Build Coastguard Worker       if (info->is_ngg) {
2003*61046927SAndroid Build Coastguard Worker          config->rsrc1 |= S_00B228_MEM_ORDERED(radv_mem_ordered(pdev));
2004*61046927SAndroid Build Coastguard Worker          config->rsrc2 |= S_00B22C_OC_LDS_EN(1) | S_00B22C_EXCP_EN(excp_en);
2005*61046927SAndroid Build Coastguard Worker       } else if (info->tes.as_es) {
2006*61046927SAndroid Build Coastguard Worker          assert(pdev->info.gfx_level <= GFX8);
2007*61046927SAndroid Build Coastguard Worker          vgpr_comp_cnt = info->uses_prim_id ? 3 : 2;
2008*61046927SAndroid Build Coastguard Worker 
2009*61046927SAndroid Build Coastguard Worker          config->rsrc2 |= S_00B12C_OC_LDS_EN(1) | S_00B12C_EXCP_EN(excp_en);
2010*61046927SAndroid Build Coastguard Worker       } else {
2011*61046927SAndroid Build Coastguard Worker          bool enable_prim_id = info->outinfo.export_prim_id || info->uses_prim_id;
2012*61046927SAndroid Build Coastguard Worker          vgpr_comp_cnt = enable_prim_id ? 3 : 2;
2013*61046927SAndroid Build Coastguard Worker 
2014*61046927SAndroid Build Coastguard Worker          config->rsrc1 |= S_00B128_MEM_ORDERED(radv_mem_ordered(pdev));
2015*61046927SAndroid Build Coastguard Worker          config->rsrc2 |= S_00B12C_OC_LDS_EN(1) | S_00B12C_EXCP_EN(excp_en);
2016*61046927SAndroid Build Coastguard Worker       }
2017*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B22C_SHARED_VGPR_CNT(num_shared_vgpr_blocks);
2018*61046927SAndroid Build Coastguard Worker       break;
2019*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_CTRL:
2020*61046927SAndroid Build Coastguard Worker       if (pdev->info.gfx_level >= GFX9) {
2021*61046927SAndroid Build Coastguard Worker          /* We need at least 2 components for LS.
2022*61046927SAndroid Build Coastguard Worker           * VGPR0-3: (VertexID, RelAutoindex, InstanceID / StepRate0, InstanceID).
2023*61046927SAndroid Build Coastguard Worker           * StepRate0 is set to 1. so that VGPR3 doesn't have to be loaded.
2024*61046927SAndroid Build Coastguard Worker           */
2025*61046927SAndroid Build Coastguard Worker          if (pdev->info.gfx_level >= GFX10) {
2026*61046927SAndroid Build Coastguard Worker             if (info->vs.needs_instance_id) {
2027*61046927SAndroid Build Coastguard Worker                vgpr_comp_cnt = pdev->info.gfx_level >= GFX12 ? 1 : 3;
2028*61046927SAndroid Build Coastguard Worker             } else if (pdev->info.gfx_level <= GFX10_3) {
2029*61046927SAndroid Build Coastguard Worker                vgpr_comp_cnt = 1;
2030*61046927SAndroid Build Coastguard Worker             }
2031*61046927SAndroid Build Coastguard Worker             config->rsrc2 |= S_00B42C_EXCP_EN_GFX6(excp_en);
2032*61046927SAndroid Build Coastguard Worker          } else {
2033*61046927SAndroid Build Coastguard Worker             vgpr_comp_cnt = info->vs.needs_instance_id ? 2 : 1;
2034*61046927SAndroid Build Coastguard Worker             config->rsrc2 |= S_00B42C_EXCP_EN_GFX9(excp_en);
2035*61046927SAndroid Build Coastguard Worker          }
2036*61046927SAndroid Build Coastguard Worker       } else {
2037*61046927SAndroid Build Coastguard Worker          config->rsrc2 |= S_00B12C_OC_LDS_EN(1) | S_00B12C_EXCP_EN(excp_en);
2038*61046927SAndroid Build Coastguard Worker       }
2039*61046927SAndroid Build Coastguard Worker       config->rsrc1 |= S_00B428_MEM_ORDERED(radv_mem_ordered(pdev)) | S_00B428_WGP_MODE(wgp_mode);
2040*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B42C_SHARED_VGPR_CNT(num_shared_vgpr_blocks);
2041*61046927SAndroid Build Coastguard Worker       break;
2042*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_VERTEX:
2043*61046927SAndroid Build Coastguard Worker       if (info->is_ngg) {
2044*61046927SAndroid Build Coastguard Worker          config->rsrc1 |= S_00B228_MEM_ORDERED(radv_mem_ordered(pdev));
2045*61046927SAndroid Build Coastguard Worker       } else if (info->vs.as_ls) {
2046*61046927SAndroid Build Coastguard Worker          assert(pdev->info.gfx_level <= GFX8);
2047*61046927SAndroid Build Coastguard Worker          /* We need at least 2 components for LS.
2048*61046927SAndroid Build Coastguard Worker           * VGPR0-3: (VertexID, RelAutoindex, InstanceID / StepRate0, InstanceID).
2049*61046927SAndroid Build Coastguard Worker           * StepRate0 is set to 1. so that VGPR3 doesn't have to be loaded.
2050*61046927SAndroid Build Coastguard Worker           *
2051*61046927SAndroid Build Coastguard Worker           * On GFX12, InstanceID is in VGPR1.
2052*61046927SAndroid Build Coastguard Worker           */
2053*61046927SAndroid Build Coastguard Worker          vgpr_comp_cnt = info->vs.needs_instance_id ? 2 : 1;
2054*61046927SAndroid Build Coastguard Worker       } else if (info->vs.as_es) {
2055*61046927SAndroid Build Coastguard Worker          assert(pdev->info.gfx_level <= GFX8);
2056*61046927SAndroid Build Coastguard Worker          /* VGPR0-3: (VertexID, InstanceID / StepRate0, ...) */
2057*61046927SAndroid Build Coastguard Worker          vgpr_comp_cnt = info->vs.needs_instance_id ? 1 : 0;
2058*61046927SAndroid Build Coastguard Worker       } else {
2059*61046927SAndroid Build Coastguard Worker          /* VGPR0-3: (VertexID, InstanceID / StepRate0, PrimID, InstanceID)
2060*61046927SAndroid Build Coastguard Worker           * If PrimID is disabled. InstanceID / StepRate1 is loaded instead.
2061*61046927SAndroid Build Coastguard Worker           * StepRate0 is set to 1. so that VGPR3 doesn't have to be loaded.
2062*61046927SAndroid Build Coastguard Worker           */
2063*61046927SAndroid Build Coastguard Worker          if (info->vs.needs_instance_id && pdev->info.gfx_level >= GFX10) {
2064*61046927SAndroid Build Coastguard Worker             vgpr_comp_cnt = 3;
2065*61046927SAndroid Build Coastguard Worker          } else if (info->outinfo.export_prim_id) {
2066*61046927SAndroid Build Coastguard Worker             vgpr_comp_cnt = 2;
2067*61046927SAndroid Build Coastguard Worker          } else if (info->vs.needs_instance_id) {
2068*61046927SAndroid Build Coastguard Worker             vgpr_comp_cnt = 1;
2069*61046927SAndroid Build Coastguard Worker          } else {
2070*61046927SAndroid Build Coastguard Worker             vgpr_comp_cnt = 0;
2071*61046927SAndroid Build Coastguard Worker          }
2072*61046927SAndroid Build Coastguard Worker 
2073*61046927SAndroid Build Coastguard Worker          config->rsrc1 |= S_00B128_MEM_ORDERED(radv_mem_ordered(pdev));
2074*61046927SAndroid Build Coastguard Worker       }
2075*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B12C_SHARED_VGPR_CNT(num_shared_vgpr_blocks) | S_00B12C_EXCP_EN(excp_en);
2076*61046927SAndroid Build Coastguard Worker       break;
2077*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_MESH:
2078*61046927SAndroid Build Coastguard Worker       config->rsrc1 |= S_00B228_MEM_ORDERED(radv_mem_ordered(pdev));
2079*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B12C_SHARED_VGPR_CNT(num_shared_vgpr_blocks) | S_00B12C_EXCP_EN(excp_en);
2080*61046927SAndroid Build Coastguard Worker       break;
2081*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_FRAGMENT:
2082*61046927SAndroid Build Coastguard Worker       config->rsrc1 |=
2083*61046927SAndroid Build Coastguard Worker          S_00B028_MEM_ORDERED(radv_mem_ordered(pdev)) | S_00B028_LOAD_PROVOKING_VTX(info->ps.load_provoking_vtx);
2084*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B02C_SHARED_VGPR_CNT(num_shared_vgpr_blocks) | S_00B02C_EXCP_EN(excp_en) |
2085*61046927SAndroid Build Coastguard Worker                        S_00B02C_LOAD_COLLISION_WAVEID(info->ps.pops && pdev->info.gfx_level < GFX11);
2086*61046927SAndroid Build Coastguard Worker       break;
2087*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_GEOMETRY:
2088*61046927SAndroid Build Coastguard Worker       config->rsrc1 |= S_00B228_MEM_ORDERED(radv_mem_ordered(pdev));
2089*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B22C_SHARED_VGPR_CNT(num_shared_vgpr_blocks) | S_00B22C_EXCP_EN(excp_en);
2090*61046927SAndroid Build Coastguard Worker       break;
2091*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_RAYGEN:
2092*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_CLOSEST_HIT:
2093*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_MISS:
2094*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_CALLABLE:
2095*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_INTERSECTION:
2096*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_ANY_HIT:
2097*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_COMPUTE:
2098*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TASK:
2099*61046927SAndroid Build Coastguard Worker       config->rsrc1 |= S_00B848_MEM_ORDERED(radv_mem_ordered(pdev)) | S_00B848_WGP_MODE(wgp_mode);
2100*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B84C_TGID_X_EN(info->cs.uses_block_id[0]) | S_00B84C_TGID_Y_EN(info->cs.uses_block_id[1]) |
2101*61046927SAndroid Build Coastguard Worker                        S_00B84C_TGID_Z_EN(info->cs.uses_block_id[2]) |
2102*61046927SAndroid Build Coastguard Worker                        S_00B84C_TIDIG_COMP_CNT(info->cs.uses_thread_id[2]   ? 2
2103*61046927SAndroid Build Coastguard Worker                                                : info->cs.uses_thread_id[1] ? 1
2104*61046927SAndroid Build Coastguard Worker                                                                             : 0) |
2105*61046927SAndroid Build Coastguard Worker                        S_00B84C_TG_SIZE_EN(info->cs.uses_local_invocation_idx) | S_00B84C_LDS_SIZE(config->lds_size) |
2106*61046927SAndroid Build Coastguard Worker                        S_00B84C_EXCP_EN(excp_en);
2107*61046927SAndroid Build Coastguard Worker       config->rsrc3 |= S_00B8A0_SHARED_VGPR_CNT(num_shared_vgpr_blocks);
2108*61046927SAndroid Build Coastguard Worker 
2109*61046927SAndroid Build Coastguard Worker       break;
2110*61046927SAndroid Build Coastguard Worker    default:
2111*61046927SAndroid Build Coastguard Worker       unreachable("unsupported shader type");
2112*61046927SAndroid Build Coastguard Worker       break;
2113*61046927SAndroid Build Coastguard Worker    }
2114*61046927SAndroid Build Coastguard Worker 
2115*61046927SAndroid Build Coastguard Worker    if (pdev->info.gfx_level >= GFX10 && info->is_ngg &&
2116*61046927SAndroid Build Coastguard Worker        (stage == MESA_SHADER_VERTEX || stage == MESA_SHADER_TESS_EVAL || stage == MESA_SHADER_GEOMETRY ||
2117*61046927SAndroid Build Coastguard Worker         stage == MESA_SHADER_MESH)) {
2118*61046927SAndroid Build Coastguard Worker       unsigned gs_vgpr_comp_cnt, es_vgpr_comp_cnt;
2119*61046927SAndroid Build Coastguard Worker 
2120*61046927SAndroid Build Coastguard Worker       /* VGPR5-8: (VertexID, UserVGPR0, UserVGPR1, UserVGPR2 / InstanceID)
2121*61046927SAndroid Build Coastguard Worker        *
2122*61046927SAndroid Build Coastguard Worker        * On GFX12, InstanceID is in VGPR1.
2123*61046927SAndroid Build Coastguard Worker        */
2124*61046927SAndroid Build Coastguard Worker       if (es_stage == MESA_SHADER_VERTEX) {
2125*61046927SAndroid Build Coastguard Worker          if (info->vs.needs_instance_id) {
2126*61046927SAndroid Build Coastguard Worker             es_vgpr_comp_cnt = pdev->info.gfx_level >= GFX12 ? 1 : 3;
2127*61046927SAndroid Build Coastguard Worker          } else {
2128*61046927SAndroid Build Coastguard Worker             es_vgpr_comp_cnt = 0;
2129*61046927SAndroid Build Coastguard Worker          }
2130*61046927SAndroid Build Coastguard Worker       } else if (es_stage == MESA_SHADER_TESS_EVAL) {
2131*61046927SAndroid Build Coastguard Worker          bool enable_prim_id = info->outinfo.export_prim_id || info->uses_prim_id;
2132*61046927SAndroid Build Coastguard Worker          es_vgpr_comp_cnt = enable_prim_id ? 3 : 2;
2133*61046927SAndroid Build Coastguard Worker       } else if (es_stage == MESA_SHADER_MESH) {
2134*61046927SAndroid Build Coastguard Worker          es_vgpr_comp_cnt = 0;
2135*61046927SAndroid Build Coastguard Worker       } else {
2136*61046927SAndroid Build Coastguard Worker          unreachable("Unexpected ES shader stage");
2137*61046927SAndroid Build Coastguard Worker       }
2138*61046927SAndroid Build Coastguard Worker 
2139*61046927SAndroid Build Coastguard Worker       if (pdev->info.gfx_level >= GFX12) {
2140*61046927SAndroid Build Coastguard Worker          if (info->gs.vertices_in >= 4) {
2141*61046927SAndroid Build Coastguard Worker             gs_vgpr_comp_cnt = 2; /* VGPR2 contains offsets 3-5 */
2142*61046927SAndroid Build Coastguard Worker          } else if (info->uses_prim_id || (es_stage == MESA_SHADER_VERTEX && info->outinfo.export_prim_id)) {
2143*61046927SAndroid Build Coastguard Worker             gs_vgpr_comp_cnt = 1; /* VGPR1 contains PrimitiveID. */
2144*61046927SAndroid Build Coastguard Worker          } else {
2145*61046927SAndroid Build Coastguard Worker             gs_vgpr_comp_cnt = 0; /* VGPR0 contains offsets 0-2, GS invocation ID. */
2146*61046927SAndroid Build Coastguard Worker          }
2147*61046927SAndroid Build Coastguard Worker       } else {
2148*61046927SAndroid Build Coastguard Worker          /* GS vertex offsets in NGG:
2149*61046927SAndroid Build Coastguard Worker           * - in passthrough mode, they are all packed into VGPR0
2150*61046927SAndroid Build Coastguard Worker           * - in the default mode: VGPR0: offsets 0, 1; VGPR1: offsets 2, 3
2151*61046927SAndroid Build Coastguard Worker           *
2152*61046927SAndroid Build Coastguard Worker           * The vertex offset 2 is always needed when NGG isn't in passthrough mode
2153*61046927SAndroid Build Coastguard Worker           * and uses triangle input primitives, including with NGG culling.
2154*61046927SAndroid Build Coastguard Worker           */
2155*61046927SAndroid Build Coastguard Worker          bool need_gs_vtx_offset2 = !info->is_ngg_passthrough || info->gs.vertices_in >= 3;
2156*61046927SAndroid Build Coastguard Worker 
2157*61046927SAndroid Build Coastguard Worker          /* TES only needs vertex offset 2 for triangles or quads. */
2158*61046927SAndroid Build Coastguard Worker          if (stage == MESA_SHADER_TESS_EVAL)
2159*61046927SAndroid Build Coastguard Worker             need_gs_vtx_offset2 &= info->tes._primitive_mode == TESS_PRIMITIVE_TRIANGLES ||
2160*61046927SAndroid Build Coastguard Worker                                    info->tes._primitive_mode == TESS_PRIMITIVE_QUADS;
2161*61046927SAndroid Build Coastguard Worker 
2162*61046927SAndroid Build Coastguard Worker          if (info->uses_invocation_id) {
2163*61046927SAndroid Build Coastguard Worker             gs_vgpr_comp_cnt = 3; /* VGPR3 contains InvocationID. */
2164*61046927SAndroid Build Coastguard Worker          } else if (info->uses_prim_id || (es_stage == MESA_SHADER_VERTEX && info->outinfo.export_prim_id)) {
2165*61046927SAndroid Build Coastguard Worker             gs_vgpr_comp_cnt = 2; /* VGPR2 contains PrimitiveID. */
2166*61046927SAndroid Build Coastguard Worker          } else if (need_gs_vtx_offset2) {
2167*61046927SAndroid Build Coastguard Worker             gs_vgpr_comp_cnt = 1; /* VGPR1 contains offsets 2, 3 */
2168*61046927SAndroid Build Coastguard Worker          } else {
2169*61046927SAndroid Build Coastguard Worker             gs_vgpr_comp_cnt = 0; /* VGPR0 contains offsets 0, 1 (or passthrough prim) */
2170*61046927SAndroid Build Coastguard Worker          }
2171*61046927SAndroid Build Coastguard Worker       }
2172*61046927SAndroid Build Coastguard Worker 
2173*61046927SAndroid Build Coastguard Worker       /* Disable the WGP mode on gfx10.3 because it can hang. (it
2174*61046927SAndroid Build Coastguard Worker        * happened on VanGogh) Let's disable it on all chips that
2175*61046927SAndroid Build Coastguard Worker        * disable exactly 1 CU per SA for GS.
2176*61046927SAndroid Build Coastguard Worker        */
2177*61046927SAndroid Build Coastguard Worker       config->rsrc1 |= S_00B228_GS_VGPR_COMP_CNT(gs_vgpr_comp_cnt) | S_00B228_WGP_MODE(wgp_mode);
2178*61046927SAndroid Build Coastguard Worker       config->rsrc2 |= S_00B22C_ES_VGPR_COMP_CNT(es_vgpr_comp_cnt) | S_00B22C_LDS_SIZE(config->lds_size) |
2179*61046927SAndroid Build Coastguard Worker                        S_00B22C_OC_LDS_EN(es_stage == MESA_SHADER_TESS_EVAL);
2180*61046927SAndroid Build Coastguard Worker    } else if (pdev->info.gfx_level >= GFX9 && stage == MESA_SHADER_GEOMETRY) {
2181*61046927SAndroid Build Coastguard Worker       unsigned gs_vgpr_comp_cnt, es_vgpr_comp_cnt;
2182*61046927SAndroid Build Coastguard Worker 
2183*61046927SAndroid Build Coastguard Worker       if (es_stage == MESA_SHADER_VERTEX) {
2184*61046927SAndroid Build Coastguard Worker          /* VGPR0-3: (VertexID, InstanceID / StepRate0, ...) */
2185*61046927SAndroid Build Coastguard Worker          if (info->vs.needs_instance_id) {
2186*61046927SAndroid Build Coastguard Worker             es_vgpr_comp_cnt = pdev->info.gfx_level >= GFX10 ? 3 : 1;
2187*61046927SAndroid Build Coastguard Worker          } else {
2188*61046927SAndroid Build Coastguard Worker             es_vgpr_comp_cnt = 0;
2189*61046927SAndroid Build Coastguard Worker          }
2190*61046927SAndroid Build Coastguard Worker       } else if (es_stage == MESA_SHADER_TESS_EVAL) {
2191*61046927SAndroid Build Coastguard Worker          es_vgpr_comp_cnt = info->uses_prim_id ? 3 : 2;
2192*61046927SAndroid Build Coastguard Worker       } else {
2193*61046927SAndroid Build Coastguard Worker          unreachable("invalid shader ES type");
2194*61046927SAndroid Build Coastguard Worker       }
2195*61046927SAndroid Build Coastguard Worker 
2196*61046927SAndroid Build Coastguard Worker       /* If offsets 4, 5 are used, GS_VGPR_COMP_CNT is ignored and
2197*61046927SAndroid Build Coastguard Worker        * VGPR[0:4] are always loaded.
2198*61046927SAndroid Build Coastguard Worker        */
2199*61046927SAndroid Build Coastguard Worker       if (info->uses_invocation_id) {
2200*61046927SAndroid Build Coastguard Worker          gs_vgpr_comp_cnt = 3; /* VGPR3 contains InvocationID. */
2201*61046927SAndroid Build Coastguard Worker       } else if (info->uses_prim_id) {
2202*61046927SAndroid Build Coastguard Worker          gs_vgpr_comp_cnt = 2; /* VGPR2 contains PrimitiveID. */
2203*61046927SAndroid Build Coastguard Worker       } else if (info->gs.vertices_in >= 3) {
2204*61046927SAndroid Build Coastguard Worker          gs_vgpr_comp_cnt = 1; /* VGPR1 contains offsets 2, 3 */
2205*61046927SAndroid Build Coastguard Worker       } else {
2206*61046927SAndroid Build Coastguard Worker          gs_vgpr_comp_cnt = 0; /* VGPR0 contains offsets 0, 1 */
2207*61046927SAndroid Build Coastguard Worker       }
2208*61046927SAndroid Build Coastguard Worker 
2209*61046927SAndroid Build Coastguard Worker       config->rsrc1 |= S_00B228_GS_VGPR_COMP_CNT(gs_vgpr_comp_cnt) | S_00B228_WGP_MODE(wgp_mode);
2210*61046927SAndroid Build Coastguard Worker       config->rsrc2 |=
2211*61046927SAndroid Build Coastguard Worker          S_00B22C_ES_VGPR_COMP_CNT(es_vgpr_comp_cnt) | S_00B22C_OC_LDS_EN(es_stage == MESA_SHADER_TESS_EVAL);
2212*61046927SAndroid Build Coastguard Worker    } else if (pdev->info.gfx_level >= GFX9 && stage == MESA_SHADER_TESS_CTRL) {
2213*61046927SAndroid Build Coastguard Worker       config->rsrc1 |= S_00B428_LS_VGPR_COMP_CNT(vgpr_comp_cnt);
2214*61046927SAndroid Build Coastguard Worker    } else {
2215*61046927SAndroid Build Coastguard Worker       config->rsrc1 |= S_00B128_VGPR_COMP_CNT(vgpr_comp_cnt);
2216*61046927SAndroid Build Coastguard Worker    }
2217*61046927SAndroid Build Coastguard Worker 
2218*61046927SAndroid Build Coastguard Worker    /* Precompute register values for faster emission. */
2219*61046927SAndroid Build Coastguard Worker    radv_precompute_registers(device, binary);
2220*61046927SAndroid Build Coastguard Worker 
2221*61046927SAndroid Build Coastguard Worker    return true;
2222*61046927SAndroid Build Coastguard Worker }
2223*61046927SAndroid Build Coastguard Worker 
2224*61046927SAndroid Build Coastguard Worker void
radv_shader_combine_cfg_vs_tcs(const struct radv_shader * vs,const struct radv_shader * tcs,uint32_t * rsrc1_out,uint32_t * rsrc2_out)2225*61046927SAndroid Build Coastguard Worker radv_shader_combine_cfg_vs_tcs(const struct radv_shader *vs, const struct radv_shader *tcs, uint32_t *rsrc1_out,
2226*61046927SAndroid Build Coastguard Worker                                uint32_t *rsrc2_out)
2227*61046927SAndroid Build Coastguard Worker {
2228*61046927SAndroid Build Coastguard Worker    if (rsrc1_out) {
2229*61046927SAndroid Build Coastguard Worker       uint32_t rsrc1 = vs->config.rsrc1;
2230*61046927SAndroid Build Coastguard Worker 
2231*61046927SAndroid Build Coastguard Worker       if (G_00B848_VGPRS(tcs->config.rsrc1) > G_00B848_VGPRS(rsrc1))
2232*61046927SAndroid Build Coastguard Worker          rsrc1 = (rsrc1 & C_00B848_VGPRS) | (tcs->config.rsrc1 & ~C_00B848_VGPRS);
2233*61046927SAndroid Build Coastguard Worker       if (G_00B228_SGPRS(tcs->config.rsrc1) > G_00B228_SGPRS(rsrc1))
2234*61046927SAndroid Build Coastguard Worker          rsrc1 = (rsrc1 & C_00B228_SGPRS) | (tcs->config.rsrc1 & ~C_00B228_SGPRS);
2235*61046927SAndroid Build Coastguard Worker       if (G_00B428_LS_VGPR_COMP_CNT(tcs->config.rsrc1) > G_00B428_LS_VGPR_COMP_CNT(rsrc1))
2236*61046927SAndroid Build Coastguard Worker          rsrc1 = (rsrc1 & C_00B428_LS_VGPR_COMP_CNT) | (tcs->config.rsrc1 & ~C_00B428_LS_VGPR_COMP_CNT);
2237*61046927SAndroid Build Coastguard Worker 
2238*61046927SAndroid Build Coastguard Worker       *rsrc1_out = rsrc1;
2239*61046927SAndroid Build Coastguard Worker    }
2240*61046927SAndroid Build Coastguard Worker 
2241*61046927SAndroid Build Coastguard Worker    if (rsrc2_out) {
2242*61046927SAndroid Build Coastguard Worker       uint32_t rsrc2 = vs->config.rsrc2;
2243*61046927SAndroid Build Coastguard Worker 
2244*61046927SAndroid Build Coastguard Worker       rsrc2 |= tcs->config.rsrc2 & ~C_00B12C_SCRATCH_EN;
2245*61046927SAndroid Build Coastguard Worker 
2246*61046927SAndroid Build Coastguard Worker       *rsrc2_out = rsrc2;
2247*61046927SAndroid Build Coastguard Worker    }
2248*61046927SAndroid Build Coastguard Worker }
2249*61046927SAndroid Build Coastguard Worker 
2250*61046927SAndroid Build Coastguard Worker void
radv_shader_combine_cfg_vs_gs(const struct radv_shader * vs,const struct radv_shader * gs,uint32_t * rsrc1_out,uint32_t * rsrc2_out)2251*61046927SAndroid Build Coastguard Worker radv_shader_combine_cfg_vs_gs(const struct radv_shader *vs, const struct radv_shader *gs, uint32_t *rsrc1_out,
2252*61046927SAndroid Build Coastguard Worker                               uint32_t *rsrc2_out)
2253*61046927SAndroid Build Coastguard Worker {
2254*61046927SAndroid Build Coastguard Worker    assert(G_00B12C_USER_SGPR(vs->config.rsrc2) == G_00B12C_USER_SGPR(gs->config.rsrc2));
2255*61046927SAndroid Build Coastguard Worker 
2256*61046927SAndroid Build Coastguard Worker    if (rsrc1_out) {
2257*61046927SAndroid Build Coastguard Worker       uint32_t rsrc1 = vs->config.rsrc1;
2258*61046927SAndroid Build Coastguard Worker 
2259*61046927SAndroid Build Coastguard Worker       if (G_00B848_VGPRS(gs->config.rsrc1) > G_00B848_VGPRS(rsrc1))
2260*61046927SAndroid Build Coastguard Worker          rsrc1 = (rsrc1 & C_00B848_VGPRS) | (gs->config.rsrc1 & ~C_00B848_VGPRS);
2261*61046927SAndroid Build Coastguard Worker       if (G_00B228_SGPRS(gs->config.rsrc1) > G_00B228_SGPRS(rsrc1))
2262*61046927SAndroid Build Coastguard Worker          rsrc1 = (rsrc1 & C_00B228_SGPRS) | (gs->config.rsrc1 & ~C_00B228_SGPRS);
2263*61046927SAndroid Build Coastguard Worker       if (G_00B228_GS_VGPR_COMP_CNT(gs->config.rsrc1) > G_00B228_GS_VGPR_COMP_CNT(rsrc1))
2264*61046927SAndroid Build Coastguard Worker          rsrc1 = (rsrc1 & C_00B228_GS_VGPR_COMP_CNT) | (gs->config.rsrc1 & ~C_00B228_GS_VGPR_COMP_CNT);
2265*61046927SAndroid Build Coastguard Worker 
2266*61046927SAndroid Build Coastguard Worker       *rsrc1_out = rsrc1;
2267*61046927SAndroid Build Coastguard Worker    }
2268*61046927SAndroid Build Coastguard Worker 
2269*61046927SAndroid Build Coastguard Worker    if (rsrc2_out) {
2270*61046927SAndroid Build Coastguard Worker       uint32_t rsrc2 = vs->config.rsrc2;
2271*61046927SAndroid Build Coastguard Worker 
2272*61046927SAndroid Build Coastguard Worker       if (G_00B22C_ES_VGPR_COMP_CNT(gs->config.rsrc2) > G_00B22C_ES_VGPR_COMP_CNT(rsrc2))
2273*61046927SAndroid Build Coastguard Worker          rsrc2 = (rsrc2 & C_00B22C_ES_VGPR_COMP_CNT) | (gs->config.rsrc2 & ~C_00B22C_ES_VGPR_COMP_CNT);
2274*61046927SAndroid Build Coastguard Worker 
2275*61046927SAndroid Build Coastguard Worker       rsrc2 |= gs->config.rsrc2 & ~(C_00B12C_SCRATCH_EN & C_00B12C_SO_EN & C_00B12C_SO_BASE0_EN & C_00B12C_SO_BASE1_EN &
2276*61046927SAndroid Build Coastguard Worker                                     C_00B12C_SO_BASE2_EN & C_00B12C_SO_BASE3_EN);
2277*61046927SAndroid Build Coastguard Worker 
2278*61046927SAndroid Build Coastguard Worker       *rsrc2_out = rsrc2;
2279*61046927SAndroid Build Coastguard Worker    }
2280*61046927SAndroid Build Coastguard Worker }
2281*61046927SAndroid Build Coastguard Worker 
2282*61046927SAndroid Build Coastguard Worker void
radv_shader_combine_cfg_tes_gs(const struct radv_shader * tes,const struct radv_shader * gs,uint32_t * rsrc1_out,uint32_t * rsrc2_out)2283*61046927SAndroid Build Coastguard Worker radv_shader_combine_cfg_tes_gs(const struct radv_shader *tes, const struct radv_shader *gs, uint32_t *rsrc1_out,
2284*61046927SAndroid Build Coastguard Worker                                uint32_t *rsrc2_out)
2285*61046927SAndroid Build Coastguard Worker {
2286*61046927SAndroid Build Coastguard Worker    radv_shader_combine_cfg_vs_gs(tes, gs, rsrc1_out, rsrc2_out);
2287*61046927SAndroid Build Coastguard Worker 
2288*61046927SAndroid Build Coastguard Worker    if (rsrc2_out) {
2289*61046927SAndroid Build Coastguard Worker       *rsrc2_out |= S_00B22C_OC_LDS_EN(1);
2290*61046927SAndroid Build Coastguard Worker    }
2291*61046927SAndroid Build Coastguard Worker }
2292*61046927SAndroid Build Coastguard Worker 
2293*61046927SAndroid Build Coastguard Worker static bool
radv_shader_binary_upload(struct radv_device * device,const struct radv_shader_binary * binary,struct radv_shader * shader,void * dest_ptr)2294*61046927SAndroid Build Coastguard Worker radv_shader_binary_upload(struct radv_device *device, const struct radv_shader_binary *binary,
2295*61046927SAndroid Build Coastguard Worker                           struct radv_shader *shader, void *dest_ptr)
2296*61046927SAndroid Build Coastguard Worker {
2297*61046927SAndroid Build Coastguard Worker    shader->code = calloc(shader->code_size, 1);
2298*61046927SAndroid Build Coastguard Worker    if (!shader->code) {
2299*61046927SAndroid Build Coastguard Worker       radv_shader_unref(device, shader);
2300*61046927SAndroid Build Coastguard Worker       return false;
2301*61046927SAndroid Build Coastguard Worker    }
2302*61046927SAndroid Build Coastguard Worker 
2303*61046927SAndroid Build Coastguard Worker    if (binary->type == RADV_BINARY_TYPE_RTLD) {
2304*61046927SAndroid Build Coastguard Worker #if !defined(USE_LIBELF)
2305*61046927SAndroid Build Coastguard Worker       return false;
2306*61046927SAndroid Build Coastguard Worker #else
2307*61046927SAndroid Build Coastguard Worker       struct ac_rtld_binary rtld_binary = {0};
2308*61046927SAndroid Build Coastguard Worker 
2309*61046927SAndroid Build Coastguard Worker       if (!radv_open_rtld_binary(device, binary, &rtld_binary)) {
2310*61046927SAndroid Build Coastguard Worker          free(shader);
2311*61046927SAndroid Build Coastguard Worker          return false;
2312*61046927SAndroid Build Coastguard Worker       }
2313*61046927SAndroid Build Coastguard Worker 
2314*61046927SAndroid Build Coastguard Worker       struct ac_rtld_upload_info info = {
2315*61046927SAndroid Build Coastguard Worker          .binary = &rtld_binary,
2316*61046927SAndroid Build Coastguard Worker          .rx_va = radv_shader_get_va(shader),
2317*61046927SAndroid Build Coastguard Worker          .rx_ptr = dest_ptr,
2318*61046927SAndroid Build Coastguard Worker       };
2319*61046927SAndroid Build Coastguard Worker 
2320*61046927SAndroid Build Coastguard Worker       if (!ac_rtld_upload(&info)) {
2321*61046927SAndroid Build Coastguard Worker          radv_shader_unref(device, shader);
2322*61046927SAndroid Build Coastguard Worker          ac_rtld_close(&rtld_binary);
2323*61046927SAndroid Build Coastguard Worker          return false;
2324*61046927SAndroid Build Coastguard Worker       }
2325*61046927SAndroid Build Coastguard Worker 
2326*61046927SAndroid Build Coastguard Worker       ac_rtld_close(&rtld_binary);
2327*61046927SAndroid Build Coastguard Worker 
2328*61046927SAndroid Build Coastguard Worker       if (shader->code) {
2329*61046927SAndroid Build Coastguard Worker          /* Instead of running RTLD twice, just copy the relocated binary back from VRAM.
2330*61046927SAndroid Build Coastguard Worker           * Use streaming memcpy to reduce penalty of copying from uncachable memory.
2331*61046927SAndroid Build Coastguard Worker           */
2332*61046927SAndroid Build Coastguard Worker          util_streaming_load_memcpy(shader->code, dest_ptr, shader->code_size);
2333*61046927SAndroid Build Coastguard Worker       }
2334*61046927SAndroid Build Coastguard Worker #endif
2335*61046927SAndroid Build Coastguard Worker    } else {
2336*61046927SAndroid Build Coastguard Worker       struct radv_shader_binary_legacy *bin = (struct radv_shader_binary_legacy *)binary;
2337*61046927SAndroid Build Coastguard Worker       memcpy(dest_ptr, bin->data + bin->stats_size, bin->code_size);
2338*61046927SAndroid Build Coastguard Worker 
2339*61046927SAndroid Build Coastguard Worker       if (shader->code) {
2340*61046927SAndroid Build Coastguard Worker          memcpy(shader->code, bin->data + bin->stats_size, bin->code_size);
2341*61046927SAndroid Build Coastguard Worker       }
2342*61046927SAndroid Build Coastguard Worker    }
2343*61046927SAndroid Build Coastguard Worker 
2344*61046927SAndroid Build Coastguard Worker    return true;
2345*61046927SAndroid Build Coastguard Worker }
2346*61046927SAndroid Build Coastguard Worker 
2347*61046927SAndroid Build Coastguard Worker static VkResult
radv_shader_dma_resize_upload_buf(struct radv_device * device,struct radv_shader_dma_submission * submission,uint64_t size)2348*61046927SAndroid Build Coastguard Worker radv_shader_dma_resize_upload_buf(struct radv_device *device, struct radv_shader_dma_submission *submission,
2349*61046927SAndroid Build Coastguard Worker                                   uint64_t size)
2350*61046927SAndroid Build Coastguard Worker {
2351*61046927SAndroid Build Coastguard Worker    if (submission->bo)
2352*61046927SAndroid Build Coastguard Worker       radv_bo_destroy(device, NULL, submission->bo);
2353*61046927SAndroid Build Coastguard Worker 
2354*61046927SAndroid Build Coastguard Worker    VkResult result = radv_bo_create(
2355*61046927SAndroid Build Coastguard Worker       device, NULL, size, RADV_SHADER_ALLOC_ALIGNMENT, RADEON_DOMAIN_GTT,
2356*61046927SAndroid Build Coastguard Worker       RADEON_FLAG_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING | RADEON_FLAG_32BIT | RADEON_FLAG_GTT_WC,
2357*61046927SAndroid Build Coastguard Worker       RADV_BO_PRIORITY_UPLOAD_BUFFER, 0, true, &submission->bo);
2358*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
2359*61046927SAndroid Build Coastguard Worker       return result;
2360*61046927SAndroid Build Coastguard Worker 
2361*61046927SAndroid Build Coastguard Worker    submission->ptr = radv_buffer_map(device->ws, submission->bo);
2362*61046927SAndroid Build Coastguard Worker    submission->bo_size = size;
2363*61046927SAndroid Build Coastguard Worker 
2364*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
2365*61046927SAndroid Build Coastguard Worker }
2366*61046927SAndroid Build Coastguard Worker 
2367*61046927SAndroid Build Coastguard Worker struct radv_shader_dma_submission *
radv_shader_dma_pop_submission(struct radv_device * device)2368*61046927SAndroid Build Coastguard Worker radv_shader_dma_pop_submission(struct radv_device *device)
2369*61046927SAndroid Build Coastguard Worker {
2370*61046927SAndroid Build Coastguard Worker    struct radv_shader_dma_submission *submission;
2371*61046927SAndroid Build Coastguard Worker 
2372*61046927SAndroid Build Coastguard Worker    mtx_lock(&device->shader_dma_submission_list_mutex);
2373*61046927SAndroid Build Coastguard Worker 
2374*61046927SAndroid Build Coastguard Worker    while (list_is_empty(&device->shader_dma_submissions))
2375*61046927SAndroid Build Coastguard Worker       cnd_wait(&device->shader_dma_submission_list_cond, &device->shader_dma_submission_list_mutex);
2376*61046927SAndroid Build Coastguard Worker 
2377*61046927SAndroid Build Coastguard Worker    submission = list_first_entry(&device->shader_dma_submissions, struct radv_shader_dma_submission, list);
2378*61046927SAndroid Build Coastguard Worker    list_del(&submission->list);
2379*61046927SAndroid Build Coastguard Worker 
2380*61046927SAndroid Build Coastguard Worker    mtx_unlock(&device->shader_dma_submission_list_mutex);
2381*61046927SAndroid Build Coastguard Worker 
2382*61046927SAndroid Build Coastguard Worker    return submission;
2383*61046927SAndroid Build Coastguard Worker }
2384*61046927SAndroid Build Coastguard Worker 
2385*61046927SAndroid Build Coastguard Worker void
radv_shader_dma_push_submission(struct radv_device * device,struct radv_shader_dma_submission * submission,uint64_t seq)2386*61046927SAndroid Build Coastguard Worker radv_shader_dma_push_submission(struct radv_device *device, struct radv_shader_dma_submission *submission, uint64_t seq)
2387*61046927SAndroid Build Coastguard Worker {
2388*61046927SAndroid Build Coastguard Worker    submission->seq = seq;
2389*61046927SAndroid Build Coastguard Worker 
2390*61046927SAndroid Build Coastguard Worker    mtx_lock(&device->shader_dma_submission_list_mutex);
2391*61046927SAndroid Build Coastguard Worker 
2392*61046927SAndroid Build Coastguard Worker    list_addtail(&submission->list, &device->shader_dma_submissions);
2393*61046927SAndroid Build Coastguard Worker    cnd_signal(&device->shader_dma_submission_list_cond);
2394*61046927SAndroid Build Coastguard Worker 
2395*61046927SAndroid Build Coastguard Worker    mtx_unlock(&device->shader_dma_submission_list_mutex);
2396*61046927SAndroid Build Coastguard Worker }
2397*61046927SAndroid Build Coastguard Worker 
2398*61046927SAndroid Build Coastguard Worker struct radv_shader_dma_submission *
radv_shader_dma_get_submission(struct radv_device * device,struct radeon_winsys_bo * bo,uint64_t va,uint64_t size)2399*61046927SAndroid Build Coastguard Worker radv_shader_dma_get_submission(struct radv_device *device, struct radeon_winsys_bo *bo, uint64_t va, uint64_t size)
2400*61046927SAndroid Build Coastguard Worker {
2401*61046927SAndroid Build Coastguard Worker    struct radv_shader_dma_submission *submission = radv_shader_dma_pop_submission(device);
2402*61046927SAndroid Build Coastguard Worker    struct radeon_cmdbuf *cs = submission->cs;
2403*61046927SAndroid Build Coastguard Worker    struct radeon_winsys *ws = device->ws;
2404*61046927SAndroid Build Coastguard Worker    VkResult result;
2405*61046927SAndroid Build Coastguard Worker 
2406*61046927SAndroid Build Coastguard Worker    /* Wait for potentially in-flight submission to settle */
2407*61046927SAndroid Build Coastguard Worker    result = radv_shader_wait_for_upload(device, submission->seq);
2408*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
2409*61046927SAndroid Build Coastguard Worker       goto fail;
2410*61046927SAndroid Build Coastguard Worker 
2411*61046927SAndroid Build Coastguard Worker    ws->cs_reset(cs);
2412*61046927SAndroid Build Coastguard Worker 
2413*61046927SAndroid Build Coastguard Worker    if (submission->bo_size < size) {
2414*61046927SAndroid Build Coastguard Worker       result = radv_shader_dma_resize_upload_buf(device, submission, size);
2415*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
2416*61046927SAndroid Build Coastguard Worker          goto fail;
2417*61046927SAndroid Build Coastguard Worker    }
2418*61046927SAndroid Build Coastguard Worker 
2419*61046927SAndroid Build Coastguard Worker    radv_sdma_copy_buffer(device, cs, radv_buffer_get_va(submission->bo), va, size);
2420*61046927SAndroid Build Coastguard Worker    radv_cs_add_buffer(ws, cs, submission->bo);
2421*61046927SAndroid Build Coastguard Worker    radv_cs_add_buffer(ws, cs, bo);
2422*61046927SAndroid Build Coastguard Worker 
2423*61046927SAndroid Build Coastguard Worker    result = ws->cs_finalize(cs);
2424*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
2425*61046927SAndroid Build Coastguard Worker       goto fail;
2426*61046927SAndroid Build Coastguard Worker 
2427*61046927SAndroid Build Coastguard Worker    return submission;
2428*61046927SAndroid Build Coastguard Worker 
2429*61046927SAndroid Build Coastguard Worker fail:
2430*61046927SAndroid Build Coastguard Worker    radv_shader_dma_push_submission(device, submission, 0);
2431*61046927SAndroid Build Coastguard Worker 
2432*61046927SAndroid Build Coastguard Worker    return NULL;
2433*61046927SAndroid Build Coastguard Worker }
2434*61046927SAndroid Build Coastguard Worker 
2435*61046927SAndroid Build Coastguard Worker /*
2436*61046927SAndroid Build Coastguard Worker  * If upload_seq_out is NULL, this function blocks until the DMA is complete. Otherwise, the
2437*61046927SAndroid Build Coastguard Worker  * semaphore value to wait on device->shader_upload_sem is stored in *upload_seq_out.
2438*61046927SAndroid Build Coastguard Worker  */
2439*61046927SAndroid Build Coastguard Worker bool
radv_shader_dma_submit(struct radv_device * device,struct radv_shader_dma_submission * submission,uint64_t * upload_seq_out)2440*61046927SAndroid Build Coastguard Worker radv_shader_dma_submit(struct radv_device *device, struct radv_shader_dma_submission *submission,
2441*61046927SAndroid Build Coastguard Worker                        uint64_t *upload_seq_out)
2442*61046927SAndroid Build Coastguard Worker {
2443*61046927SAndroid Build Coastguard Worker    struct radeon_cmdbuf *cs = submission->cs;
2444*61046927SAndroid Build Coastguard Worker    struct radeon_winsys *ws = device->ws;
2445*61046927SAndroid Build Coastguard Worker    VkResult result;
2446*61046927SAndroid Build Coastguard Worker 
2447*61046927SAndroid Build Coastguard Worker    mtx_lock(&device->shader_upload_hw_ctx_mutex);
2448*61046927SAndroid Build Coastguard Worker 
2449*61046927SAndroid Build Coastguard Worker    uint64_t upload_seq = device->shader_upload_seq + 1;
2450*61046927SAndroid Build Coastguard Worker 
2451*61046927SAndroid Build Coastguard Worker    struct vk_semaphore *semaphore = vk_semaphore_from_handle(device->shader_upload_sem);
2452*61046927SAndroid Build Coastguard Worker    struct vk_sync *sync = vk_semaphore_get_active_sync(semaphore);
2453*61046927SAndroid Build Coastguard Worker    const struct vk_sync_signal signal_info = {
2454*61046927SAndroid Build Coastguard Worker       .sync = sync,
2455*61046927SAndroid Build Coastguard Worker       .signal_value = upload_seq,
2456*61046927SAndroid Build Coastguard Worker       .stage_mask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
2457*61046927SAndroid Build Coastguard Worker    };
2458*61046927SAndroid Build Coastguard Worker 
2459*61046927SAndroid Build Coastguard Worker    struct radv_winsys_submit_info submit = {
2460*61046927SAndroid Build Coastguard Worker       .ip_type = AMD_IP_SDMA,
2461*61046927SAndroid Build Coastguard Worker       .queue_index = 0,
2462*61046927SAndroid Build Coastguard Worker       .cs_array = &cs,
2463*61046927SAndroid Build Coastguard Worker       .cs_count = 1,
2464*61046927SAndroid Build Coastguard Worker    };
2465*61046927SAndroid Build Coastguard Worker 
2466*61046927SAndroid Build Coastguard Worker    result = ws->cs_submit(device->shader_upload_hw_ctx, &submit, 0, NULL, 1, &signal_info);
2467*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
2468*61046927SAndroid Build Coastguard Worker       mtx_unlock(&device->shader_upload_hw_ctx_mutex);
2469*61046927SAndroid Build Coastguard Worker       radv_shader_dma_push_submission(device, submission, 0);
2470*61046927SAndroid Build Coastguard Worker       return false;
2471*61046927SAndroid Build Coastguard Worker    }
2472*61046927SAndroid Build Coastguard Worker    device->shader_upload_seq = upload_seq;
2473*61046927SAndroid Build Coastguard Worker    mtx_unlock(&device->shader_upload_hw_ctx_mutex);
2474*61046927SAndroid Build Coastguard Worker 
2475*61046927SAndroid Build Coastguard Worker    radv_shader_dma_push_submission(device, submission, upload_seq);
2476*61046927SAndroid Build Coastguard Worker 
2477*61046927SAndroid Build Coastguard Worker    if (upload_seq_out) {
2478*61046927SAndroid Build Coastguard Worker       *upload_seq_out = upload_seq;
2479*61046927SAndroid Build Coastguard Worker    } else {
2480*61046927SAndroid Build Coastguard Worker       result = radv_shader_wait_for_upload(device, upload_seq);
2481*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
2482*61046927SAndroid Build Coastguard Worker          return false;
2483*61046927SAndroid Build Coastguard Worker    }
2484*61046927SAndroid Build Coastguard Worker 
2485*61046927SAndroid Build Coastguard Worker    return true;
2486*61046927SAndroid Build Coastguard Worker }
2487*61046927SAndroid Build Coastguard Worker 
2488*61046927SAndroid Build Coastguard Worker static bool
radv_shader_upload(struct radv_device * device,struct radv_shader * shader,const struct radv_shader_binary * binary)2489*61046927SAndroid Build Coastguard Worker radv_shader_upload(struct radv_device *device, struct radv_shader *shader, const struct radv_shader_binary *binary)
2490*61046927SAndroid Build Coastguard Worker {
2491*61046927SAndroid Build Coastguard Worker    if (device->shader_use_invisible_vram) {
2492*61046927SAndroid Build Coastguard Worker       struct radv_shader_dma_submission *submission =
2493*61046927SAndroid Build Coastguard Worker          radv_shader_dma_get_submission(device, shader->bo, shader->va, shader->code_size);
2494*61046927SAndroid Build Coastguard Worker       if (!submission)
2495*61046927SAndroid Build Coastguard Worker          return false;
2496*61046927SAndroid Build Coastguard Worker 
2497*61046927SAndroid Build Coastguard Worker       if (!radv_shader_binary_upload(device, binary, shader, submission->ptr)) {
2498*61046927SAndroid Build Coastguard Worker          radv_shader_dma_push_submission(device, submission, 0);
2499*61046927SAndroid Build Coastguard Worker          return false;
2500*61046927SAndroid Build Coastguard Worker       }
2501*61046927SAndroid Build Coastguard Worker 
2502*61046927SAndroid Build Coastguard Worker       if (!radv_shader_dma_submit(device, submission, &shader->upload_seq))
2503*61046927SAndroid Build Coastguard Worker          return false;
2504*61046927SAndroid Build Coastguard Worker    } else {
2505*61046927SAndroid Build Coastguard Worker       void *dest_ptr = shader->alloc->arena->ptr + shader->alloc->offset;
2506*61046927SAndroid Build Coastguard Worker 
2507*61046927SAndroid Build Coastguard Worker       if (!radv_shader_binary_upload(device, binary, shader, dest_ptr))
2508*61046927SAndroid Build Coastguard Worker          return false;
2509*61046927SAndroid Build Coastguard Worker    }
2510*61046927SAndroid Build Coastguard Worker    return true;
2511*61046927SAndroid Build Coastguard Worker }
2512*61046927SAndroid Build Coastguard Worker 
2513*61046927SAndroid Build Coastguard Worker unsigned
radv_get_max_waves(const struct radv_device * device,const struct ac_shader_config * conf,const struct radv_shader_info * info)2514*61046927SAndroid Build Coastguard Worker radv_get_max_waves(const struct radv_device *device, const struct ac_shader_config *conf,
2515*61046927SAndroid Build Coastguard Worker                    const struct radv_shader_info *info)
2516*61046927SAndroid Build Coastguard Worker {
2517*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
2518*61046927SAndroid Build Coastguard Worker    const struct radeon_info *gpu_info = &pdev->info;
2519*61046927SAndroid Build Coastguard Worker    const enum amd_gfx_level gfx_level = gpu_info->gfx_level;
2520*61046927SAndroid Build Coastguard Worker    const uint8_t wave_size = info->wave_size;
2521*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage = info->stage;
2522*61046927SAndroid Build Coastguard Worker    unsigned max_simd_waves = gpu_info->max_waves_per_simd;
2523*61046927SAndroid Build Coastguard Worker    unsigned lds_per_wave = 0;
2524*61046927SAndroid Build Coastguard Worker 
2525*61046927SAndroid Build Coastguard Worker    if (stage == MESA_SHADER_FRAGMENT) {
2526*61046927SAndroid Build Coastguard Worker       lds_per_wave = conf->lds_size * gpu_info->lds_encode_granularity + info->ps.num_interp * 48;
2527*61046927SAndroid Build Coastguard Worker       lds_per_wave = align(lds_per_wave, gpu_info->lds_alloc_granularity);
2528*61046927SAndroid Build Coastguard Worker    } else if (stage == MESA_SHADER_COMPUTE || stage == MESA_SHADER_TASK) {
2529*61046927SAndroid Build Coastguard Worker       unsigned max_workgroup_size = info->workgroup_size;
2530*61046927SAndroid Build Coastguard Worker       lds_per_wave = align(conf->lds_size * gpu_info->lds_encode_granularity, gpu_info->lds_alloc_granularity);
2531*61046927SAndroid Build Coastguard Worker       lds_per_wave /= DIV_ROUND_UP(max_workgroup_size, wave_size);
2532*61046927SAndroid Build Coastguard Worker    }
2533*61046927SAndroid Build Coastguard Worker 
2534*61046927SAndroid Build Coastguard Worker    if (conf->num_sgprs && gfx_level < GFX10) {
2535*61046927SAndroid Build Coastguard Worker       unsigned sgprs = align(conf->num_sgprs, gfx_level >= GFX8 ? 16 : 8);
2536*61046927SAndroid Build Coastguard Worker       max_simd_waves = MIN2(max_simd_waves, gpu_info->num_physical_sgprs_per_simd / sgprs);
2537*61046927SAndroid Build Coastguard Worker    }
2538*61046927SAndroid Build Coastguard Worker 
2539*61046927SAndroid Build Coastguard Worker    if (conf->num_vgprs) {
2540*61046927SAndroid Build Coastguard Worker       unsigned physical_vgprs = gpu_info->num_physical_wave64_vgprs_per_simd * (64 / wave_size);
2541*61046927SAndroid Build Coastguard Worker       unsigned vgprs = align(conf->num_vgprs, wave_size == 32 ? 8 : 4);
2542*61046927SAndroid Build Coastguard Worker       if (gfx_level >= GFX10_3) {
2543*61046927SAndroid Build Coastguard Worker          unsigned real_vgpr_gran = gpu_info->num_physical_wave64_vgprs_per_simd / 64;
2544*61046927SAndroid Build Coastguard Worker          vgprs = util_align_npot(vgprs, real_vgpr_gran * (wave_size == 32 ? 2 : 1));
2545*61046927SAndroid Build Coastguard Worker       }
2546*61046927SAndroid Build Coastguard Worker       max_simd_waves = MIN2(max_simd_waves, physical_vgprs / vgprs);
2547*61046927SAndroid Build Coastguard Worker    }
2548*61046927SAndroid Build Coastguard Worker 
2549*61046927SAndroid Build Coastguard Worker    unsigned simd_per_workgroup = gpu_info->num_simd_per_compute_unit;
2550*61046927SAndroid Build Coastguard Worker    if (gfx_level >= GFX10)
2551*61046927SAndroid Build Coastguard Worker       simd_per_workgroup *= 2; /* like lds_size_per_workgroup, assume WGP on GFX10+ */
2552*61046927SAndroid Build Coastguard Worker 
2553*61046927SAndroid Build Coastguard Worker    unsigned max_lds_per_simd = gpu_info->lds_size_per_workgroup / simd_per_workgroup;
2554*61046927SAndroid Build Coastguard Worker    if (lds_per_wave)
2555*61046927SAndroid Build Coastguard Worker       max_simd_waves = MIN2(max_simd_waves, DIV_ROUND_UP(max_lds_per_simd, lds_per_wave));
2556*61046927SAndroid Build Coastguard Worker 
2557*61046927SAndroid Build Coastguard Worker    return gfx_level >= GFX10 ? max_simd_waves * (wave_size / 32) : max_simd_waves;
2558*61046927SAndroid Build Coastguard Worker }
2559*61046927SAndroid Build Coastguard Worker 
2560*61046927SAndroid Build Coastguard Worker unsigned
radv_get_max_scratch_waves(const struct radv_device * device,struct radv_shader * shader)2561*61046927SAndroid Build Coastguard Worker radv_get_max_scratch_waves(const struct radv_device *device, struct radv_shader *shader)
2562*61046927SAndroid Build Coastguard Worker {
2563*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
2564*61046927SAndroid Build Coastguard Worker    const unsigned num_cu = pdev->info.num_cu;
2565*61046927SAndroid Build Coastguard Worker 
2566*61046927SAndroid Build Coastguard Worker    return MIN2(device->scratch_waves, 4 * num_cu * shader->max_waves);
2567*61046927SAndroid Build Coastguard Worker }
2568*61046927SAndroid Build Coastguard Worker 
2569*61046927SAndroid Build Coastguard Worker VkResult
radv_shader_create_uncached(struct radv_device * device,const struct radv_shader_binary * binary,bool replayable,struct radv_serialized_shader_arena_block * replay_block,struct radv_shader ** out_shader)2570*61046927SAndroid Build Coastguard Worker radv_shader_create_uncached(struct radv_device *device, const struct radv_shader_binary *binary, bool replayable,
2571*61046927SAndroid Build Coastguard Worker                             struct radv_serialized_shader_arena_block *replay_block, struct radv_shader **out_shader)
2572*61046927SAndroid Build Coastguard Worker {
2573*61046927SAndroid Build Coastguard Worker    VkResult result = VK_SUCCESS;
2574*61046927SAndroid Build Coastguard Worker    struct radv_shader *shader = calloc(1, sizeof(struct radv_shader));
2575*61046927SAndroid Build Coastguard Worker    if (!shader) {
2576*61046927SAndroid Build Coastguard Worker       result = VK_ERROR_OUT_OF_HOST_MEMORY;
2577*61046927SAndroid Build Coastguard Worker       goto out;
2578*61046927SAndroid Build Coastguard Worker    }
2579*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&shader->replay_mtx, mtx_plain);
2580*61046927SAndroid Build Coastguard Worker 
2581*61046927SAndroid Build Coastguard Worker    _mesa_blake3_compute(binary, binary->total_size, shader->hash);
2582*61046927SAndroid Build Coastguard Worker 
2583*61046927SAndroid Build Coastguard Worker    vk_pipeline_cache_object_init(&device->vk, &shader->base, &radv_shader_ops, shader->hash, sizeof(shader->hash));
2584*61046927SAndroid Build Coastguard Worker 
2585*61046927SAndroid Build Coastguard Worker    shader->info = binary->info;
2586*61046927SAndroid Build Coastguard Worker    shader->config = binary->config;
2587*61046927SAndroid Build Coastguard Worker    shader->max_waves = radv_get_max_waves(device, &shader->config, &shader->info);
2588*61046927SAndroid Build Coastguard Worker 
2589*61046927SAndroid Build Coastguard Worker    if (binary->type == RADV_BINARY_TYPE_RTLD) {
2590*61046927SAndroid Build Coastguard Worker #if !defined(USE_LIBELF)
2591*61046927SAndroid Build Coastguard Worker       goto out;
2592*61046927SAndroid Build Coastguard Worker #else
2593*61046927SAndroid Build Coastguard Worker       struct ac_rtld_binary rtld_binary = {0};
2594*61046927SAndroid Build Coastguard Worker 
2595*61046927SAndroid Build Coastguard Worker       if (!radv_open_rtld_binary(device, binary, &rtld_binary)) {
2596*61046927SAndroid Build Coastguard Worker          result = VK_ERROR_OUT_OF_HOST_MEMORY;
2597*61046927SAndroid Build Coastguard Worker          goto out;
2598*61046927SAndroid Build Coastguard Worker       }
2599*61046927SAndroid Build Coastguard Worker 
2600*61046927SAndroid Build Coastguard Worker       shader->code_size = rtld_binary.rx_size;
2601*61046927SAndroid Build Coastguard Worker       shader->exec_size = rtld_binary.exec_size;
2602*61046927SAndroid Build Coastguard Worker       ac_rtld_close(&rtld_binary);
2603*61046927SAndroid Build Coastguard Worker #endif
2604*61046927SAndroid Build Coastguard Worker    } else {
2605*61046927SAndroid Build Coastguard Worker       struct radv_shader_binary_legacy *bin = (struct radv_shader_binary_legacy *)binary;
2606*61046927SAndroid Build Coastguard Worker 
2607*61046927SAndroid Build Coastguard Worker       shader->code_size = bin->code_size;
2608*61046927SAndroid Build Coastguard Worker       shader->exec_size = bin->exec_size;
2609*61046927SAndroid Build Coastguard Worker 
2610*61046927SAndroid Build Coastguard Worker       if (bin->stats_size) {
2611*61046927SAndroid Build Coastguard Worker          shader->statistics = calloc(bin->stats_size, 1);
2612*61046927SAndroid Build Coastguard Worker          memcpy(shader->statistics, bin->data, bin->stats_size);
2613*61046927SAndroid Build Coastguard Worker       }
2614*61046927SAndroid Build Coastguard Worker    }
2615*61046927SAndroid Build Coastguard Worker 
2616*61046927SAndroid Build Coastguard Worker    if (replay_block) {
2617*61046927SAndroid Build Coastguard Worker       shader->alloc = radv_replay_shader_arena_block(device, replay_block, shader);
2618*61046927SAndroid Build Coastguard Worker       if (!shader->alloc) {
2619*61046927SAndroid Build Coastguard Worker          result = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS;
2620*61046927SAndroid Build Coastguard Worker          goto out;
2621*61046927SAndroid Build Coastguard Worker       }
2622*61046927SAndroid Build Coastguard Worker 
2623*61046927SAndroid Build Coastguard Worker       shader->has_replay_alloc = true;
2624*61046927SAndroid Build Coastguard Worker    } else {
2625*61046927SAndroid Build Coastguard Worker       shader->alloc = radv_alloc_shader_memory(device, shader->code_size, replayable, shader);
2626*61046927SAndroid Build Coastguard Worker       if (!shader->alloc) {
2627*61046927SAndroid Build Coastguard Worker          result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
2628*61046927SAndroid Build Coastguard Worker          goto out;
2629*61046927SAndroid Build Coastguard Worker       }
2630*61046927SAndroid Build Coastguard Worker    }
2631*61046927SAndroid Build Coastguard Worker 
2632*61046927SAndroid Build Coastguard Worker    shader->bo = shader->alloc->arena->bo;
2633*61046927SAndroid Build Coastguard Worker    shader->va = radv_buffer_get_va(shader->bo) + shader->alloc->offset;
2634*61046927SAndroid Build Coastguard Worker 
2635*61046927SAndroid Build Coastguard Worker    if (!radv_shader_upload(device, shader, binary)) {
2636*61046927SAndroid Build Coastguard Worker       result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
2637*61046927SAndroid Build Coastguard Worker       goto out;
2638*61046927SAndroid Build Coastguard Worker    }
2639*61046927SAndroid Build Coastguard Worker 
2640*61046927SAndroid Build Coastguard Worker    *out_shader = shader;
2641*61046927SAndroid Build Coastguard Worker 
2642*61046927SAndroid Build Coastguard Worker out:
2643*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
2644*61046927SAndroid Build Coastguard Worker       free(shader);
2645*61046927SAndroid Build Coastguard Worker       *out_shader = NULL;
2646*61046927SAndroid Build Coastguard Worker    }
2647*61046927SAndroid Build Coastguard Worker 
2648*61046927SAndroid Build Coastguard Worker    return result;
2649*61046927SAndroid Build Coastguard Worker }
2650*61046927SAndroid Build Coastguard Worker 
2651*61046927SAndroid Build Coastguard Worker bool
radv_shader_reupload(struct radv_device * device,struct radv_shader * shader)2652*61046927SAndroid Build Coastguard Worker radv_shader_reupload(struct radv_device *device, struct radv_shader *shader)
2653*61046927SAndroid Build Coastguard Worker {
2654*61046927SAndroid Build Coastguard Worker    if (device->shader_use_invisible_vram) {
2655*61046927SAndroid Build Coastguard Worker       struct radv_shader_dma_submission *submission =
2656*61046927SAndroid Build Coastguard Worker          radv_shader_dma_get_submission(device, shader->bo, shader->va, shader->code_size);
2657*61046927SAndroid Build Coastguard Worker       if (!submission)
2658*61046927SAndroid Build Coastguard Worker          return false;
2659*61046927SAndroid Build Coastguard Worker 
2660*61046927SAndroid Build Coastguard Worker       memcpy(submission->ptr, shader->code, shader->code_size);
2661*61046927SAndroid Build Coastguard Worker 
2662*61046927SAndroid Build Coastguard Worker       if (!radv_shader_dma_submit(device, submission, &shader->upload_seq))
2663*61046927SAndroid Build Coastguard Worker          return false;
2664*61046927SAndroid Build Coastguard Worker    } else {
2665*61046927SAndroid Build Coastguard Worker       void *dest_ptr = shader->alloc->arena->ptr + shader->alloc->offset;
2666*61046927SAndroid Build Coastguard Worker       memcpy(dest_ptr, shader->code, shader->code_size);
2667*61046927SAndroid Build Coastguard Worker    }
2668*61046927SAndroid Build Coastguard Worker    return true;
2669*61046927SAndroid Build Coastguard Worker }
2670*61046927SAndroid Build Coastguard Worker 
2671*61046927SAndroid Build Coastguard Worker static bool
radv_shader_part_binary_upload(struct radv_device * device,const struct radv_shader_part_binary * bin,struct radv_shader_part * shader_part)2672*61046927SAndroid Build Coastguard Worker radv_shader_part_binary_upload(struct radv_device *device, const struct radv_shader_part_binary *bin,
2673*61046927SAndroid Build Coastguard Worker                                struct radv_shader_part *shader_part)
2674*61046927SAndroid Build Coastguard Worker {
2675*61046927SAndroid Build Coastguard Worker    struct radv_shader_dma_submission *submission = NULL;
2676*61046927SAndroid Build Coastguard Worker    void *dest_ptr;
2677*61046927SAndroid Build Coastguard Worker 
2678*61046927SAndroid Build Coastguard Worker    if (device->shader_use_invisible_vram) {
2679*61046927SAndroid Build Coastguard Worker       uint64_t va = radv_buffer_get_va(shader_part->alloc->arena->bo) + shader_part->alloc->offset;
2680*61046927SAndroid Build Coastguard Worker       submission = radv_shader_dma_get_submission(device, shader_part->alloc->arena->bo, va, bin->code_size);
2681*61046927SAndroid Build Coastguard Worker       if (!submission)
2682*61046927SAndroid Build Coastguard Worker          return false;
2683*61046927SAndroid Build Coastguard Worker 
2684*61046927SAndroid Build Coastguard Worker       dest_ptr = submission->ptr;
2685*61046927SAndroid Build Coastguard Worker    } else {
2686*61046927SAndroid Build Coastguard Worker       dest_ptr = shader_part->alloc->arena->ptr + shader_part->alloc->offset;
2687*61046927SAndroid Build Coastguard Worker    }
2688*61046927SAndroid Build Coastguard Worker 
2689*61046927SAndroid Build Coastguard Worker    memcpy(dest_ptr, bin->data, bin->code_size);
2690*61046927SAndroid Build Coastguard Worker 
2691*61046927SAndroid Build Coastguard Worker    if (device->shader_use_invisible_vram) {
2692*61046927SAndroid Build Coastguard Worker       if (!radv_shader_dma_submit(device, submission, &shader_part->upload_seq))
2693*61046927SAndroid Build Coastguard Worker          return false;
2694*61046927SAndroid Build Coastguard Worker    }
2695*61046927SAndroid Build Coastguard Worker 
2696*61046927SAndroid Build Coastguard Worker    return true;
2697*61046927SAndroid Build Coastguard Worker }
2698*61046927SAndroid Build Coastguard Worker 
2699*61046927SAndroid Build Coastguard Worker struct radv_shader_part *
radv_shader_part_create(struct radv_device * device,struct radv_shader_part_binary * binary,unsigned wave_size)2700*61046927SAndroid Build Coastguard Worker radv_shader_part_create(struct radv_device *device, struct radv_shader_part_binary *binary, unsigned wave_size)
2701*61046927SAndroid Build Coastguard Worker {
2702*61046927SAndroid Build Coastguard Worker    struct radv_shader_part *shader_part;
2703*61046927SAndroid Build Coastguard Worker 
2704*61046927SAndroid Build Coastguard Worker    shader_part = calloc(1, sizeof(struct radv_shader_part));
2705*61046927SAndroid Build Coastguard Worker    if (!shader_part)
2706*61046927SAndroid Build Coastguard Worker       return NULL;
2707*61046927SAndroid Build Coastguard Worker 
2708*61046927SAndroid Build Coastguard Worker    shader_part->ref_count = 1;
2709*61046927SAndroid Build Coastguard Worker    shader_part->code_size = binary->code_size;
2710*61046927SAndroid Build Coastguard Worker    shader_part->rsrc1 =
2711*61046927SAndroid Build Coastguard Worker       S_00B848_VGPRS((binary->num_vgprs - 1) / (wave_size == 32 ? 8 : 4)) | S_00B228_SGPRS((binary->num_sgprs - 1) / 8);
2712*61046927SAndroid Build Coastguard Worker    shader_part->disasm_string = binary->disasm_size ? strdup((const char *)(binary->data + binary->code_size)) : NULL;
2713*61046927SAndroid Build Coastguard Worker 
2714*61046927SAndroid Build Coastguard Worker    shader_part->spi_shader_col_format = binary->info.spi_shader_col_format;
2715*61046927SAndroid Build Coastguard Worker    shader_part->cb_shader_mask = binary->info.cb_shader_mask;
2716*61046927SAndroid Build Coastguard Worker    shader_part->spi_shader_z_format = binary->info.spi_shader_z_format;
2717*61046927SAndroid Build Coastguard Worker 
2718*61046927SAndroid Build Coastguard Worker    /* Allocate memory and upload. */
2719*61046927SAndroid Build Coastguard Worker    shader_part->alloc = radv_alloc_shader_memory(device, shader_part->code_size, false, NULL);
2720*61046927SAndroid Build Coastguard Worker    if (!shader_part->alloc)
2721*61046927SAndroid Build Coastguard Worker       goto fail;
2722*61046927SAndroid Build Coastguard Worker 
2723*61046927SAndroid Build Coastguard Worker    shader_part->bo = shader_part->alloc->arena->bo;
2724*61046927SAndroid Build Coastguard Worker    shader_part->va = radv_buffer_get_va(shader_part->bo) + shader_part->alloc->offset;
2725*61046927SAndroid Build Coastguard Worker 
2726*61046927SAndroid Build Coastguard Worker    if (!radv_shader_part_binary_upload(device, binary, shader_part))
2727*61046927SAndroid Build Coastguard Worker       goto fail;
2728*61046927SAndroid Build Coastguard Worker 
2729*61046927SAndroid Build Coastguard Worker    return shader_part;
2730*61046927SAndroid Build Coastguard Worker 
2731*61046927SAndroid Build Coastguard Worker fail:
2732*61046927SAndroid Build Coastguard Worker    radv_shader_part_destroy(device, shader_part);
2733*61046927SAndroid Build Coastguard Worker    return NULL;
2734*61046927SAndroid Build Coastguard Worker }
2735*61046927SAndroid Build Coastguard Worker 
2736*61046927SAndroid Build Coastguard Worker bool
radv_shader_part_cache_init(struct radv_shader_part_cache * cache,struct radv_shader_part_cache_ops * ops)2737*61046927SAndroid Build Coastguard Worker radv_shader_part_cache_init(struct radv_shader_part_cache *cache, struct radv_shader_part_cache_ops *ops)
2738*61046927SAndroid Build Coastguard Worker {
2739*61046927SAndroid Build Coastguard Worker    cache->ops = ops;
2740*61046927SAndroid Build Coastguard Worker    if (!_mesa_set_init(&cache->entries, NULL, cache->ops->hash, cache->ops->equals))
2741*61046927SAndroid Build Coastguard Worker       return false;
2742*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&cache->lock, mtx_plain);
2743*61046927SAndroid Build Coastguard Worker    return true;
2744*61046927SAndroid Build Coastguard Worker }
2745*61046927SAndroid Build Coastguard Worker 
2746*61046927SAndroid Build Coastguard Worker void
radv_shader_part_cache_finish(struct radv_device * device,struct radv_shader_part_cache * cache)2747*61046927SAndroid Build Coastguard Worker radv_shader_part_cache_finish(struct radv_device *device, struct radv_shader_part_cache *cache)
2748*61046927SAndroid Build Coastguard Worker {
2749*61046927SAndroid Build Coastguard Worker    set_foreach (&cache->entries, entry)
2750*61046927SAndroid Build Coastguard Worker       radv_shader_part_unref(device, radv_shader_part_from_cache_entry(entry->key));
2751*61046927SAndroid Build Coastguard Worker    simple_mtx_destroy(&cache->lock);
2752*61046927SAndroid Build Coastguard Worker    ralloc_free(cache->entries.table);
2753*61046927SAndroid Build Coastguard Worker }
2754*61046927SAndroid Build Coastguard Worker 
2755*61046927SAndroid Build Coastguard Worker /*
2756*61046927SAndroid Build Coastguard Worker  * A cache with atomics-free fast path for prolog / epilog lookups.
2757*61046927SAndroid Build Coastguard Worker  *
2758*61046927SAndroid Build Coastguard Worker  * VS prologs and PS/TCS epilogs are used to support dynamic states. In
2759*61046927SAndroid Build Coastguard Worker  * particular dynamic blend state is heavily used by Zink. These are called
2760*61046927SAndroid Build Coastguard Worker  * every frame as a part of command buffer building, so these functions are
2761*61046927SAndroid Build Coastguard Worker  * on the hot path.
2762*61046927SAndroid Build Coastguard Worker  *
2763*61046927SAndroid Build Coastguard Worker  * Originally this was implemented with a rwlock, but this lead to high
2764*61046927SAndroid Build Coastguard Worker  * overhead. To avoid locking altogether in the hot path, the cache is done
2765*61046927SAndroid Build Coastguard Worker  * at two levels: one at device level, and another at each CS. Access to the
2766*61046927SAndroid Build Coastguard Worker  * CS cache is externally synchronized and do not require a lock.
2767*61046927SAndroid Build Coastguard Worker  */
2768*61046927SAndroid Build Coastguard Worker struct radv_shader_part *
radv_shader_part_cache_get(struct radv_device * device,struct radv_shader_part_cache * cache,struct set * local_entries,const void * key)2769*61046927SAndroid Build Coastguard Worker radv_shader_part_cache_get(struct radv_device *device, struct radv_shader_part_cache *cache, struct set *local_entries,
2770*61046927SAndroid Build Coastguard Worker                            const void *key)
2771*61046927SAndroid Build Coastguard Worker {
2772*61046927SAndroid Build Coastguard Worker    struct set_entry *local, *global;
2773*61046927SAndroid Build Coastguard Worker    bool local_found, global_found;
2774*61046927SAndroid Build Coastguard Worker    uint32_t hash = cache->ops->hash(key);
2775*61046927SAndroid Build Coastguard Worker 
2776*61046927SAndroid Build Coastguard Worker    local = _mesa_set_search_or_add_pre_hashed(local_entries, hash, key, &local_found);
2777*61046927SAndroid Build Coastguard Worker    if (local_found)
2778*61046927SAndroid Build Coastguard Worker       return radv_shader_part_from_cache_entry(local->key);
2779*61046927SAndroid Build Coastguard Worker 
2780*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&cache->lock);
2781*61046927SAndroid Build Coastguard Worker    global = _mesa_set_search_or_add_pre_hashed(&cache->entries, hash, key, &global_found);
2782*61046927SAndroid Build Coastguard Worker    if (global_found) {
2783*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&cache->lock);
2784*61046927SAndroid Build Coastguard Worker       local->key = global->key;
2785*61046927SAndroid Build Coastguard Worker       return radv_shader_part_from_cache_entry(global->key);
2786*61046927SAndroid Build Coastguard Worker    }
2787*61046927SAndroid Build Coastguard Worker 
2788*61046927SAndroid Build Coastguard Worker    struct radv_shader_part *shader_part = cache->ops->create(device, key);
2789*61046927SAndroid Build Coastguard Worker    if (!shader_part) {
2790*61046927SAndroid Build Coastguard Worker       _mesa_set_remove(&cache->entries, global);
2791*61046927SAndroid Build Coastguard Worker       simple_mtx_unlock(&cache->lock);
2792*61046927SAndroid Build Coastguard Worker       _mesa_set_remove(local_entries, local);
2793*61046927SAndroid Build Coastguard Worker       return NULL;
2794*61046927SAndroid Build Coastguard Worker    }
2795*61046927SAndroid Build Coastguard Worker 
2796*61046927SAndroid Build Coastguard Worker    /* Make the set entry a pointer to the key, so that the hash and equals
2797*61046927SAndroid Build Coastguard Worker     * functions from radv_shader_part_cache_ops can be directly used.
2798*61046927SAndroid Build Coastguard Worker     */
2799*61046927SAndroid Build Coastguard Worker    global->key = &shader_part->key;
2800*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&cache->lock);
2801*61046927SAndroid Build Coastguard Worker    local->key = &shader_part->key;
2802*61046927SAndroid Build Coastguard Worker    return shader_part;
2803*61046927SAndroid Build Coastguard Worker }
2804*61046927SAndroid Build Coastguard Worker 
2805*61046927SAndroid Build Coastguard Worker static char *
radv_dump_nir_shaders(struct nir_shader * const * shaders,int shader_count)2806*61046927SAndroid Build Coastguard Worker radv_dump_nir_shaders(struct nir_shader *const *shaders, int shader_count)
2807*61046927SAndroid Build Coastguard Worker {
2808*61046927SAndroid Build Coastguard Worker    char *data = NULL;
2809*61046927SAndroid Build Coastguard Worker    char *ret = NULL;
2810*61046927SAndroid Build Coastguard Worker    size_t size = 0;
2811*61046927SAndroid Build Coastguard Worker    struct u_memstream mem;
2812*61046927SAndroid Build Coastguard Worker    if (u_memstream_open(&mem, &data, &size)) {
2813*61046927SAndroid Build Coastguard Worker       FILE *const memf = u_memstream_get(&mem);
2814*61046927SAndroid Build Coastguard Worker       for (int i = 0; i < shader_count; ++i)
2815*61046927SAndroid Build Coastguard Worker          nir_print_shader(shaders[i], memf);
2816*61046927SAndroid Build Coastguard Worker       u_memstream_close(&mem);
2817*61046927SAndroid Build Coastguard Worker    }
2818*61046927SAndroid Build Coastguard Worker 
2819*61046927SAndroid Build Coastguard Worker    ret = malloc(size + 1);
2820*61046927SAndroid Build Coastguard Worker    if (ret) {
2821*61046927SAndroid Build Coastguard Worker       memcpy(ret, data, size);
2822*61046927SAndroid Build Coastguard Worker       ret[size] = 0;
2823*61046927SAndroid Build Coastguard Worker    }
2824*61046927SAndroid Build Coastguard Worker    free(data);
2825*61046927SAndroid Build Coastguard Worker    return ret;
2826*61046927SAndroid Build Coastguard Worker }
2827*61046927SAndroid Build Coastguard Worker 
2828*61046927SAndroid Build Coastguard Worker static void
radv_aco_build_shader_binary(void ** bin,const struct ac_shader_config * config,const char * llvm_ir_str,unsigned llvm_ir_size,const char * disasm_str,unsigned disasm_size,uint32_t * statistics,uint32_t stats_size,uint32_t exec_size,const uint32_t * code,uint32_t code_dw,const struct aco_symbol * symbols,unsigned num_symbols)2829*61046927SAndroid Build Coastguard Worker radv_aco_build_shader_binary(void **bin, const struct ac_shader_config *config, const char *llvm_ir_str,
2830*61046927SAndroid Build Coastguard Worker                              unsigned llvm_ir_size, const char *disasm_str, unsigned disasm_size, uint32_t *statistics,
2831*61046927SAndroid Build Coastguard Worker                              uint32_t stats_size, uint32_t exec_size, const uint32_t *code, uint32_t code_dw,
2832*61046927SAndroid Build Coastguard Worker                              const struct aco_symbol *symbols, unsigned num_symbols)
2833*61046927SAndroid Build Coastguard Worker {
2834*61046927SAndroid Build Coastguard Worker    struct radv_shader_binary **binary = (struct radv_shader_binary **)bin;
2835*61046927SAndroid Build Coastguard Worker    size_t size = llvm_ir_size;
2836*61046927SAndroid Build Coastguard Worker 
2837*61046927SAndroid Build Coastguard Worker    size += disasm_size;
2838*61046927SAndroid Build Coastguard Worker    size += stats_size;
2839*61046927SAndroid Build Coastguard Worker 
2840*61046927SAndroid Build Coastguard Worker    size += code_dw * sizeof(uint32_t) + sizeof(struct radv_shader_binary_legacy);
2841*61046927SAndroid Build Coastguard Worker 
2842*61046927SAndroid Build Coastguard Worker    /* We need to calloc to prevent uninitialized data because this will be used
2843*61046927SAndroid Build Coastguard Worker     * directly for the disk cache. Uninitialized data can appear because of
2844*61046927SAndroid Build Coastguard Worker     * padding in the struct or because legacy_binary->data can be at an offset
2845*61046927SAndroid Build Coastguard Worker     * from the start less than sizeof(radv_shader_binary_legacy). */
2846*61046927SAndroid Build Coastguard Worker    struct radv_shader_binary_legacy *legacy_binary = (struct radv_shader_binary_legacy *)calloc(size, 1);
2847*61046927SAndroid Build Coastguard Worker    legacy_binary->base.type = RADV_BINARY_TYPE_LEGACY;
2848*61046927SAndroid Build Coastguard Worker    legacy_binary->base.total_size = size;
2849*61046927SAndroid Build Coastguard Worker    legacy_binary->base.config = *config;
2850*61046927SAndroid Build Coastguard Worker 
2851*61046927SAndroid Build Coastguard Worker    if (stats_size)
2852*61046927SAndroid Build Coastguard Worker       memcpy(legacy_binary->data, statistics, stats_size);
2853*61046927SAndroid Build Coastguard Worker    legacy_binary->stats_size = stats_size;
2854*61046927SAndroid Build Coastguard Worker 
2855*61046927SAndroid Build Coastguard Worker    memcpy(legacy_binary->data + legacy_binary->stats_size, code, code_dw * sizeof(uint32_t));
2856*61046927SAndroid Build Coastguard Worker    legacy_binary->exec_size = exec_size;
2857*61046927SAndroid Build Coastguard Worker    legacy_binary->code_size = code_dw * sizeof(uint32_t);
2858*61046927SAndroid Build Coastguard Worker 
2859*61046927SAndroid Build Coastguard Worker    legacy_binary->disasm_size = 0;
2860*61046927SAndroid Build Coastguard Worker    legacy_binary->ir_size = llvm_ir_size;
2861*61046927SAndroid Build Coastguard Worker 
2862*61046927SAndroid Build Coastguard Worker    if (llvm_ir_size) {
2863*61046927SAndroid Build Coastguard Worker       memcpy((char *)legacy_binary->data + legacy_binary->stats_size + legacy_binary->code_size, llvm_ir_str,
2864*61046927SAndroid Build Coastguard Worker              llvm_ir_size);
2865*61046927SAndroid Build Coastguard Worker    }
2866*61046927SAndroid Build Coastguard Worker 
2867*61046927SAndroid Build Coastguard Worker    legacy_binary->disasm_size = disasm_size;
2868*61046927SAndroid Build Coastguard Worker    if (disasm_size) {
2869*61046927SAndroid Build Coastguard Worker       memcpy((char *)legacy_binary->data + legacy_binary->stats_size + legacy_binary->code_size + llvm_ir_size,
2870*61046927SAndroid Build Coastguard Worker              disasm_str, disasm_size);
2871*61046927SAndroid Build Coastguard Worker    }
2872*61046927SAndroid Build Coastguard Worker    *binary = (struct radv_shader_binary *)legacy_binary;
2873*61046927SAndroid Build Coastguard Worker }
2874*61046927SAndroid Build Coastguard Worker 
2875*61046927SAndroid Build Coastguard Worker static void
radv_fill_nir_compiler_options(struct radv_nir_compiler_options * options,struct radv_device * device,const struct radv_graphics_state_key * gfx_state,bool should_use_wgp,bool can_dump_shader,bool is_meta_shader,bool keep_shader_info,bool keep_statistic_info)2876*61046927SAndroid Build Coastguard Worker radv_fill_nir_compiler_options(struct radv_nir_compiler_options *options, struct radv_device *device,
2877*61046927SAndroid Build Coastguard Worker                                const struct radv_graphics_state_key *gfx_state, bool should_use_wgp,
2878*61046927SAndroid Build Coastguard Worker                                bool can_dump_shader, bool is_meta_shader, bool keep_shader_info,
2879*61046927SAndroid Build Coastguard Worker                                bool keep_statistic_info)
2880*61046927SAndroid Build Coastguard Worker {
2881*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
2882*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
2883*61046927SAndroid Build Coastguard Worker 
2884*61046927SAndroid Build Coastguard Worker    /* robust_buffer_access_llvm here used by LLVM only, pipeline robustness is not exposed there. */
2885*61046927SAndroid Build Coastguard Worker    options->robust_buffer_access_llvm =
2886*61046927SAndroid Build Coastguard Worker       (device->vk.enabled_features.robustBufferAccess2 || device->vk.enabled_features.robustBufferAccess);
2887*61046927SAndroid Build Coastguard Worker    options->wgp_mode = should_use_wgp;
2888*61046927SAndroid Build Coastguard Worker    options->info = &pdev->info;
2889*61046927SAndroid Build Coastguard Worker    options->dump_shader = can_dump_shader;
2890*61046927SAndroid Build Coastguard Worker    options->dump_preoptir = options->dump_shader && instance->debug_flags & RADV_DEBUG_PREOPTIR;
2891*61046927SAndroid Build Coastguard Worker    options->record_ir = keep_shader_info;
2892*61046927SAndroid Build Coastguard Worker    options->record_stats = keep_statistic_info;
2893*61046927SAndroid Build Coastguard Worker    options->check_ir = instance->debug_flags & RADV_DEBUG_CHECKIR;
2894*61046927SAndroid Build Coastguard Worker    options->enable_mrt_output_nan_fixup = gfx_state ? gfx_state->ps.epilog.enable_mrt_output_nan_fixup : false;
2895*61046927SAndroid Build Coastguard Worker }
2896*61046927SAndroid Build Coastguard Worker 
2897*61046927SAndroid Build Coastguard Worker void
radv_set_stage_key_robustness(const struct vk_pipeline_robustness_state * rs,gl_shader_stage stage,struct radv_shader_stage_key * key)2898*61046927SAndroid Build Coastguard Worker radv_set_stage_key_robustness(const struct vk_pipeline_robustness_state *rs, gl_shader_stage stage,
2899*61046927SAndroid Build Coastguard Worker                               struct radv_shader_stage_key *key)
2900*61046927SAndroid Build Coastguard Worker {
2901*61046927SAndroid Build Coastguard Worker    if (rs->storage_buffers == VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT)
2902*61046927SAndroid Build Coastguard Worker       key->storage_robustness2 = 1;
2903*61046927SAndroid Build Coastguard Worker    if (rs->uniform_buffers == VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT)
2904*61046927SAndroid Build Coastguard Worker       key->uniform_robustness2 = 1;
2905*61046927SAndroid Build Coastguard Worker    if (stage == MESA_SHADER_VERTEX &&
2906*61046927SAndroid Build Coastguard Worker        (rs->vertex_inputs == VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT ||
2907*61046927SAndroid Build Coastguard Worker         rs->vertex_inputs == VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT))
2908*61046927SAndroid Build Coastguard Worker       key->vertex_robustness1 = 1u;
2909*61046927SAndroid Build Coastguard Worker }
2910*61046927SAndroid Build Coastguard Worker 
2911*61046927SAndroid Build Coastguard Worker static void
radv_capture_shader_executable_info(struct radv_device * device,struct radv_shader * shader,struct nir_shader * const * shaders,int shader_count,const struct radv_shader_binary * binary)2912*61046927SAndroid Build Coastguard Worker radv_capture_shader_executable_info(struct radv_device *device, struct radv_shader *shader,
2913*61046927SAndroid Build Coastguard Worker                                     struct nir_shader *const *shaders, int shader_count,
2914*61046927SAndroid Build Coastguard Worker                                     const struct radv_shader_binary *binary)
2915*61046927SAndroid Build Coastguard Worker {
2916*61046927SAndroid Build Coastguard Worker    shader->nir_string = radv_dump_nir_shaders(shaders, shader_count);
2917*61046927SAndroid Build Coastguard Worker 
2918*61046927SAndroid Build Coastguard Worker    if (binary->type == RADV_BINARY_TYPE_RTLD) {
2919*61046927SAndroid Build Coastguard Worker #if !defined(USE_LIBELF)
2920*61046927SAndroid Build Coastguard Worker       return;
2921*61046927SAndroid Build Coastguard Worker #else
2922*61046927SAndroid Build Coastguard Worker       struct radv_shader_binary_rtld *bin = (struct radv_shader_binary_rtld *)binary;
2923*61046927SAndroid Build Coastguard Worker       struct ac_rtld_binary rtld_binary = {0};
2924*61046927SAndroid Build Coastguard Worker 
2925*61046927SAndroid Build Coastguard Worker       if (!radv_open_rtld_binary(device, binary, &rtld_binary)) {
2926*61046927SAndroid Build Coastguard Worker          return;
2927*61046927SAndroid Build Coastguard Worker       }
2928*61046927SAndroid Build Coastguard Worker 
2929*61046927SAndroid Build Coastguard Worker       const char *disasm_data;
2930*61046927SAndroid Build Coastguard Worker       size_t disasm_size;
2931*61046927SAndroid Build Coastguard Worker       if (!ac_rtld_get_section_by_name(&rtld_binary, ".AMDGPU.disasm", &disasm_data, &disasm_size)) {
2932*61046927SAndroid Build Coastguard Worker          return;
2933*61046927SAndroid Build Coastguard Worker       }
2934*61046927SAndroid Build Coastguard Worker 
2935*61046927SAndroid Build Coastguard Worker       shader->ir_string = bin->llvm_ir_size ? strdup((const char *)(bin->data + bin->elf_size)) : NULL;
2936*61046927SAndroid Build Coastguard Worker       shader->disasm_string = malloc(disasm_size + 1);
2937*61046927SAndroid Build Coastguard Worker       memcpy(shader->disasm_string, disasm_data, disasm_size);
2938*61046927SAndroid Build Coastguard Worker       shader->disasm_string[disasm_size] = 0;
2939*61046927SAndroid Build Coastguard Worker 
2940*61046927SAndroid Build Coastguard Worker       ac_rtld_close(&rtld_binary);
2941*61046927SAndroid Build Coastguard Worker #endif
2942*61046927SAndroid Build Coastguard Worker    } else {
2943*61046927SAndroid Build Coastguard Worker       struct radv_shader_binary_legacy *bin = (struct radv_shader_binary_legacy *)binary;
2944*61046927SAndroid Build Coastguard Worker 
2945*61046927SAndroid Build Coastguard Worker       shader->ir_string = bin->ir_size ? strdup((const char *)(bin->data + bin->stats_size + bin->code_size)) : NULL;
2946*61046927SAndroid Build Coastguard Worker       shader->disasm_string =
2947*61046927SAndroid Build Coastguard Worker          bin->disasm_size ? strdup((const char *)(bin->data + bin->stats_size + bin->code_size + bin->ir_size)) : NULL;
2948*61046927SAndroid Build Coastguard Worker    }
2949*61046927SAndroid Build Coastguard Worker }
2950*61046927SAndroid Build Coastguard Worker 
2951*61046927SAndroid Build Coastguard Worker static struct radv_shader_binary *
shader_compile(struct radv_device * device,struct nir_shader * const * shaders,int shader_count,gl_shader_stage stage,const struct radv_shader_info * info,const struct radv_shader_args * args,const struct radv_shader_stage_key * stage_key,struct radv_nir_compiler_options * options)2952*61046927SAndroid Build Coastguard Worker shader_compile(struct radv_device *device, struct nir_shader *const *shaders, int shader_count, gl_shader_stage stage,
2953*61046927SAndroid Build Coastguard Worker                const struct radv_shader_info *info, const struct radv_shader_args *args,
2954*61046927SAndroid Build Coastguard Worker                const struct radv_shader_stage_key *stage_key, struct radv_nir_compiler_options *options)
2955*61046927SAndroid Build Coastguard Worker {
2956*61046927SAndroid Build Coastguard Worker    struct radv_shader_debug_data debug_data = {
2957*61046927SAndroid Build Coastguard Worker       .device = device,
2958*61046927SAndroid Build Coastguard Worker       .object = NULL,
2959*61046927SAndroid Build Coastguard Worker    };
2960*61046927SAndroid Build Coastguard Worker    options->debug.func = radv_compiler_debug;
2961*61046927SAndroid Build Coastguard Worker    options->debug.private_data = &debug_data;
2962*61046927SAndroid Build Coastguard Worker 
2963*61046927SAndroid Build Coastguard Worker    struct radv_shader_binary *binary = NULL;
2964*61046927SAndroid Build Coastguard Worker 
2965*61046927SAndroid Build Coastguard Worker #if AMD_LLVM_AVAILABLE
2966*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
2967*61046927SAndroid Build Coastguard Worker 
2968*61046927SAndroid Build Coastguard Worker    if (radv_use_llvm_for_stage(pdev, stage) || options->dump_shader || options->record_ir)
2969*61046927SAndroid Build Coastguard Worker       ac_init_llvm_once();
2970*61046927SAndroid Build Coastguard Worker 
2971*61046927SAndroid Build Coastguard Worker    if (radv_use_llvm_for_stage(pdev, stage)) {
2972*61046927SAndroid Build Coastguard Worker       llvm_compile_shader(options, info, shader_count, shaders, &binary, args);
2973*61046927SAndroid Build Coastguard Worker #else
2974*61046927SAndroid Build Coastguard Worker    if (false) {
2975*61046927SAndroid Build Coastguard Worker #endif
2976*61046927SAndroid Build Coastguard Worker    } else {
2977*61046927SAndroid Build Coastguard Worker       struct aco_shader_info ac_info;
2978*61046927SAndroid Build Coastguard Worker       struct aco_compiler_options ac_opts;
2979*61046927SAndroid Build Coastguard Worker       radv_aco_convert_opts(&ac_opts, options, args, stage_key);
2980*61046927SAndroid Build Coastguard Worker       radv_aco_convert_shader_info(&ac_info, info, args, &device->cache_key, options->info->gfx_level);
2981*61046927SAndroid Build Coastguard Worker       aco_compile_shader(&ac_opts, &ac_info, shader_count, shaders, &args->ac, &radv_aco_build_shader_binary,
2982*61046927SAndroid Build Coastguard Worker                          (void **)&binary);
2983*61046927SAndroid Build Coastguard Worker    }
2984*61046927SAndroid Build Coastguard Worker 
2985*61046927SAndroid Build Coastguard Worker    binary->info = *info;
2986*61046927SAndroid Build Coastguard Worker 
2987*61046927SAndroid Build Coastguard Worker    if (!radv_postprocess_binary_config(device, binary, args)) {
2988*61046927SAndroid Build Coastguard Worker       free(binary);
2989*61046927SAndroid Build Coastguard Worker       return NULL;
2990*61046927SAndroid Build Coastguard Worker    }
2991*61046927SAndroid Build Coastguard Worker 
2992*61046927SAndroid Build Coastguard Worker    return binary;
2993*61046927SAndroid Build Coastguard Worker }
2994*61046927SAndroid Build Coastguard Worker 
2995*61046927SAndroid Build Coastguard Worker struct radv_shader_binary *
2996*61046927SAndroid Build Coastguard Worker radv_shader_nir_to_asm(struct radv_device *device, struct radv_shader_stage *pl_stage,
2997*61046927SAndroid Build Coastguard Worker                        struct nir_shader *const *shaders, int shader_count,
2998*61046927SAndroid Build Coastguard Worker                        const struct radv_graphics_state_key *gfx_state, bool keep_shader_info, bool keep_statistic_info)
2999*61046927SAndroid Build Coastguard Worker {
3000*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage = shaders[shader_count - 1]->info.stage;
3001*61046927SAndroid Build Coastguard Worker    struct radv_shader_info *info = &pl_stage->info;
3002*61046927SAndroid Build Coastguard Worker 
3003*61046927SAndroid Build Coastguard Worker    struct radv_nir_compiler_options options = {0};
3004*61046927SAndroid Build Coastguard Worker    radv_fill_nir_compiler_options(&options, device, gfx_state, radv_should_use_wgp_mode(device, stage, info),
3005*61046927SAndroid Build Coastguard Worker                                   radv_can_dump_shader(device, shaders[0], false), is_meta_shader(shaders[0]),
3006*61046927SAndroid Build Coastguard Worker                                   keep_shader_info, keep_statistic_info);
3007*61046927SAndroid Build Coastguard Worker 
3008*61046927SAndroid Build Coastguard Worker    struct radv_shader_binary *binary =
3009*61046927SAndroid Build Coastguard Worker       shader_compile(device, shaders, shader_count, stage, info, &pl_stage->args, &pl_stage->key, &options);
3010*61046927SAndroid Build Coastguard Worker 
3011*61046927SAndroid Build Coastguard Worker    return binary;
3012*61046927SAndroid Build Coastguard Worker }
3013*61046927SAndroid Build Coastguard Worker 
3014*61046927SAndroid Build Coastguard Worker void
3015*61046927SAndroid Build Coastguard Worker radv_shader_generate_debug_info(struct radv_device *device, bool dump_shader, bool keep_shader_info,
3016*61046927SAndroid Build Coastguard Worker                                 struct radv_shader_binary *binary, struct radv_shader *shader,
3017*61046927SAndroid Build Coastguard Worker                                 struct nir_shader *const *shaders, int shader_count, struct radv_shader_info *info)
3018*61046927SAndroid Build Coastguard Worker {
3019*61046927SAndroid Build Coastguard Worker    if (dump_shader || keep_shader_info)
3020*61046927SAndroid Build Coastguard Worker       radv_capture_shader_executable_info(device, shader, shaders, shader_count, binary);
3021*61046927SAndroid Build Coastguard Worker 
3022*61046927SAndroid Build Coastguard Worker    if (dump_shader) {
3023*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "%s", radv_get_shader_name(info, shaders[0]->info.stage));
3024*61046927SAndroid Build Coastguard Worker       for (int i = 1; i < shader_count; ++i)
3025*61046927SAndroid Build Coastguard Worker          fprintf(stderr, " + %s", radv_get_shader_name(info, shaders[i]->info.stage));
3026*61046927SAndroid Build Coastguard Worker 
3027*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "\ndisasm:\n%s\n", shader->disasm_string);
3028*61046927SAndroid Build Coastguard Worker    }
3029*61046927SAndroid Build Coastguard Worker }
3030*61046927SAndroid Build Coastguard Worker 
3031*61046927SAndroid Build Coastguard Worker struct radv_shader *
3032*61046927SAndroid Build Coastguard Worker radv_create_trap_handler_shader(struct radv_device *device)
3033*61046927SAndroid Build Coastguard Worker {
3034*61046927SAndroid Build Coastguard Worker    gl_shader_stage stage = MESA_SHADER_COMPUTE;
3035*61046927SAndroid Build Coastguard Worker    struct radv_shader_stage_key stage_key = {0};
3036*61046927SAndroid Build Coastguard Worker    struct radv_shader_info info = {0};
3037*61046927SAndroid Build Coastguard Worker    struct radv_nir_compiler_options options = {0};
3038*61046927SAndroid Build Coastguard Worker    radv_fill_nir_compiler_options(&options, device, NULL, radv_should_use_wgp_mode(device, stage, &info), false, false,
3039*61046927SAndroid Build Coastguard Worker                                   false, false);
3040*61046927SAndroid Build Coastguard Worker 
3041*61046927SAndroid Build Coastguard Worker    nir_builder b = radv_meta_init_shader(device, stage, "meta_trap_handler");
3042*61046927SAndroid Build Coastguard Worker 
3043*61046927SAndroid Build Coastguard Worker    info.wave_size = 64;
3044*61046927SAndroid Build Coastguard Worker    info.type = RADV_SHADER_TYPE_TRAP_HANDLER;
3045*61046927SAndroid Build Coastguard Worker 
3046*61046927SAndroid Build Coastguard Worker    struct radv_shader_args args;
3047*61046927SAndroid Build Coastguard Worker    radv_declare_shader_args(device, NULL, &info, stage, MESA_SHADER_NONE, &args);
3048*61046927SAndroid Build Coastguard Worker 
3049*61046927SAndroid Build Coastguard Worker    struct radv_shader_binary *binary = shader_compile(device, &b.shader, 1, stage, &info, &args, &stage_key, &options);
3050*61046927SAndroid Build Coastguard Worker    struct radv_shader *shader;
3051*61046927SAndroid Build Coastguard Worker    radv_shader_create_uncached(device, binary, false, NULL, &shader);
3052*61046927SAndroid Build Coastguard Worker 
3053*61046927SAndroid Build Coastguard Worker    ralloc_free(b.shader);
3054*61046927SAndroid Build Coastguard Worker    free(binary);
3055*61046927SAndroid Build Coastguard Worker 
3056*61046927SAndroid Build Coastguard Worker    return shader;
3057*61046927SAndroid Build Coastguard Worker }
3058*61046927SAndroid Build Coastguard Worker 
3059*61046927SAndroid Build Coastguard Worker static void
3060*61046927SAndroid Build Coastguard Worker radv_aco_build_shader_part(void **bin, uint32_t num_sgprs, uint32_t num_vgprs, const uint32_t *code, uint32_t code_size,
3061*61046927SAndroid Build Coastguard Worker                            const char *disasm_str, uint32_t disasm_size)
3062*61046927SAndroid Build Coastguard Worker {
3063*61046927SAndroid Build Coastguard Worker    struct radv_shader_part_binary **binary = (struct radv_shader_part_binary **)bin;
3064*61046927SAndroid Build Coastguard Worker    size_t size = code_size * sizeof(uint32_t) + sizeof(struct radv_shader_part_binary);
3065*61046927SAndroid Build Coastguard Worker 
3066*61046927SAndroid Build Coastguard Worker    size += disasm_size;
3067*61046927SAndroid Build Coastguard Worker    struct radv_shader_part_binary *part_binary = (struct radv_shader_part_binary *)calloc(size, 1);
3068*61046927SAndroid Build Coastguard Worker 
3069*61046927SAndroid Build Coastguard Worker    part_binary->num_sgprs = num_sgprs;
3070*61046927SAndroid Build Coastguard Worker    part_binary->num_vgprs = num_vgprs;
3071*61046927SAndroid Build Coastguard Worker    part_binary->total_size = size;
3072*61046927SAndroid Build Coastguard Worker    part_binary->code_size = code_size * sizeof(uint32_t);
3073*61046927SAndroid Build Coastguard Worker    memcpy(part_binary->data, code, part_binary->code_size);
3074*61046927SAndroid Build Coastguard Worker    if (disasm_size) {
3075*61046927SAndroid Build Coastguard Worker       memcpy((char *)part_binary->data + part_binary->code_size, disasm_str, disasm_size);
3076*61046927SAndroid Build Coastguard Worker       part_binary->disasm_size = disasm_size;
3077*61046927SAndroid Build Coastguard Worker    }
3078*61046927SAndroid Build Coastguard Worker 
3079*61046927SAndroid Build Coastguard Worker    *binary = part_binary;
3080*61046927SAndroid Build Coastguard Worker }
3081*61046927SAndroid Build Coastguard Worker 
3082*61046927SAndroid Build Coastguard Worker struct radv_shader *
3083*61046927SAndroid Build Coastguard Worker radv_create_rt_prolog(struct radv_device *device)
3084*61046927SAndroid Build Coastguard Worker {
3085*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
3086*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
3087*61046927SAndroid Build Coastguard Worker    struct radv_shader *prolog;
3088*61046927SAndroid Build Coastguard Worker    struct radv_shader_args in_args = {0};
3089*61046927SAndroid Build Coastguard Worker    struct radv_shader_args out_args = {0};
3090*61046927SAndroid Build Coastguard Worker    struct radv_nir_compiler_options options = {0};
3091*61046927SAndroid Build Coastguard Worker    radv_fill_nir_compiler_options(&options, device, NULL, false, instance->debug_flags & RADV_DEBUG_DUMP_PROLOGS, false,
3092*61046927SAndroid Build Coastguard Worker                                   radv_device_fault_detection_enabled(device), false);
3093*61046927SAndroid Build Coastguard Worker    struct radv_shader_info info = {0};
3094*61046927SAndroid Build Coastguard Worker    info.stage = MESA_SHADER_COMPUTE;
3095*61046927SAndroid Build Coastguard Worker    info.loads_push_constants = true;
3096*61046927SAndroid Build Coastguard Worker    info.desc_set_used_mask = -1; /* just to force indirection */
3097*61046927SAndroid Build Coastguard Worker    info.wave_size = pdev->rt_wave_size;
3098*61046927SAndroid Build Coastguard Worker    info.workgroup_size = info.wave_size;
3099*61046927SAndroid Build Coastguard Worker    info.user_data_0 = R_00B900_COMPUTE_USER_DATA_0;
3100*61046927SAndroid Build Coastguard Worker    info.type = RADV_SHADER_TYPE_RT_PROLOG;
3101*61046927SAndroid Build Coastguard Worker    info.cs.block_size[0] = 8;
3102*61046927SAndroid Build Coastguard Worker    info.cs.block_size[1] = pdev->rt_wave_size == 64 ? 8 : 4;
3103*61046927SAndroid Build Coastguard Worker    info.cs.block_size[2] = 1;
3104*61046927SAndroid Build Coastguard Worker    info.cs.uses_thread_id[0] = true;
3105*61046927SAndroid Build Coastguard Worker    info.cs.uses_thread_id[1] = true;
3106*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < 3; i++)
3107*61046927SAndroid Build Coastguard Worker       info.cs.uses_block_id[i] = true;
3108*61046927SAndroid Build Coastguard Worker 
3109*61046927SAndroid Build Coastguard Worker    radv_declare_shader_args(device, NULL, &info, MESA_SHADER_COMPUTE, MESA_SHADER_NONE, &in_args);
3110*61046927SAndroid Build Coastguard Worker    radv_declare_rt_shader_args(options.info->gfx_level, &out_args);
3111*61046927SAndroid Build Coastguard Worker    info.user_sgprs_locs = in_args.user_sgprs_locs;
3112*61046927SAndroid Build Coastguard Worker 
3113*61046927SAndroid Build Coastguard Worker #if AMD_LLVM_AVAILABLE
3114*61046927SAndroid Build Coastguard Worker    if (options.dump_shader || options.record_ir)
3115*61046927SAndroid Build Coastguard Worker       ac_init_llvm_once();
3116*61046927SAndroid Build Coastguard Worker #endif
3117*61046927SAndroid Build Coastguard Worker 
3118*61046927SAndroid Build Coastguard Worker    struct radv_shader_binary *binary = NULL;
3119*61046927SAndroid Build Coastguard Worker    struct radv_shader_stage_key stage_key = {0};
3120*61046927SAndroid Build Coastguard Worker    struct aco_shader_info ac_info;
3121*61046927SAndroid Build Coastguard Worker    struct aco_compiler_options ac_opts;
3122*61046927SAndroid Build Coastguard Worker    radv_aco_convert_shader_info(&ac_info, &info, &in_args, &device->cache_key, options.info->gfx_level);
3123*61046927SAndroid Build Coastguard Worker    radv_aco_convert_opts(&ac_opts, &options, &in_args, &stage_key);
3124*61046927SAndroid Build Coastguard Worker    aco_compile_rt_prolog(&ac_opts, &ac_info, &in_args.ac, &out_args.ac, &radv_aco_build_shader_binary,
3125*61046927SAndroid Build Coastguard Worker                          (void **)&binary);
3126*61046927SAndroid Build Coastguard Worker    binary->info = info;
3127*61046927SAndroid Build Coastguard Worker 
3128*61046927SAndroid Build Coastguard Worker    radv_postprocess_binary_config(device, binary, &in_args);
3129*61046927SAndroid Build Coastguard Worker    radv_shader_create_uncached(device, binary, false, NULL, &prolog);
3130*61046927SAndroid Build Coastguard Worker    if (!prolog)
3131*61046927SAndroid Build Coastguard Worker       goto done;
3132*61046927SAndroid Build Coastguard Worker 
3133*61046927SAndroid Build Coastguard Worker    if (device->keep_shader_info || options.dump_shader) {
3134*61046927SAndroid Build Coastguard Worker       radv_capture_shader_executable_info(device, prolog, NULL, 0, binary);
3135*61046927SAndroid Build Coastguard Worker    }
3136*61046927SAndroid Build Coastguard Worker 
3137*61046927SAndroid Build Coastguard Worker    if (options.dump_shader) {
3138*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "Raytracing prolog");
3139*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "\ndisasm:\n%s\n", prolog->disasm_string);
3140*61046927SAndroid Build Coastguard Worker    }
3141*61046927SAndroid Build Coastguard Worker 
3142*61046927SAndroid Build Coastguard Worker done:
3143*61046927SAndroid Build Coastguard Worker    free(binary);
3144*61046927SAndroid Build Coastguard Worker    return prolog;
3145*61046927SAndroid Build Coastguard Worker }
3146*61046927SAndroid Build Coastguard Worker 
3147*61046927SAndroid Build Coastguard Worker struct radv_shader_part *
3148*61046927SAndroid Build Coastguard Worker radv_create_vs_prolog(struct radv_device *device, const struct radv_vs_prolog_key *key)
3149*61046927SAndroid Build Coastguard Worker {
3150*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
3151*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
3152*61046927SAndroid Build Coastguard Worker    struct radv_shader_part *prolog;
3153*61046927SAndroid Build Coastguard Worker    struct radv_shader_args args = {0};
3154*61046927SAndroid Build Coastguard Worker    struct radv_nir_compiler_options options = {0};
3155*61046927SAndroid Build Coastguard Worker    radv_fill_nir_compiler_options(&options, device, NULL, false, instance->debug_flags & RADV_DEBUG_DUMP_PROLOGS, false,
3156*61046927SAndroid Build Coastguard Worker                                   radv_device_fault_detection_enabled(device), false);
3157*61046927SAndroid Build Coastguard Worker 
3158*61046927SAndroid Build Coastguard Worker    struct radv_shader_info info = {0};
3159*61046927SAndroid Build Coastguard Worker    info.stage = MESA_SHADER_VERTEX;
3160*61046927SAndroid Build Coastguard Worker    info.wave_size = key->wave32 ? 32 : 64;
3161*61046927SAndroid Build Coastguard Worker    info.vs.needs_instance_id = true;
3162*61046927SAndroid Build Coastguard Worker    info.vs.needs_base_instance = true;
3163*61046927SAndroid Build Coastguard Worker    info.vs.needs_draw_id = true;
3164*61046927SAndroid Build Coastguard Worker    info.vs.use_per_attribute_vb_descs = true;
3165*61046927SAndroid Build Coastguard Worker    info.vs.vb_desc_usage_mask = BITFIELD_MASK(key->num_attributes);
3166*61046927SAndroid Build Coastguard Worker    info.vs.has_prolog = true;
3167*61046927SAndroid Build Coastguard Worker    info.vs.as_ls = key->as_ls;
3168*61046927SAndroid Build Coastguard Worker    info.is_ngg = key->is_ngg;
3169*61046927SAndroid Build Coastguard Worker 
3170*61046927SAndroid Build Coastguard Worker    struct radv_graphics_state_key gfx_state = {0};
3171*61046927SAndroid Build Coastguard Worker 
3172*61046927SAndroid Build Coastguard Worker    radv_declare_shader_args(device, &gfx_state, &info, key->next_stage,
3173*61046927SAndroid Build Coastguard Worker                             key->next_stage != MESA_SHADER_VERTEX ? MESA_SHADER_VERTEX : MESA_SHADER_NONE, &args);
3174*61046927SAndroid Build Coastguard Worker 
3175*61046927SAndroid Build Coastguard Worker    info.user_sgprs_locs = args.user_sgprs_locs;
3176*61046927SAndroid Build Coastguard Worker    info.inline_push_constant_mask = args.ac.inline_push_const_mask;
3177*61046927SAndroid Build Coastguard Worker 
3178*61046927SAndroid Build Coastguard Worker #if AMD_LLVM_AVAILABLE
3179*61046927SAndroid Build Coastguard Worker    if (options.dump_shader || options.record_ir)
3180*61046927SAndroid Build Coastguard Worker       ac_init_llvm_once();
3181*61046927SAndroid Build Coastguard Worker #endif
3182*61046927SAndroid Build Coastguard Worker 
3183*61046927SAndroid Build Coastguard Worker    struct radv_shader_part_binary *binary = NULL;
3184*61046927SAndroid Build Coastguard Worker    struct radv_shader_stage_key stage_key = {0};
3185*61046927SAndroid Build Coastguard Worker    struct aco_shader_info ac_info;
3186*61046927SAndroid Build Coastguard Worker    struct aco_vs_prolog_info ac_prolog_info;
3187*61046927SAndroid Build Coastguard Worker    struct aco_compiler_options ac_opts;
3188*61046927SAndroid Build Coastguard Worker    radv_aco_convert_shader_info(&ac_info, &info, &args, &device->cache_key, options.info->gfx_level);
3189*61046927SAndroid Build Coastguard Worker    radv_aco_convert_opts(&ac_opts, &options, &args, &stage_key);
3190*61046927SAndroid Build Coastguard Worker    radv_aco_convert_vs_prolog_key(&ac_prolog_info, key, &args);
3191*61046927SAndroid Build Coastguard Worker    aco_compile_vs_prolog(&ac_opts, &ac_info, &ac_prolog_info, &args.ac, &radv_aco_build_shader_part, (void **)&binary);
3192*61046927SAndroid Build Coastguard Worker 
3193*61046927SAndroid Build Coastguard Worker    prolog = radv_shader_part_create(device, binary, info.wave_size);
3194*61046927SAndroid Build Coastguard Worker    if (!prolog)
3195*61046927SAndroid Build Coastguard Worker       goto fail;
3196*61046927SAndroid Build Coastguard Worker 
3197*61046927SAndroid Build Coastguard Worker    prolog->key.vs = *key;
3198*61046927SAndroid Build Coastguard Worker    prolog->nontrivial_divisors = key->nontrivial_divisors;
3199*61046927SAndroid Build Coastguard Worker 
3200*61046927SAndroid Build Coastguard Worker    if (options.dump_shader) {
3201*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "Vertex prolog");
3202*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "\ndisasm:\n%s\n", prolog->disasm_string);
3203*61046927SAndroid Build Coastguard Worker    }
3204*61046927SAndroid Build Coastguard Worker 
3205*61046927SAndroid Build Coastguard Worker    free(binary);
3206*61046927SAndroid Build Coastguard Worker 
3207*61046927SAndroid Build Coastguard Worker    return prolog;
3208*61046927SAndroid Build Coastguard Worker 
3209*61046927SAndroid Build Coastguard Worker fail:
3210*61046927SAndroid Build Coastguard Worker    free(binary);
3211*61046927SAndroid Build Coastguard Worker    return NULL;
3212*61046927SAndroid Build Coastguard Worker }
3213*61046927SAndroid Build Coastguard Worker 
3214*61046927SAndroid Build Coastguard Worker struct radv_shader_part *
3215*61046927SAndroid Build Coastguard Worker radv_create_ps_epilog(struct radv_device *device, const struct radv_ps_epilog_key *key,
3216*61046927SAndroid Build Coastguard Worker                       struct radv_shader_part_binary **binary_out)
3217*61046927SAndroid Build Coastguard Worker {
3218*61046927SAndroid Build Coastguard Worker    const struct radv_physical_device *pdev = radv_device_physical(device);
3219*61046927SAndroid Build Coastguard Worker    const struct radv_instance *instance = radv_physical_device_instance(pdev);
3220*61046927SAndroid Build Coastguard Worker    struct radv_shader_part *epilog;
3221*61046927SAndroid Build Coastguard Worker    struct radv_shader_args args = {0};
3222*61046927SAndroid Build Coastguard Worker    struct radv_nir_compiler_options options = {0};
3223*61046927SAndroid Build Coastguard Worker    radv_fill_nir_compiler_options(&options, device, NULL, false, instance->debug_flags & RADV_DEBUG_DUMP_EPILOGS, false,
3224*61046927SAndroid Build Coastguard Worker                                   radv_device_fault_detection_enabled(device), false);
3225*61046927SAndroid Build Coastguard Worker 
3226*61046927SAndroid Build Coastguard Worker    struct radv_shader_info info = {0};
3227*61046927SAndroid Build Coastguard Worker    info.stage = MESA_SHADER_FRAGMENT;
3228*61046927SAndroid Build Coastguard Worker    info.wave_size = pdev->ps_wave_size;
3229*61046927SAndroid Build Coastguard Worker    info.workgroup_size = 64;
3230*61046927SAndroid Build Coastguard Worker 
3231*61046927SAndroid Build Coastguard Worker    radv_declare_ps_epilog_args(device, key, &args);
3232*61046927SAndroid Build Coastguard Worker 
3233*61046927SAndroid Build Coastguard Worker #if AMD_LLVM_AVAILABLE
3234*61046927SAndroid Build Coastguard Worker    if (options.dump_shader || options.record_ir)
3235*61046927SAndroid Build Coastguard Worker       ac_init_llvm_once();
3236*61046927SAndroid Build Coastguard Worker #endif
3237*61046927SAndroid Build Coastguard Worker 
3238*61046927SAndroid Build Coastguard Worker    struct radv_shader_part_binary *binary = NULL;
3239*61046927SAndroid Build Coastguard Worker    struct radv_shader_stage_key stage_key = {0};
3240*61046927SAndroid Build Coastguard Worker    struct aco_shader_info ac_info;
3241*61046927SAndroid Build Coastguard Worker    struct aco_ps_epilog_info ac_epilog_info = {0};
3242*61046927SAndroid Build Coastguard Worker    struct aco_compiler_options ac_opts;
3243*61046927SAndroid Build Coastguard Worker    radv_aco_convert_shader_info(&ac_info, &info, &args, &device->cache_key, options.info->gfx_level);
3244*61046927SAndroid Build Coastguard Worker    radv_aco_convert_opts(&ac_opts, &options, &args, &stage_key);
3245*61046927SAndroid Build Coastguard Worker    radv_aco_convert_ps_epilog_key(&ac_epilog_info, key, &args);
3246*61046927SAndroid Build Coastguard Worker    aco_compile_ps_epilog(&ac_opts, &ac_info, &ac_epilog_info, &args.ac, &radv_aco_build_shader_part, (void **)&binary);
3247*61046927SAndroid Build Coastguard Worker 
3248*61046927SAndroid Build Coastguard Worker    binary->info.spi_shader_col_format = key->spi_shader_col_format;
3249*61046927SAndroid Build Coastguard Worker    binary->info.cb_shader_mask = ac_get_cb_shader_mask(key->spi_shader_col_format);
3250*61046927SAndroid Build Coastguard Worker    binary->info.spi_shader_z_format = key->spi_shader_z_format;
3251*61046927SAndroid Build Coastguard Worker 
3252*61046927SAndroid Build Coastguard Worker    epilog = radv_shader_part_create(device, binary, info.wave_size);
3253*61046927SAndroid Build Coastguard Worker    if (!epilog)
3254*61046927SAndroid Build Coastguard Worker       goto fail;
3255*61046927SAndroid Build Coastguard Worker 
3256*61046927SAndroid Build Coastguard Worker    epilog->key.ps = *key;
3257*61046927SAndroid Build Coastguard Worker 
3258*61046927SAndroid Build Coastguard Worker    if (options.dump_shader) {
3259*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "Fragment epilog");
3260*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "\ndisasm:\n%s\n", epilog->disasm_string);
3261*61046927SAndroid Build Coastguard Worker    }
3262*61046927SAndroid Build Coastguard Worker 
3263*61046927SAndroid Build Coastguard Worker    if (binary_out) {
3264*61046927SAndroid Build Coastguard Worker       *binary_out = binary;
3265*61046927SAndroid Build Coastguard Worker    } else {
3266*61046927SAndroid Build Coastguard Worker       free(binary);
3267*61046927SAndroid Build Coastguard Worker    }
3268*61046927SAndroid Build Coastguard Worker 
3269*61046927SAndroid Build Coastguard Worker    return epilog;
3270*61046927SAndroid Build Coastguard Worker 
3271*61046927SAndroid Build Coastguard Worker fail:
3272*61046927SAndroid Build Coastguard Worker    free(binary);
3273*61046927SAndroid Build Coastguard Worker    return NULL;
3274*61046927SAndroid Build Coastguard Worker }
3275*61046927SAndroid Build Coastguard Worker 
3276*61046927SAndroid Build Coastguard Worker void
3277*61046927SAndroid Build Coastguard Worker radv_shader_part_destroy(struct radv_device *device, struct radv_shader_part *shader_part)
3278*61046927SAndroid Build Coastguard Worker {
3279*61046927SAndroid Build Coastguard Worker    assert(shader_part->ref_count == 0);
3280*61046927SAndroid Build Coastguard Worker 
3281*61046927SAndroid Build Coastguard Worker    if (device->shader_use_invisible_vram) {
3282*61046927SAndroid Build Coastguard Worker       /* Wait for any pending upload to complete, or we'll be writing into freed shader memory. */
3283*61046927SAndroid Build Coastguard Worker       radv_shader_wait_for_upload(device, shader_part->upload_seq);
3284*61046927SAndroid Build Coastguard Worker    }
3285*61046927SAndroid Build Coastguard Worker 
3286*61046927SAndroid Build Coastguard Worker    if (shader_part->alloc)
3287*61046927SAndroid Build Coastguard Worker       radv_free_shader_memory(device, shader_part->alloc);
3288*61046927SAndroid Build Coastguard Worker    free(shader_part->disasm_string);
3289*61046927SAndroid Build Coastguard Worker    free(shader_part);
3290*61046927SAndroid Build Coastguard Worker }
3291*61046927SAndroid Build Coastguard Worker 
3292*61046927SAndroid Build Coastguard Worker uint64_t
3293*61046927SAndroid Build Coastguard Worker radv_shader_get_va(const struct radv_shader *shader)
3294*61046927SAndroid Build Coastguard Worker {
3295*61046927SAndroid Build Coastguard Worker    return shader->va;
3296*61046927SAndroid Build Coastguard Worker }
3297*61046927SAndroid Build Coastguard Worker 
3298*61046927SAndroid Build Coastguard Worker struct radv_shader *
3299*61046927SAndroid Build Coastguard Worker radv_find_shader(struct radv_device *device, uint64_t pc)
3300*61046927SAndroid Build Coastguard Worker {
3301*61046927SAndroid Build Coastguard Worker    mtx_lock(&device->shader_arena_mutex);
3302*61046927SAndroid Build Coastguard Worker    list_for_each_entry (struct radv_shader_arena, arena, &device->shader_arenas, list) {
3303*61046927SAndroid Build Coastguard Worker #ifdef __GNUC__
3304*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic push
3305*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wshadow"
3306*61046927SAndroid Build Coastguard Worker #endif
3307*61046927SAndroid Build Coastguard Worker       list_for_each_entry (union radv_shader_arena_block, block, &arena->entries, list) {
3308*61046927SAndroid Build Coastguard Worker #ifdef __GNUC__
3309*61046927SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
3310*61046927SAndroid Build Coastguard Worker #endif
3311*61046927SAndroid Build Coastguard Worker          uint64_t start = radv_buffer_get_va(block->arena->bo) + block->offset;
3312*61046927SAndroid Build Coastguard Worker          start &= ((1ull << 48) - 1);
3313*61046927SAndroid Build Coastguard Worker          if (!block->freelist.prev && pc >= start && pc < start + block->size) {
3314*61046927SAndroid Build Coastguard Worker             mtx_unlock(&device->shader_arena_mutex);
3315*61046927SAndroid Build Coastguard Worker             return (struct radv_shader *)block->freelist.next;
3316*61046927SAndroid Build Coastguard Worker          }
3317*61046927SAndroid Build Coastguard Worker       }
3318*61046927SAndroid Build Coastguard Worker    }
3319*61046927SAndroid Build Coastguard Worker 
3320*61046927SAndroid Build Coastguard Worker    mtx_unlock(&device->shader_arena_mutex);
3321*61046927SAndroid Build Coastguard Worker    return NULL;
3322*61046927SAndroid Build Coastguard Worker }
3323*61046927SAndroid Build Coastguard Worker 
3324*61046927SAndroid Build Coastguard Worker const char *
3325*61046927SAndroid Build Coastguard Worker radv_get_shader_name(const struct radv_shader_info *info, gl_shader_stage stage)
3326*61046927SAndroid Build Coastguard Worker {
3327*61046927SAndroid Build Coastguard Worker    switch (stage) {
3328*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_VERTEX:
3329*61046927SAndroid Build Coastguard Worker       if (info->vs.as_ls)
3330*61046927SAndroid Build Coastguard Worker          return "Vertex Shader as LS";
3331*61046927SAndroid Build Coastguard Worker       else if (info->vs.as_es)
3332*61046927SAndroid Build Coastguard Worker          return "Vertex Shader as ES";
3333*61046927SAndroid Build Coastguard Worker       else if (info->is_ngg)
3334*61046927SAndroid Build Coastguard Worker          return "Vertex Shader as ESGS";
3335*61046927SAndroid Build Coastguard Worker       else
3336*61046927SAndroid Build Coastguard Worker          return "Vertex Shader as VS";
3337*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_CTRL:
3338*61046927SAndroid Build Coastguard Worker       return "Tessellation Control Shader";
3339*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TESS_EVAL:
3340*61046927SAndroid Build Coastguard Worker       if (info->tes.as_es)
3341*61046927SAndroid Build Coastguard Worker          return "Tessellation Evaluation Shader as ES";
3342*61046927SAndroid Build Coastguard Worker       else if (info->is_ngg)
3343*61046927SAndroid Build Coastguard Worker          return "Tessellation Evaluation Shader as ESGS";
3344*61046927SAndroid Build Coastguard Worker       else
3345*61046927SAndroid Build Coastguard Worker          return "Tessellation Evaluation Shader as VS";
3346*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_GEOMETRY:
3347*61046927SAndroid Build Coastguard Worker       return "Geometry Shader";
3348*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_FRAGMENT:
3349*61046927SAndroid Build Coastguard Worker       return "Pixel Shader";
3350*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_COMPUTE:
3351*61046927SAndroid Build Coastguard Worker       return "Compute Shader";
3352*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_MESH:
3353*61046927SAndroid Build Coastguard Worker       return "Mesh Shader as NGG";
3354*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_TASK:
3355*61046927SAndroid Build Coastguard Worker       return "Task Shader as CS";
3356*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_RAYGEN:
3357*61046927SAndroid Build Coastguard Worker       return "Ray Generation Shader as CS Function";
3358*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_CLOSEST_HIT:
3359*61046927SAndroid Build Coastguard Worker       return "Closest Hit Shader as CS Function";
3360*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_INTERSECTION:
3361*61046927SAndroid Build Coastguard Worker       return "Intersection Shader as CS Function";
3362*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_ANY_HIT:
3363*61046927SAndroid Build Coastguard Worker       return "Any Hit Shader as CS Function";
3364*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_MISS:
3365*61046927SAndroid Build Coastguard Worker       return "Miss Shader as CS Function";
3366*61046927SAndroid Build Coastguard Worker    case MESA_SHADER_CALLABLE:
3367*61046927SAndroid Build Coastguard Worker       return "Callable Shader as CS Function";
3368*61046927SAndroid Build Coastguard Worker    default:
3369*61046927SAndroid Build Coastguard Worker       return "Unknown shader";
3370*61046927SAndroid Build Coastguard Worker    };
3371*61046927SAndroid Build Coastguard Worker }
3372*61046927SAndroid Build Coastguard Worker 
3373*61046927SAndroid Build Coastguard Worker unsigned
3374*61046927SAndroid Build Coastguard Worker radv_compute_spi_ps_input(const struct radv_physical_device *pdev, const struct radv_graphics_state_key *gfx_state,
3375*61046927SAndroid Build Coastguard Worker                           const struct radv_shader_info *info)
3376*61046927SAndroid Build Coastguard Worker {
3377*61046927SAndroid Build Coastguard Worker    unsigned spi_ps_input;
3378*61046927SAndroid Build Coastguard Worker 
3379*61046927SAndroid Build Coastguard Worker    spi_ps_input = S_0286CC_PERSP_CENTER_ENA(info->ps.reads_persp_center) |
3380*61046927SAndroid Build Coastguard Worker                   S_0286CC_PERSP_CENTROID_ENA(info->ps.reads_persp_centroid) |
3381*61046927SAndroid Build Coastguard Worker                   S_0286CC_PERSP_SAMPLE_ENA(info->ps.reads_persp_sample) |
3382*61046927SAndroid Build Coastguard Worker                   S_0286CC_LINEAR_CENTER_ENA(info->ps.reads_linear_center) |
3383*61046927SAndroid Build Coastguard Worker                   S_0286CC_LINEAR_CENTROID_ENA(info->ps.reads_linear_centroid) |
3384*61046927SAndroid Build Coastguard Worker                   S_0286CC_LINEAR_SAMPLE_ENA(info->ps.reads_linear_sample) |
3385*61046927SAndroid Build Coastguard Worker                   S_0286CC_PERSP_PULL_MODEL_ENA(info->ps.reads_barycentric_model) |
3386*61046927SAndroid Build Coastguard Worker                   S_0286CC_FRONT_FACE_ENA(info->ps.reads_front_face);
3387*61046927SAndroid Build Coastguard Worker 
3388*61046927SAndroid Build Coastguard Worker    if (info->ps.reads_frag_coord_mask || info->ps.reads_sample_pos_mask) {
3389*61046927SAndroid Build Coastguard Worker       uint8_t mask = info->ps.reads_frag_coord_mask | info->ps.reads_sample_pos_mask;
3390*61046927SAndroid Build Coastguard Worker 
3391*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < 4; i++) {
3392*61046927SAndroid Build Coastguard Worker          if (mask & (1 << i))
3393*61046927SAndroid Build Coastguard Worker             spi_ps_input |= S_0286CC_POS_X_FLOAT_ENA(1) << i;
3394*61046927SAndroid Build Coastguard Worker       }
3395*61046927SAndroid Build Coastguard Worker 
3396*61046927SAndroid Build Coastguard Worker       if (gfx_state->adjust_frag_coord_z && info->ps.reads_frag_coord_mask & (1 << 2)) {
3397*61046927SAndroid Build Coastguard Worker          spi_ps_input |= S_0286CC_ANCILLARY_ENA(1);
3398*61046927SAndroid Build Coastguard Worker       }
3399*61046927SAndroid Build Coastguard Worker    }
3400*61046927SAndroid Build Coastguard Worker 
3401*61046927SAndroid Build Coastguard Worker    if (info->ps.reads_sample_id || info->ps.reads_frag_shading_rate || info->ps.reads_sample_mask_in) {
3402*61046927SAndroid Build Coastguard Worker       spi_ps_input |= S_0286CC_ANCILLARY_ENA(1);
3403*61046927SAndroid Build Coastguard Worker    }
3404*61046927SAndroid Build Coastguard Worker 
3405*61046927SAndroid Build Coastguard Worker    if (info->ps.reads_sample_mask_in || info->ps.reads_fully_covered) {
3406*61046927SAndroid Build Coastguard Worker       spi_ps_input |= S_0286CC_SAMPLE_COVERAGE_ENA(1) |
3407*61046927SAndroid Build Coastguard Worker                       S_02865C_COVERAGE_TO_SHADER_SELECT(pdev->info.gfx_level >= GFX12 && info->ps.reads_fully_covered);
3408*61046927SAndroid Build Coastguard Worker    }
3409*61046927SAndroid Build Coastguard Worker 
3410*61046927SAndroid Build Coastguard Worker    if (G_0286CC_POS_W_FLOAT_ENA(spi_ps_input)) {
3411*61046927SAndroid Build Coastguard Worker       /* If POS_W_FLOAT (11) is enabled, at least one of PERSP_* must be enabled too */
3412*61046927SAndroid Build Coastguard Worker       spi_ps_input |= S_0286CC_PERSP_CENTER_ENA(1);
3413*61046927SAndroid Build Coastguard Worker    }
3414*61046927SAndroid Build Coastguard Worker 
3415*61046927SAndroid Build Coastguard Worker    if (!(spi_ps_input & 0x7F)) {
3416*61046927SAndroid Build Coastguard Worker       /* At least one of PERSP_* (0xF) or LINEAR_* (0x70) must be enabled */
3417*61046927SAndroid Build Coastguard Worker       spi_ps_input |= S_0286CC_PERSP_CENTER_ENA(1);
3418*61046927SAndroid Build Coastguard Worker    }
3419*61046927SAndroid Build Coastguard Worker 
3420*61046927SAndroid Build Coastguard Worker    return spi_ps_input;
3421*61046927SAndroid Build Coastguard Worker }
3422*61046927SAndroid Build Coastguard Worker 
3423*61046927SAndroid Build Coastguard Worker const struct radv_userdata_info *
3424*61046927SAndroid Build Coastguard Worker radv_get_user_sgpr_info(const struct radv_shader *shader, int idx)
3425*61046927SAndroid Build Coastguard Worker {
3426*61046927SAndroid Build Coastguard Worker    return &shader->info.user_sgprs_locs.shader_data[idx];
3427*61046927SAndroid Build Coastguard Worker }
3428*61046927SAndroid Build Coastguard Worker 
3429*61046927SAndroid Build Coastguard Worker uint32_t
3430*61046927SAndroid Build Coastguard Worker radv_get_user_sgpr_loc(const struct radv_shader *shader, int idx)
3431*61046927SAndroid Build Coastguard Worker {
3432*61046927SAndroid Build Coastguard Worker    const struct radv_userdata_info *loc = radv_get_user_sgpr_info(shader, idx);
3433*61046927SAndroid Build Coastguard Worker 
3434*61046927SAndroid Build Coastguard Worker    if (loc->sgpr_idx == -1)
3435*61046927SAndroid Build Coastguard Worker       return 0;
3436*61046927SAndroid Build Coastguard Worker 
3437*61046927SAndroid Build Coastguard Worker    return shader->info.user_data_0 + loc->sgpr_idx * 4;
3438*61046927SAndroid Build Coastguard Worker }
3439*61046927SAndroid Build Coastguard Worker 
3440*61046927SAndroid Build Coastguard Worker uint32_t
3441*61046927SAndroid Build Coastguard Worker radv_get_user_sgpr(const struct radv_shader *shader, int idx)
3442*61046927SAndroid Build Coastguard Worker {
3443*61046927SAndroid Build Coastguard Worker    const uint32_t offset = radv_get_user_sgpr_loc(shader, idx);
3444*61046927SAndroid Build Coastguard Worker 
3445*61046927SAndroid Build Coastguard Worker    return offset ? ((offset - SI_SH_REG_OFFSET) >> 2) : 0;
3446*61046927SAndroid Build Coastguard Worker }
3447*61046927SAndroid Build Coastguard Worker 
3448*61046927SAndroid Build Coastguard Worker static uint32_t
3449*61046927SAndroid Build Coastguard Worker radv_get_tess_patch_size(uint32_t tcs_num_input_vertices, uint32_t tcs_num_output_vertices, uint32_t tcs_num_inputs,
3450*61046927SAndroid Build Coastguard Worker                          uint32_t tcs_num_lds_outputs, uint32_t tcs_num_lds_patch_outputs)
3451*61046927SAndroid Build Coastguard Worker {
3452*61046927SAndroid Build Coastguard Worker    const uint32_t input_vertex_size = get_tcs_input_vertex_stride(tcs_num_inputs);
3453*61046927SAndroid Build Coastguard Worker    const uint32_t input_patch_size = tcs_num_input_vertices * input_vertex_size;
3454*61046927SAndroid Build Coastguard Worker    const uint32_t lds_output_vertex_size = tcs_num_lds_outputs * 16;
3455*61046927SAndroid Build Coastguard Worker    const uint32_t lds_pervertex_output_patch_size = tcs_num_output_vertices * lds_output_vertex_size;
3456*61046927SAndroid Build Coastguard Worker    const uint32_t lds_output_patch_size = lds_pervertex_output_patch_size + tcs_num_lds_patch_outputs * 16;
3457*61046927SAndroid Build Coastguard Worker 
3458*61046927SAndroid Build Coastguard Worker    return input_patch_size + lds_output_patch_size;
3459*61046927SAndroid Build Coastguard Worker }
3460*61046927SAndroid Build Coastguard Worker 
3461*61046927SAndroid Build Coastguard Worker uint32_t
3462*61046927SAndroid Build Coastguard Worker radv_get_tcs_num_patches(const struct radv_physical_device *pdev, unsigned tcs_num_input_vertices,
3463*61046927SAndroid Build Coastguard Worker                          unsigned tcs_num_output_vertices, unsigned tcs_num_inputs, unsigned tcs_num_lds_outputs,
3464*61046927SAndroid Build Coastguard Worker                          unsigned tcs_num_lds_patch_outputs, unsigned tcs_num_vram_outputs,
3465*61046927SAndroid Build Coastguard Worker                          unsigned tcs_num_vram_patch_outputs)
3466*61046927SAndroid Build Coastguard Worker {
3467*61046927SAndroid Build Coastguard Worker    const uint32_t lds_per_patch = radv_get_tess_patch_size(
3468*61046927SAndroid Build Coastguard Worker       tcs_num_input_vertices, tcs_num_output_vertices, tcs_num_inputs, tcs_num_lds_outputs, tcs_num_lds_patch_outputs);
3469*61046927SAndroid Build Coastguard Worker    const uint32_t vram_per_patch = radv_get_tess_patch_size(tcs_num_input_vertices, tcs_num_output_vertices, 0,
3470*61046927SAndroid Build Coastguard Worker                                                             tcs_num_vram_outputs, tcs_num_vram_patch_outputs);
3471*61046927SAndroid Build Coastguard Worker 
3472*61046927SAndroid Build Coastguard Worker    return ac_compute_num_tess_patches(&pdev->info, tcs_num_input_vertices, tcs_num_output_vertices, vram_per_patch,
3473*61046927SAndroid Build Coastguard Worker                                       lds_per_patch, pdev->ge_wave_size, false);
3474*61046927SAndroid Build Coastguard Worker }
3475*61046927SAndroid Build Coastguard Worker 
3476*61046927SAndroid Build Coastguard Worker uint32_t
3477*61046927SAndroid Build Coastguard Worker radv_get_tess_lds_size(const struct radv_physical_device *pdev, uint32_t tcs_num_input_vertices,
3478*61046927SAndroid Build Coastguard Worker                        uint32_t tcs_num_output_vertices, uint32_t tcs_num_inputs, uint32_t tcs_num_patches,
3479*61046927SAndroid Build Coastguard Worker                        uint32_t tcs_num_lds_outputs, uint32_t tcs_num_lds_patch_outputs)
3480*61046927SAndroid Build Coastguard Worker {
3481*61046927SAndroid Build Coastguard Worker    const uint32_t lds_per_patch = radv_get_tess_patch_size(
3482*61046927SAndroid Build Coastguard Worker       tcs_num_input_vertices, tcs_num_output_vertices, tcs_num_inputs, tcs_num_lds_outputs, tcs_num_lds_patch_outputs);
3483*61046927SAndroid Build Coastguard Worker 
3484*61046927SAndroid Build Coastguard Worker    return ac_compute_tess_lds_size(&pdev->info, lds_per_patch, tcs_num_patches);
3485*61046927SAndroid Build Coastguard Worker }
3486*61046927SAndroid Build Coastguard Worker 
3487*61046927SAndroid Build Coastguard Worker VkResult
3488*61046927SAndroid Build Coastguard Worker radv_dump_shader_stats(struct radv_device *device, struct radv_pipeline *pipeline, struct radv_shader *shader,
3489*61046927SAndroid Build Coastguard Worker                        gl_shader_stage stage, FILE *output)
3490*61046927SAndroid Build Coastguard Worker {
3491*61046927SAndroid Build Coastguard Worker    VkPipelineExecutablePropertiesKHR *props = NULL;
3492*61046927SAndroid Build Coastguard Worker    uint32_t prop_count = 0;
3493*61046927SAndroid Build Coastguard Worker    VkResult result;
3494*61046927SAndroid Build Coastguard Worker 
3495*61046927SAndroid Build Coastguard Worker    VkPipelineInfoKHR pipeline_info = {0};
3496*61046927SAndroid Build Coastguard Worker    pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR;
3497*61046927SAndroid Build Coastguard Worker    pipeline_info.pipeline = radv_pipeline_to_handle(pipeline);
3498*61046927SAndroid Build Coastguard Worker 
3499*61046927SAndroid Build Coastguard Worker    result = radv_GetPipelineExecutablePropertiesKHR(radv_device_to_handle(device), &pipeline_info, &prop_count, NULL);
3500*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
3501*61046927SAndroid Build Coastguard Worker       return result;
3502*61046927SAndroid Build Coastguard Worker 
3503*61046927SAndroid Build Coastguard Worker    props = calloc(prop_count, sizeof(*props));
3504*61046927SAndroid Build Coastguard Worker    if (!props)
3505*61046927SAndroid Build Coastguard Worker       return VK_ERROR_OUT_OF_HOST_MEMORY;
3506*61046927SAndroid Build Coastguard Worker 
3507*61046927SAndroid Build Coastguard Worker    result = radv_GetPipelineExecutablePropertiesKHR(radv_device_to_handle(device), &pipeline_info, &prop_count, props);
3508*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
3509*61046927SAndroid Build Coastguard Worker       goto fail;
3510*61046927SAndroid Build Coastguard Worker 
3511*61046927SAndroid Build Coastguard Worker    for (unsigned exec_idx = 0; exec_idx < prop_count; exec_idx++) {
3512*61046927SAndroid Build Coastguard Worker       if (!(props[exec_idx].stages & mesa_to_vk_shader_stage(stage)))
3513*61046927SAndroid Build Coastguard Worker          continue;
3514*61046927SAndroid Build Coastguard Worker 
3515*61046927SAndroid Build Coastguard Worker       VkPipelineExecutableStatisticKHR *stats = NULL;
3516*61046927SAndroid Build Coastguard Worker       uint32_t stat_count = 0;
3517*61046927SAndroid Build Coastguard Worker 
3518*61046927SAndroid Build Coastguard Worker       VkPipelineExecutableInfoKHR exec_info = {0};
3519*61046927SAndroid Build Coastguard Worker       exec_info.pipeline = radv_pipeline_to_handle(pipeline);
3520*61046927SAndroid Build Coastguard Worker       exec_info.executableIndex = exec_idx;
3521*61046927SAndroid Build Coastguard Worker 
3522*61046927SAndroid Build Coastguard Worker       result = radv_GetPipelineExecutableStatisticsKHR(radv_device_to_handle(device), &exec_info, &stat_count, NULL);
3523*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
3524*61046927SAndroid Build Coastguard Worker          goto fail;
3525*61046927SAndroid Build Coastguard Worker 
3526*61046927SAndroid Build Coastguard Worker       stats = calloc(stat_count, sizeof(*stats));
3527*61046927SAndroid Build Coastguard Worker       if (!stats) {
3528*61046927SAndroid Build Coastguard Worker          result = VK_ERROR_OUT_OF_HOST_MEMORY;
3529*61046927SAndroid Build Coastguard Worker          goto fail;
3530*61046927SAndroid Build Coastguard Worker       }
3531*61046927SAndroid Build Coastguard Worker 
3532*61046927SAndroid Build Coastguard Worker       result = radv_GetPipelineExecutableStatisticsKHR(radv_device_to_handle(device), &exec_info, &stat_count, stats);
3533*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
3534*61046927SAndroid Build Coastguard Worker          free(stats);
3535*61046927SAndroid Build Coastguard Worker          goto fail;
3536*61046927SAndroid Build Coastguard Worker       }
3537*61046927SAndroid Build Coastguard Worker 
3538*61046927SAndroid Build Coastguard Worker       fprintf(output, "\n%s:\n", radv_get_shader_name(&shader->info, stage));
3539*61046927SAndroid Build Coastguard Worker       fprintf(output, "*** SHADER STATS ***\n");
3540*61046927SAndroid Build Coastguard Worker 
3541*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < stat_count; i++) {
3542*61046927SAndroid Build Coastguard Worker          fprintf(output, "%s: ", stats[i].name);
3543*61046927SAndroid Build Coastguard Worker          switch (stats[i].format) {
3544*61046927SAndroid Build Coastguard Worker          case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
3545*61046927SAndroid Build Coastguard Worker             fprintf(output, "%s", stats[i].value.b32 == VK_TRUE ? "true" : "false");
3546*61046927SAndroid Build Coastguard Worker             break;
3547*61046927SAndroid Build Coastguard Worker          case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
3548*61046927SAndroid Build Coastguard Worker             fprintf(output, "%" PRIi64, stats[i].value.i64);
3549*61046927SAndroid Build Coastguard Worker             break;
3550*61046927SAndroid Build Coastguard Worker          case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
3551*61046927SAndroid Build Coastguard Worker             fprintf(output, "%" PRIu64, stats[i].value.u64);
3552*61046927SAndroid Build Coastguard Worker             break;
3553*61046927SAndroid Build Coastguard Worker          case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
3554*61046927SAndroid Build Coastguard Worker             fprintf(output, "%f", stats[i].value.f64);
3555*61046927SAndroid Build Coastguard Worker             break;
3556*61046927SAndroid Build Coastguard Worker          default:
3557*61046927SAndroid Build Coastguard Worker             unreachable("Invalid pipeline statistic format");
3558*61046927SAndroid Build Coastguard Worker          }
3559*61046927SAndroid Build Coastguard Worker          fprintf(output, "\n");
3560*61046927SAndroid Build Coastguard Worker       }
3561*61046927SAndroid Build Coastguard Worker 
3562*61046927SAndroid Build Coastguard Worker       fprintf(output, "********************\n\n\n");
3563*61046927SAndroid Build Coastguard Worker 
3564*61046927SAndroid Build Coastguard Worker       free(stats);
3565*61046927SAndroid Build Coastguard Worker    }
3566*61046927SAndroid Build Coastguard Worker 
3567*61046927SAndroid Build Coastguard Worker fail:
3568*61046927SAndroid Build Coastguard Worker    free(props);
3569*61046927SAndroid Build Coastguard Worker    return result;
3570*61046927SAndroid Build Coastguard Worker }
3571