1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2022 Collabora Ltd. and Red Hat Inc.
3*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker */
5*61046927SAndroid Build Coastguard Worker #include "nvk_shader.h"
6*61046927SAndroid Build Coastguard Worker
7*61046927SAndroid Build Coastguard Worker #include "nvk_cmd_buffer.h"
8*61046927SAndroid Build Coastguard Worker #include "nvk_descriptor_set_layout.h"
9*61046927SAndroid Build Coastguard Worker #include "nvk_device.h"
10*61046927SAndroid Build Coastguard Worker #include "nvk_physical_device.h"
11*61046927SAndroid Build Coastguard Worker #include "nvk_sampler.h"
12*61046927SAndroid Build Coastguard Worker #include "nvk_shader.h"
13*61046927SAndroid Build Coastguard Worker
14*61046927SAndroid Build Coastguard Worker #include "vk_nir_convert_ycbcr.h"
15*61046927SAndroid Build Coastguard Worker #include "vk_pipeline.h"
16*61046927SAndroid Build Coastguard Worker #include "vk_pipeline_layout.h"
17*61046927SAndroid Build Coastguard Worker #include "vk_shader_module.h"
18*61046927SAndroid Build Coastguard Worker #include "vk_ycbcr_conversion.h"
19*61046927SAndroid Build Coastguard Worker
20*61046927SAndroid Build Coastguard Worker #include "nak.h"
21*61046927SAndroid Build Coastguard Worker #include "nir.h"
22*61046927SAndroid Build Coastguard Worker #include "nir_builder.h"
23*61046927SAndroid Build Coastguard Worker #include "compiler/spirv/nir_spirv.h"
24*61046927SAndroid Build Coastguard Worker
25*61046927SAndroid Build Coastguard Worker #include "nv50_ir_driver.h"
26*61046927SAndroid Build Coastguard Worker
27*61046927SAndroid Build Coastguard Worker #include "util/mesa-sha1.h"
28*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Worker #include "cla097.h"
31*61046927SAndroid Build Coastguard Worker #include "clb097.h"
32*61046927SAndroid Build Coastguard Worker #include "clc397.h"
33*61046927SAndroid Build Coastguard Worker #include "clc597.h"
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Worker static void
shared_var_info(const struct glsl_type * type,unsigned * size,unsigned * align)36*61046927SAndroid Build Coastguard Worker shared_var_info(const struct glsl_type *type, unsigned *size, unsigned *align)
37*61046927SAndroid Build Coastguard Worker {
38*61046927SAndroid Build Coastguard Worker assert(glsl_type_is_vector_or_scalar(type));
39*61046927SAndroid Build Coastguard Worker
40*61046927SAndroid Build Coastguard Worker uint32_t comp_size = glsl_type_is_boolean(type) ? 4 : glsl_get_bit_size(type) / 8;
41*61046927SAndroid Build Coastguard Worker unsigned length = glsl_get_vector_elements(type);
42*61046927SAndroid Build Coastguard Worker *size = comp_size * length, *align = comp_size;
43*61046927SAndroid Build Coastguard Worker }
44*61046927SAndroid Build Coastguard Worker
45*61046927SAndroid Build Coastguard Worker VkShaderStageFlags
nvk_nak_stages(const struct nv_device_info * info)46*61046927SAndroid Build Coastguard Worker nvk_nak_stages(const struct nv_device_info *info)
47*61046927SAndroid Build Coastguard Worker {
48*61046927SAndroid Build Coastguard Worker const VkShaderStageFlags all =
49*61046927SAndroid Build Coastguard Worker VK_SHADER_STAGE_VERTEX_BIT |
50*61046927SAndroid Build Coastguard Worker VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
51*61046927SAndroid Build Coastguard Worker VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT |
52*61046927SAndroid Build Coastguard Worker VK_SHADER_STAGE_GEOMETRY_BIT |
53*61046927SAndroid Build Coastguard Worker VK_SHADER_STAGE_FRAGMENT_BIT |
54*61046927SAndroid Build Coastguard Worker VK_SHADER_STAGE_COMPUTE_BIT;
55*61046927SAndroid Build Coastguard Worker
56*61046927SAndroid Build Coastguard Worker const struct debug_control flags[] = {
57*61046927SAndroid Build Coastguard Worker { "vs", BITFIELD64_BIT(MESA_SHADER_VERTEX) },
58*61046927SAndroid Build Coastguard Worker { "tcs", BITFIELD64_BIT(MESA_SHADER_TESS_CTRL) },
59*61046927SAndroid Build Coastguard Worker { "tes", BITFIELD64_BIT(MESA_SHADER_TESS_EVAL) },
60*61046927SAndroid Build Coastguard Worker { "gs", BITFIELD64_BIT(MESA_SHADER_GEOMETRY) },
61*61046927SAndroid Build Coastguard Worker { "fs", BITFIELD64_BIT(MESA_SHADER_FRAGMENT) },
62*61046927SAndroid Build Coastguard Worker { "cs", BITFIELD64_BIT(MESA_SHADER_COMPUTE) },
63*61046927SAndroid Build Coastguard Worker { "all", all },
64*61046927SAndroid Build Coastguard Worker { NULL, 0 },
65*61046927SAndroid Build Coastguard Worker };
66*61046927SAndroid Build Coastguard Worker
67*61046927SAndroid Build Coastguard Worker const char *env_str = getenv("NVK_USE_NAK");
68*61046927SAndroid Build Coastguard Worker if (env_str == NULL)
69*61046927SAndroid Build Coastguard Worker return info->cls_eng3d >= MAXWELL_A ? all : 0;
70*61046927SAndroid Build Coastguard Worker else
71*61046927SAndroid Build Coastguard Worker return parse_debug_string(env_str, flags);
72*61046927SAndroid Build Coastguard Worker }
73*61046927SAndroid Build Coastguard Worker
74*61046927SAndroid Build Coastguard Worker static bool
use_nak(const struct nvk_physical_device * pdev,gl_shader_stage stage)75*61046927SAndroid Build Coastguard Worker use_nak(const struct nvk_physical_device *pdev, gl_shader_stage stage)
76*61046927SAndroid Build Coastguard Worker {
77*61046927SAndroid Build Coastguard Worker return nvk_nak_stages(&pdev->info) & mesa_to_vk_shader_stage(stage);
78*61046927SAndroid Build Coastguard Worker }
79*61046927SAndroid Build Coastguard Worker
80*61046927SAndroid Build Coastguard Worker uint64_t
nvk_physical_device_compiler_flags(const struct nvk_physical_device * pdev)81*61046927SAndroid Build Coastguard Worker nvk_physical_device_compiler_flags(const struct nvk_physical_device *pdev)
82*61046927SAndroid Build Coastguard Worker {
83*61046927SAndroid Build Coastguard Worker bool no_cbufs = pdev->debug_flags & NVK_DEBUG_NO_CBUF;
84*61046927SAndroid Build Coastguard Worker bool use_edb_buffer_views = nvk_use_edb_buffer_views(pdev);
85*61046927SAndroid Build Coastguard Worker uint64_t prog_debug = nvk_cg_get_prog_debug();
86*61046927SAndroid Build Coastguard Worker uint64_t prog_optimize = nvk_cg_get_prog_optimize();
87*61046927SAndroid Build Coastguard Worker uint64_t nak_stages = nvk_nak_stages(&pdev->info);
88*61046927SAndroid Build Coastguard Worker uint64_t nak_flags = nak_debug_flags(pdev->nak);
89*61046927SAndroid Build Coastguard Worker
90*61046927SAndroid Build Coastguard Worker assert(prog_debug <= UINT8_MAX);
91*61046927SAndroid Build Coastguard Worker assert(prog_optimize < 16);
92*61046927SAndroid Build Coastguard Worker assert(nak_stages <= UINT32_MAX);
93*61046927SAndroid Build Coastguard Worker assert(nak_flags <= UINT16_MAX);
94*61046927SAndroid Build Coastguard Worker
95*61046927SAndroid Build Coastguard Worker return prog_debug
96*61046927SAndroid Build Coastguard Worker | (prog_optimize << 8)
97*61046927SAndroid Build Coastguard Worker | ((uint64_t)no_cbufs << 12)
98*61046927SAndroid Build Coastguard Worker | ((uint64_t)use_edb_buffer_views << 13)
99*61046927SAndroid Build Coastguard Worker | (nak_stages << 16)
100*61046927SAndroid Build Coastguard Worker | (nak_flags << 48);
101*61046927SAndroid Build Coastguard Worker }
102*61046927SAndroid Build Coastguard Worker
103*61046927SAndroid Build Coastguard Worker static const nir_shader_compiler_options *
nvk_get_nir_options(struct vk_physical_device * vk_pdev,gl_shader_stage stage,UNUSED const struct vk_pipeline_robustness_state * rs)104*61046927SAndroid Build Coastguard Worker nvk_get_nir_options(struct vk_physical_device *vk_pdev,
105*61046927SAndroid Build Coastguard Worker gl_shader_stage stage,
106*61046927SAndroid Build Coastguard Worker UNUSED const struct vk_pipeline_robustness_state *rs)
107*61046927SAndroid Build Coastguard Worker {
108*61046927SAndroid Build Coastguard Worker const struct nvk_physical_device *pdev =
109*61046927SAndroid Build Coastguard Worker container_of(vk_pdev, struct nvk_physical_device, vk);
110*61046927SAndroid Build Coastguard Worker
111*61046927SAndroid Build Coastguard Worker if (use_nak(pdev, stage))
112*61046927SAndroid Build Coastguard Worker return nak_nir_options(pdev->nak);
113*61046927SAndroid Build Coastguard Worker else
114*61046927SAndroid Build Coastguard Worker return nvk_cg_nir_options(pdev, stage);
115*61046927SAndroid Build Coastguard Worker }
116*61046927SAndroid Build Coastguard Worker
117*61046927SAndroid Build Coastguard Worker nir_address_format
nvk_ubo_addr_format(const struct nvk_physical_device * pdev,const struct vk_pipeline_robustness_state * rs)118*61046927SAndroid Build Coastguard Worker nvk_ubo_addr_format(const struct nvk_physical_device *pdev,
119*61046927SAndroid Build Coastguard Worker const struct vk_pipeline_robustness_state *rs)
120*61046927SAndroid Build Coastguard Worker {
121*61046927SAndroid Build Coastguard Worker if (nvk_use_bindless_cbuf(&pdev->info)) {
122*61046927SAndroid Build Coastguard Worker return nir_address_format_vec2_index_32bit_offset;
123*61046927SAndroid Build Coastguard Worker } else if (rs->null_uniform_buffer_descriptor) {
124*61046927SAndroid Build Coastguard Worker /* We need bounds checking for null descriptors */
125*61046927SAndroid Build Coastguard Worker return nir_address_format_64bit_bounded_global;
126*61046927SAndroid Build Coastguard Worker } else {
127*61046927SAndroid Build Coastguard Worker switch (rs->uniform_buffers) {
128*61046927SAndroid Build Coastguard Worker case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT:
129*61046927SAndroid Build Coastguard Worker return nir_address_format_64bit_global_32bit_offset;
130*61046927SAndroid Build Coastguard Worker case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT:
131*61046927SAndroid Build Coastguard Worker case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT:
132*61046927SAndroid Build Coastguard Worker return nir_address_format_64bit_bounded_global;
133*61046927SAndroid Build Coastguard Worker default:
134*61046927SAndroid Build Coastguard Worker unreachable("Invalid robust buffer access behavior");
135*61046927SAndroid Build Coastguard Worker }
136*61046927SAndroid Build Coastguard Worker }
137*61046927SAndroid Build Coastguard Worker }
138*61046927SAndroid Build Coastguard Worker
139*61046927SAndroid Build Coastguard Worker nir_address_format
nvk_ssbo_addr_format(const struct nvk_physical_device * pdev,const struct vk_pipeline_robustness_state * rs)140*61046927SAndroid Build Coastguard Worker nvk_ssbo_addr_format(const struct nvk_physical_device *pdev,
141*61046927SAndroid Build Coastguard Worker const struct vk_pipeline_robustness_state *rs)
142*61046927SAndroid Build Coastguard Worker {
143*61046927SAndroid Build Coastguard Worker if (rs->null_storage_buffer_descriptor) {
144*61046927SAndroid Build Coastguard Worker /* We need bounds checking for null descriptors */
145*61046927SAndroid Build Coastguard Worker return nir_address_format_64bit_bounded_global;
146*61046927SAndroid Build Coastguard Worker } else {
147*61046927SAndroid Build Coastguard Worker switch (rs->storage_buffers) {
148*61046927SAndroid Build Coastguard Worker case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT:
149*61046927SAndroid Build Coastguard Worker return nir_address_format_64bit_global_32bit_offset;
150*61046927SAndroid Build Coastguard Worker case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT:
151*61046927SAndroid Build Coastguard Worker case VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT:
152*61046927SAndroid Build Coastguard Worker return nir_address_format_64bit_bounded_global;
153*61046927SAndroid Build Coastguard Worker default:
154*61046927SAndroid Build Coastguard Worker unreachable("Invalid robust buffer access behavior");
155*61046927SAndroid Build Coastguard Worker }
156*61046927SAndroid Build Coastguard Worker }
157*61046927SAndroid Build Coastguard Worker }
158*61046927SAndroid Build Coastguard Worker
159*61046927SAndroid Build Coastguard Worker static struct spirv_to_nir_options
nvk_get_spirv_options(struct vk_physical_device * vk_pdev,UNUSED gl_shader_stage stage,const struct vk_pipeline_robustness_state * rs)160*61046927SAndroid Build Coastguard Worker nvk_get_spirv_options(struct vk_physical_device *vk_pdev,
161*61046927SAndroid Build Coastguard Worker UNUSED gl_shader_stage stage,
162*61046927SAndroid Build Coastguard Worker const struct vk_pipeline_robustness_state *rs)
163*61046927SAndroid Build Coastguard Worker {
164*61046927SAndroid Build Coastguard Worker const struct nvk_physical_device *pdev =
165*61046927SAndroid Build Coastguard Worker container_of(vk_pdev, struct nvk_physical_device, vk);
166*61046927SAndroid Build Coastguard Worker
167*61046927SAndroid Build Coastguard Worker return (struct spirv_to_nir_options) {
168*61046927SAndroid Build Coastguard Worker .ssbo_addr_format = nvk_ssbo_addr_format(pdev, rs),
169*61046927SAndroid Build Coastguard Worker .phys_ssbo_addr_format = nir_address_format_64bit_global,
170*61046927SAndroid Build Coastguard Worker .ubo_addr_format = nvk_ubo_addr_format(pdev, rs),
171*61046927SAndroid Build Coastguard Worker .shared_addr_format = nir_address_format_32bit_offset,
172*61046927SAndroid Build Coastguard Worker .min_ssbo_alignment = NVK_MIN_SSBO_ALIGNMENT,
173*61046927SAndroid Build Coastguard Worker .min_ubo_alignment = nvk_min_cbuf_alignment(&pdev->info),
174*61046927SAndroid Build Coastguard Worker };
175*61046927SAndroid Build Coastguard Worker }
176*61046927SAndroid Build Coastguard Worker
177*61046927SAndroid Build Coastguard Worker static void
nvk_preprocess_nir(struct vk_physical_device * vk_pdev,nir_shader * nir)178*61046927SAndroid Build Coastguard Worker nvk_preprocess_nir(struct vk_physical_device *vk_pdev, nir_shader *nir)
179*61046927SAndroid Build Coastguard Worker {
180*61046927SAndroid Build Coastguard Worker const struct nvk_physical_device *pdev =
181*61046927SAndroid Build Coastguard Worker container_of(vk_pdev, struct nvk_physical_device, vk);
182*61046927SAndroid Build Coastguard Worker
183*61046927SAndroid Build Coastguard Worker NIR_PASS_V(nir, nir_lower_io_to_temporaries,
184*61046927SAndroid Build Coastguard Worker nir_shader_get_entrypoint(nir), true, false);
185*61046927SAndroid Build Coastguard Worker
186*61046927SAndroid Build Coastguard Worker if (use_nak(pdev, nir->info.stage))
187*61046927SAndroid Build Coastguard Worker nak_preprocess_nir(nir, pdev->nak);
188*61046927SAndroid Build Coastguard Worker else
189*61046927SAndroid Build Coastguard Worker nvk_cg_preprocess_nir(nir);
190*61046927SAndroid Build Coastguard Worker }
191*61046927SAndroid Build Coastguard Worker
192*61046927SAndroid Build Coastguard Worker static void
nvk_populate_fs_key(struct nak_fs_key * key,const struct vk_graphics_pipeline_state * state)193*61046927SAndroid Build Coastguard Worker nvk_populate_fs_key(struct nak_fs_key *key,
194*61046927SAndroid Build Coastguard Worker const struct vk_graphics_pipeline_state *state)
195*61046927SAndroid Build Coastguard Worker {
196*61046927SAndroid Build Coastguard Worker memset(key, 0, sizeof(*key));
197*61046927SAndroid Build Coastguard Worker
198*61046927SAndroid Build Coastguard Worker key->sample_info_cb = 0;
199*61046927SAndroid Build Coastguard Worker key->sample_locations_offset = nvk_root_descriptor_offset(draw.sample_locations);
200*61046927SAndroid Build Coastguard Worker key->sample_masks_offset = nvk_root_descriptor_offset(draw.sample_masks);
201*61046927SAndroid Build Coastguard Worker
202*61046927SAndroid Build Coastguard Worker /* Turn underestimate on when no state is availaible or if explicitly set */
203*61046927SAndroid Build Coastguard Worker if (state == NULL || state->rs == NULL ||
204*61046927SAndroid Build Coastguard Worker state->rs->conservative_mode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT)
205*61046927SAndroid Build Coastguard Worker key->uses_underestimate = true;
206*61046927SAndroid Build Coastguard Worker
207*61046927SAndroid Build Coastguard Worker if (state == NULL)
208*61046927SAndroid Build Coastguard Worker return;
209*61046927SAndroid Build Coastguard Worker
210*61046927SAndroid Build Coastguard Worker if (state->pipeline_flags &
211*61046927SAndroid Build Coastguard Worker VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT)
212*61046927SAndroid Build Coastguard Worker key->zs_self_dep = true;
213*61046927SAndroid Build Coastguard Worker
214*61046927SAndroid Build Coastguard Worker /* We force per-sample interpolation whenever sampleShadingEnable is set
215*61046927SAndroid Build Coastguard Worker * regardless of minSampleShading or rasterizationSamples.
216*61046927SAndroid Build Coastguard Worker *
217*61046927SAndroid Build Coastguard Worker * When sampleShadingEnable is set, few guarantees are made about the
218*61046927SAndroid Build Coastguard Worker * location of interpolation of the inputs. The only real guarantees are
219*61046927SAndroid Build Coastguard Worker * that the inputs are interpolated within the pixel and that you get at
220*61046927SAndroid Build Coastguard Worker * least `rasterizationSamples * minSampleShading` unique positions.
221*61046927SAndroid Build Coastguard Worker * Importantly, it does not require that when `rasterizationSamples *
222*61046927SAndroid Build Coastguard Worker * minSampleShading <= 1.0` that those positions are at the fragment
223*61046927SAndroid Build Coastguard Worker * center. Therefore, it's valid to just always do per-sample (which maps
224*61046927SAndroid Build Coastguard Worker * to CENTROID on NVIDIA hardware) all the time and let the hardware sort
225*61046927SAndroid Build Coastguard Worker * it out based on what we set in HYBRID_ANTI_ALIAS_CONTROL::passes.
226*61046927SAndroid Build Coastguard Worker *
227*61046927SAndroid Build Coastguard Worker * Also, we set HYBRID_ANTI_ALIAS_CONTROL::centroid at draw time based on
228*61046927SAndroid Build Coastguard Worker * `rasterizationSamples * minSampleShading` so it should be per-pixel
229*61046927SAndroid Build Coastguard Worker * whenever we're running only a single pass. However, this would still be
230*61046927SAndroid Build Coastguard Worker * correct even if it got interpolated at some other sample.
231*61046927SAndroid Build Coastguard Worker *
232*61046927SAndroid Build Coastguard Worker * The one caveat here is that we have to be careful about gl_SampleMaskIn.
233*61046927SAndroid Build Coastguard Worker * When `nak_fs_key::force_sample_shading = true` we also turn any reads of
234*61046927SAndroid Build Coastguard Worker * gl_SampleMaskIn into `1 << gl_SampleID` because the hardware sample mask
235*61046927SAndroid Build Coastguard Worker * is actually per-fragment, not per-pass. We handle this by smashing
236*61046927SAndroid Build Coastguard Worker * minSampleShading to 1.0 whenever gl_SampleMaskIn is read.
237*61046927SAndroid Build Coastguard Worker */
238*61046927SAndroid Build Coastguard Worker const struct vk_multisample_state *ms = state->ms;
239*61046927SAndroid Build Coastguard Worker if (ms != NULL && ms->sample_shading_enable)
240*61046927SAndroid Build Coastguard Worker key->force_sample_shading = true;
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker
243*61046927SAndroid Build Coastguard Worker static void
nvk_hash_graphics_state(struct vk_physical_device * device,const struct vk_graphics_pipeline_state * state,VkShaderStageFlags stages,blake3_hash blake3_out)244*61046927SAndroid Build Coastguard Worker nvk_hash_graphics_state(struct vk_physical_device *device,
245*61046927SAndroid Build Coastguard Worker const struct vk_graphics_pipeline_state *state,
246*61046927SAndroid Build Coastguard Worker VkShaderStageFlags stages,
247*61046927SAndroid Build Coastguard Worker blake3_hash blake3_out)
248*61046927SAndroid Build Coastguard Worker {
249*61046927SAndroid Build Coastguard Worker struct mesa_blake3 blake3_ctx;
250*61046927SAndroid Build Coastguard Worker _mesa_blake3_init(&blake3_ctx);
251*61046927SAndroid Build Coastguard Worker if (stages & VK_SHADER_STAGE_FRAGMENT_BIT) {
252*61046927SAndroid Build Coastguard Worker struct nak_fs_key key;
253*61046927SAndroid Build Coastguard Worker nvk_populate_fs_key(&key, state);
254*61046927SAndroid Build Coastguard Worker _mesa_blake3_update(&blake3_ctx, &key, sizeof(key));
255*61046927SAndroid Build Coastguard Worker
256*61046927SAndroid Build Coastguard Worker const bool is_multiview = state->rp->view_mask != 0;
257*61046927SAndroid Build Coastguard Worker _mesa_blake3_update(&blake3_ctx, &is_multiview, sizeof(is_multiview));
258*61046927SAndroid Build Coastguard Worker
259*61046927SAndroid Build Coastguard Worker /* This doesn't impact the shader compile but it does go in the
260*61046927SAndroid Build Coastguard Worker * nvk_shader and gets [de]serialized along with the binary so we
261*61046927SAndroid Build Coastguard Worker * need to hash it.
262*61046927SAndroid Build Coastguard Worker */
263*61046927SAndroid Build Coastguard Worker if (state->ms && state->ms->sample_shading_enable) {
264*61046927SAndroid Build Coastguard Worker _mesa_blake3_update(&blake3_ctx, &state->ms->min_sample_shading,
265*61046927SAndroid Build Coastguard Worker sizeof(state->ms->min_sample_shading));
266*61046927SAndroid Build Coastguard Worker }
267*61046927SAndroid Build Coastguard Worker }
268*61046927SAndroid Build Coastguard Worker _mesa_blake3_final(&blake3_ctx, blake3_out);
269*61046927SAndroid Build Coastguard Worker }
270*61046927SAndroid Build Coastguard Worker
271*61046927SAndroid Build Coastguard Worker static bool
lower_load_intrinsic(nir_builder * b,nir_intrinsic_instr * load,UNUSED void * _data)272*61046927SAndroid Build Coastguard Worker lower_load_intrinsic(nir_builder *b, nir_intrinsic_instr *load,
273*61046927SAndroid Build Coastguard Worker UNUSED void *_data)
274*61046927SAndroid Build Coastguard Worker {
275*61046927SAndroid Build Coastguard Worker switch (load->intrinsic) {
276*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_ubo: {
277*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(&load->instr);
278*61046927SAndroid Build Coastguard Worker
279*61046927SAndroid Build Coastguard Worker nir_def *index = load->src[0].ssa;
280*61046927SAndroid Build Coastguard Worker nir_def *offset = load->src[1].ssa;
281*61046927SAndroid Build Coastguard Worker const enum gl_access_qualifier access = nir_intrinsic_access(load);
282*61046927SAndroid Build Coastguard Worker const uint32_t align_mul = nir_intrinsic_align_mul(load);
283*61046927SAndroid Build Coastguard Worker const uint32_t align_offset = nir_intrinsic_align_offset(load);
284*61046927SAndroid Build Coastguard Worker
285*61046927SAndroid Build Coastguard Worker nir_def *val;
286*61046927SAndroid Build Coastguard Worker if (load->src[0].ssa->num_components == 1) {
287*61046927SAndroid Build Coastguard Worker val = nir_ldc_nv(b, load->num_components, load->def.bit_size,
288*61046927SAndroid Build Coastguard Worker index, offset, .access = access,
289*61046927SAndroid Build Coastguard Worker .align_mul = align_mul,
290*61046927SAndroid Build Coastguard Worker .align_offset = align_offset);
291*61046927SAndroid Build Coastguard Worker } else if (load->src[0].ssa->num_components == 2) {
292*61046927SAndroid Build Coastguard Worker nir_def *handle = nir_pack_64_2x32(b, load->src[0].ssa);
293*61046927SAndroid Build Coastguard Worker val = nir_ldcx_nv(b, load->num_components, load->def.bit_size,
294*61046927SAndroid Build Coastguard Worker handle, offset, .access = access,
295*61046927SAndroid Build Coastguard Worker .align_mul = align_mul,
296*61046927SAndroid Build Coastguard Worker .align_offset = align_offset);
297*61046927SAndroid Build Coastguard Worker } else {
298*61046927SAndroid Build Coastguard Worker unreachable("Invalid UBO index");
299*61046927SAndroid Build Coastguard Worker }
300*61046927SAndroid Build Coastguard Worker nir_def_rewrite_uses(&load->def, val);
301*61046927SAndroid Build Coastguard Worker return true;
302*61046927SAndroid Build Coastguard Worker }
303*61046927SAndroid Build Coastguard Worker
304*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_global_constant_offset:
305*61046927SAndroid Build Coastguard Worker case nir_intrinsic_load_global_constant_bounded: {
306*61046927SAndroid Build Coastguard Worker b->cursor = nir_before_instr(&load->instr);
307*61046927SAndroid Build Coastguard Worker
308*61046927SAndroid Build Coastguard Worker nir_def *base_addr = load->src[0].ssa;
309*61046927SAndroid Build Coastguard Worker nir_def *offset = load->src[1].ssa;
310*61046927SAndroid Build Coastguard Worker
311*61046927SAndroid Build Coastguard Worker nir_def *zero = NULL;
312*61046927SAndroid Build Coastguard Worker if (load->intrinsic == nir_intrinsic_load_global_constant_bounded) {
313*61046927SAndroid Build Coastguard Worker nir_def *bound = load->src[2].ssa;
314*61046927SAndroid Build Coastguard Worker
315*61046927SAndroid Build Coastguard Worker unsigned bit_size = load->def.bit_size;
316*61046927SAndroid Build Coastguard Worker assert(bit_size >= 8 && bit_size % 8 == 0);
317*61046927SAndroid Build Coastguard Worker unsigned byte_size = bit_size / 8;
318*61046927SAndroid Build Coastguard Worker
319*61046927SAndroid Build Coastguard Worker zero = nir_imm_zero(b, load->num_components, bit_size);
320*61046927SAndroid Build Coastguard Worker
321*61046927SAndroid Build Coastguard Worker unsigned load_size = byte_size * load->num_components;
322*61046927SAndroid Build Coastguard Worker
323*61046927SAndroid Build Coastguard Worker nir_def *sat_offset =
324*61046927SAndroid Build Coastguard Worker nir_umin(b, offset, nir_imm_int(b, UINT32_MAX - (load_size - 1)));
325*61046927SAndroid Build Coastguard Worker nir_def *in_bounds =
326*61046927SAndroid Build Coastguard Worker nir_ilt(b, nir_iadd_imm(b, sat_offset, load_size - 1), bound);
327*61046927SAndroid Build Coastguard Worker
328*61046927SAndroid Build Coastguard Worker nir_push_if(b, in_bounds);
329*61046927SAndroid Build Coastguard Worker }
330*61046927SAndroid Build Coastguard Worker
331*61046927SAndroid Build Coastguard Worker nir_def *val =
332*61046927SAndroid Build Coastguard Worker nir_build_load_global_constant(b, load->def.num_components,
333*61046927SAndroid Build Coastguard Worker load->def.bit_size,
334*61046927SAndroid Build Coastguard Worker nir_iadd(b, base_addr, nir_u2u64(b, offset)),
335*61046927SAndroid Build Coastguard Worker .align_mul = nir_intrinsic_align_mul(load),
336*61046927SAndroid Build Coastguard Worker .align_offset = nir_intrinsic_align_offset(load));
337*61046927SAndroid Build Coastguard Worker
338*61046927SAndroid Build Coastguard Worker if (load->intrinsic == nir_intrinsic_load_global_constant_bounded) {
339*61046927SAndroid Build Coastguard Worker nir_pop_if(b, NULL);
340*61046927SAndroid Build Coastguard Worker val = nir_if_phi(b, val, zero);
341*61046927SAndroid Build Coastguard Worker }
342*61046927SAndroid Build Coastguard Worker
343*61046927SAndroid Build Coastguard Worker nir_def_rewrite_uses(&load->def, val);
344*61046927SAndroid Build Coastguard Worker return true;
345*61046927SAndroid Build Coastguard Worker }
346*61046927SAndroid Build Coastguard Worker
347*61046927SAndroid Build Coastguard Worker default:
348*61046927SAndroid Build Coastguard Worker return false;
349*61046927SAndroid Build Coastguard Worker }
350*61046927SAndroid Build Coastguard Worker }
351*61046927SAndroid Build Coastguard Worker
352*61046927SAndroid Build Coastguard Worker struct lower_ycbcr_state {
353*61046927SAndroid Build Coastguard Worker uint32_t set_layout_count;
354*61046927SAndroid Build Coastguard Worker struct vk_descriptor_set_layout * const *set_layouts;
355*61046927SAndroid Build Coastguard Worker };
356*61046927SAndroid Build Coastguard Worker
357*61046927SAndroid Build Coastguard Worker static const struct vk_ycbcr_conversion_state *
lookup_ycbcr_conversion(const void * _state,uint32_t set,uint32_t binding,uint32_t array_index)358*61046927SAndroid Build Coastguard Worker lookup_ycbcr_conversion(const void *_state, uint32_t set,
359*61046927SAndroid Build Coastguard Worker uint32_t binding, uint32_t array_index)
360*61046927SAndroid Build Coastguard Worker {
361*61046927SAndroid Build Coastguard Worker const struct lower_ycbcr_state *state = _state;
362*61046927SAndroid Build Coastguard Worker assert(set < state->set_layout_count);
363*61046927SAndroid Build Coastguard Worker assert(state->set_layouts[set] != NULL);
364*61046927SAndroid Build Coastguard Worker const struct nvk_descriptor_set_layout *set_layout =
365*61046927SAndroid Build Coastguard Worker vk_to_nvk_descriptor_set_layout(state->set_layouts[set]);
366*61046927SAndroid Build Coastguard Worker assert(binding < set_layout->binding_count);
367*61046927SAndroid Build Coastguard Worker
368*61046927SAndroid Build Coastguard Worker const struct nvk_descriptor_set_binding_layout *bind_layout =
369*61046927SAndroid Build Coastguard Worker &set_layout->binding[binding];
370*61046927SAndroid Build Coastguard Worker
371*61046927SAndroid Build Coastguard Worker if (bind_layout->immutable_samplers == NULL)
372*61046927SAndroid Build Coastguard Worker return NULL;
373*61046927SAndroid Build Coastguard Worker
374*61046927SAndroid Build Coastguard Worker array_index = MIN2(array_index, bind_layout->array_size - 1);
375*61046927SAndroid Build Coastguard Worker
376*61046927SAndroid Build Coastguard Worker const struct nvk_sampler *sampler =
377*61046927SAndroid Build Coastguard Worker bind_layout->immutable_samplers[array_index];
378*61046927SAndroid Build Coastguard Worker
379*61046927SAndroid Build Coastguard Worker return sampler && sampler->vk.ycbcr_conversion ?
380*61046927SAndroid Build Coastguard Worker &sampler->vk.ycbcr_conversion->state : NULL;
381*61046927SAndroid Build Coastguard Worker }
382*61046927SAndroid Build Coastguard Worker
383*61046927SAndroid Build Coastguard Worker static inline bool
nir_has_image_var(nir_shader * nir)384*61046927SAndroid Build Coastguard Worker nir_has_image_var(nir_shader *nir)
385*61046927SAndroid Build Coastguard Worker {
386*61046927SAndroid Build Coastguard Worker nir_foreach_image_variable(_, nir)
387*61046927SAndroid Build Coastguard Worker return true;
388*61046927SAndroid Build Coastguard Worker
389*61046927SAndroid Build Coastguard Worker return false;
390*61046927SAndroid Build Coastguard Worker }
391*61046927SAndroid Build Coastguard Worker
392*61046927SAndroid Build Coastguard Worker void
nvk_lower_nir(struct nvk_device * dev,nir_shader * nir,const struct vk_pipeline_robustness_state * rs,bool is_multiview,uint32_t set_layout_count,struct vk_descriptor_set_layout * const * set_layouts,struct nvk_cbuf_map * cbuf_map_out)393*61046927SAndroid Build Coastguard Worker nvk_lower_nir(struct nvk_device *dev, nir_shader *nir,
394*61046927SAndroid Build Coastguard Worker const struct vk_pipeline_robustness_state *rs,
395*61046927SAndroid Build Coastguard Worker bool is_multiview,
396*61046927SAndroid Build Coastguard Worker uint32_t set_layout_count,
397*61046927SAndroid Build Coastguard Worker struct vk_descriptor_set_layout * const *set_layouts,
398*61046927SAndroid Build Coastguard Worker struct nvk_cbuf_map *cbuf_map_out)
399*61046927SAndroid Build Coastguard Worker {
400*61046927SAndroid Build Coastguard Worker struct nvk_physical_device *pdev = nvk_device_physical(dev);
401*61046927SAndroid Build Coastguard Worker
402*61046927SAndroid Build Coastguard Worker if (nir->info.stage == MESA_SHADER_FRAGMENT) {
403*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_lower_input_attachments,
404*61046927SAndroid Build Coastguard Worker &(nir_input_attachment_options) {
405*61046927SAndroid Build Coastguard Worker .use_fragcoord_sysval = use_nak(pdev, nir->info.stage),
406*61046927SAndroid Build Coastguard Worker .use_layer_id_sysval = use_nak(pdev, nir->info.stage) ||
407*61046927SAndroid Build Coastguard Worker is_multiview,
408*61046927SAndroid Build Coastguard Worker .use_view_id_for_layer = is_multiview,
409*61046927SAndroid Build Coastguard Worker });
410*61046927SAndroid Build Coastguard Worker }
411*61046927SAndroid Build Coastguard Worker
412*61046927SAndroid Build Coastguard Worker if (nir->info.stage == MESA_SHADER_TESS_EVAL) {
413*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_lower_patch_vertices,
414*61046927SAndroid Build Coastguard Worker nir->info.tess.tcs_vertices_out, NULL);
415*61046927SAndroid Build Coastguard Worker }
416*61046927SAndroid Build Coastguard Worker
417*61046927SAndroid Build Coastguard Worker const struct lower_ycbcr_state ycbcr_state = {
418*61046927SAndroid Build Coastguard Worker .set_layout_count = set_layout_count,
419*61046927SAndroid Build Coastguard Worker .set_layouts = set_layouts,
420*61046927SAndroid Build Coastguard Worker };
421*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_vk_lower_ycbcr_tex,
422*61046927SAndroid Build Coastguard Worker lookup_ycbcr_conversion, &ycbcr_state);
423*61046927SAndroid Build Coastguard Worker
424*61046927SAndroid Build Coastguard Worker nir_lower_compute_system_values_options csv_options = {
425*61046927SAndroid Build Coastguard Worker .has_base_workgroup_id = true,
426*61046927SAndroid Build Coastguard Worker };
427*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_lower_compute_system_values, &csv_options);
428*61046927SAndroid Build Coastguard Worker
429*61046927SAndroid Build Coastguard Worker /* Lower push constants before lower_descriptors */
430*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_push_const,
431*61046927SAndroid Build Coastguard Worker nir_address_format_32bit_offset);
432*61046927SAndroid Build Coastguard Worker
433*61046927SAndroid Build Coastguard Worker /* Lower non-uniform access before lower_descriptors */
434*61046927SAndroid Build Coastguard Worker enum nir_lower_non_uniform_access_type lower_non_uniform_access_types =
435*61046927SAndroid Build Coastguard Worker nir_lower_non_uniform_ubo_access;
436*61046927SAndroid Build Coastguard Worker
437*61046927SAndroid Build Coastguard Worker if (pdev->info.cls_eng3d < TURING_A) {
438*61046927SAndroid Build Coastguard Worker lower_non_uniform_access_types |= nir_lower_non_uniform_texture_access |
439*61046927SAndroid Build Coastguard Worker nir_lower_non_uniform_image_access;
440*61046927SAndroid Build Coastguard Worker }
441*61046927SAndroid Build Coastguard Worker
442*61046927SAndroid Build Coastguard Worker /* In practice, most shaders do not have non-uniform-qualified accesses
443*61046927SAndroid Build Coastguard Worker * thus a cheaper and likely to fail check is run first.
444*61046927SAndroid Build Coastguard Worker */
445*61046927SAndroid Build Coastguard Worker if (nir_has_non_uniform_access(nir, lower_non_uniform_access_types)) {
446*61046927SAndroid Build Coastguard Worker struct nir_lower_non_uniform_access_options opts = {
447*61046927SAndroid Build Coastguard Worker .types = lower_non_uniform_access_types,
448*61046927SAndroid Build Coastguard Worker .callback = NULL,
449*61046927SAndroid Build Coastguard Worker };
450*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_opt_non_uniform_access);
451*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_lower_non_uniform_access, &opts);
452*61046927SAndroid Build Coastguard Worker }
453*61046927SAndroid Build Coastguard Worker
454*61046927SAndroid Build Coastguard Worker /* TODO: Kepler image lowering requires image params to be loaded from the
455*61046927SAndroid Build Coastguard Worker * descriptor set which we don't currently support.
456*61046927SAndroid Build Coastguard Worker */
457*61046927SAndroid Build Coastguard Worker assert(pdev->info.cls_eng3d >= MAXWELL_A || !nir_has_image_var(nir));
458*61046927SAndroid Build Coastguard Worker
459*61046927SAndroid Build Coastguard Worker struct nvk_cbuf_map *cbuf_map = NULL;
460*61046927SAndroid Build Coastguard Worker if (use_nak(pdev, nir->info.stage) &&
461*61046927SAndroid Build Coastguard Worker !(pdev->debug_flags & NVK_DEBUG_NO_CBUF)) {
462*61046927SAndroid Build Coastguard Worker cbuf_map = cbuf_map_out;
463*61046927SAndroid Build Coastguard Worker
464*61046927SAndroid Build Coastguard Worker /* Large constant support assumes cbufs */
465*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_opt_large_constants, NULL, 32);
466*61046927SAndroid Build Coastguard Worker } else {
467*61046927SAndroid Build Coastguard Worker /* Codegen sometimes puts stuff in cbuf 1 and adds 1 to our cbuf indices
468*61046927SAndroid Build Coastguard Worker * so we can't really rely on it for lowering to cbufs and instead place
469*61046927SAndroid Build Coastguard Worker * the root descriptors in both cbuf 0 and cbuf 1.
470*61046927SAndroid Build Coastguard Worker */
471*61046927SAndroid Build Coastguard Worker *cbuf_map_out = (struct nvk_cbuf_map) {
472*61046927SAndroid Build Coastguard Worker .cbuf_count = 2,
473*61046927SAndroid Build Coastguard Worker .cbufs = {
474*61046927SAndroid Build Coastguard Worker { .type = NVK_CBUF_TYPE_ROOT_DESC },
475*61046927SAndroid Build Coastguard Worker { .type = NVK_CBUF_TYPE_ROOT_DESC },
476*61046927SAndroid Build Coastguard Worker }
477*61046927SAndroid Build Coastguard Worker };
478*61046927SAndroid Build Coastguard Worker }
479*61046927SAndroid Build Coastguard Worker
480*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nvk_nir_lower_descriptors, pdev, rs,
481*61046927SAndroid Build Coastguard Worker set_layout_count, set_layouts, cbuf_map);
482*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_global,
483*61046927SAndroid Build Coastguard Worker nir_address_format_64bit_global);
484*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_ssbo,
485*61046927SAndroid Build Coastguard Worker nvk_ssbo_addr_format(pdev, rs));
486*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_lower_explicit_io, nir_var_mem_ubo,
487*61046927SAndroid Build Coastguard Worker nvk_ubo_addr_format(pdev, rs));
488*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_shader_intrinsics_pass,
489*61046927SAndroid Build Coastguard Worker lower_load_intrinsic, nir_metadata_none, NULL);
490*61046927SAndroid Build Coastguard Worker
491*61046927SAndroid Build Coastguard Worker if (!nir->info.shared_memory_explicit_layout) {
492*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_lower_vars_to_explicit_types,
493*61046927SAndroid Build Coastguard Worker 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,
496*61046927SAndroid Build Coastguard Worker nir_address_format_32bit_offset);
497*61046927SAndroid Build Coastguard Worker
498*61046927SAndroid Build Coastguard Worker if (nir->info.zero_initialize_shared_memory && nir->info.shared_size > 0) {
499*61046927SAndroid Build Coastguard Worker /* QMD::SHARED_MEMORY_SIZE requires an alignment of 256B so it's safe to
500*61046927SAndroid Build Coastguard Worker * align everything up to 16B so we can write whole vec4s.
501*61046927SAndroid Build Coastguard Worker */
502*61046927SAndroid Build Coastguard Worker nir->info.shared_size = align(nir->info.shared_size, 16);
503*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_zero_initialize_shared_memory,
504*61046927SAndroid Build Coastguard Worker nir->info.shared_size, 16);
505*61046927SAndroid Build Coastguard Worker
506*61046927SAndroid Build Coastguard Worker /* We need to call lower_compute_system_values again because
507*61046927SAndroid Build Coastguard Worker * nir_zero_initialize_shared_memory generates load_invocation_id which
508*61046927SAndroid Build Coastguard Worker * has to be lowered to load_invocation_index.
509*61046927SAndroid Build Coastguard Worker */
510*61046927SAndroid Build Coastguard Worker NIR_PASS(_, nir, nir_lower_compute_system_values, NULL);
511*61046927SAndroid Build Coastguard Worker }
512*61046927SAndroid Build Coastguard Worker }
513*61046927SAndroid Build Coastguard Worker
514*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
515*61046927SAndroid Build Coastguard Worker static void
nvk_shader_dump(struct nvk_shader * shader)516*61046927SAndroid Build Coastguard Worker nvk_shader_dump(struct nvk_shader *shader)
517*61046927SAndroid Build Coastguard Worker {
518*61046927SAndroid Build Coastguard Worker unsigned pos;
519*61046927SAndroid Build Coastguard Worker
520*61046927SAndroid Build Coastguard Worker if (shader->info.stage != MESA_SHADER_COMPUTE) {
521*61046927SAndroid Build Coastguard Worker _debug_printf("dumping HDR for %s shader\n",
522*61046927SAndroid Build Coastguard Worker _mesa_shader_stage_to_string(shader->info.stage));
523*61046927SAndroid Build Coastguard Worker for (pos = 0; pos < ARRAY_SIZE(shader->info.hdr); ++pos)
524*61046927SAndroid Build Coastguard Worker _debug_printf("HDR[%02"PRIxPTR"] = 0x%08x\n",
525*61046927SAndroid Build Coastguard Worker pos * sizeof(shader->info.hdr[0]), shader->info.hdr[pos]);
526*61046927SAndroid Build Coastguard Worker }
527*61046927SAndroid Build Coastguard Worker _debug_printf("shader binary code (0x%x bytes):", shader->code_size);
528*61046927SAndroid Build Coastguard Worker for (pos = 0; pos < shader->code_size / 4; ++pos) {
529*61046927SAndroid Build Coastguard Worker if ((pos % 8) == 0)
530*61046927SAndroid Build Coastguard Worker _debug_printf("\n");
531*61046927SAndroid Build Coastguard Worker _debug_printf("%08x ", ((const uint32_t *)shader->code_ptr)[pos]);
532*61046927SAndroid Build Coastguard Worker }
533*61046927SAndroid Build Coastguard Worker _debug_printf("\n");
534*61046927SAndroid Build Coastguard Worker }
535*61046927SAndroid Build Coastguard Worker #endif
536*61046927SAndroid Build Coastguard Worker
537*61046927SAndroid Build Coastguard Worker static VkResult
nvk_compile_nir_with_nak(struct nvk_physical_device * pdev,nir_shader * nir,VkShaderCreateFlagsEXT shader_flags,const struct vk_pipeline_robustness_state * rs,const struct nak_fs_key * fs_key,struct nvk_shader * shader)538*61046927SAndroid Build Coastguard Worker nvk_compile_nir_with_nak(struct nvk_physical_device *pdev,
539*61046927SAndroid Build Coastguard Worker nir_shader *nir,
540*61046927SAndroid Build Coastguard Worker VkShaderCreateFlagsEXT shader_flags,
541*61046927SAndroid Build Coastguard Worker const struct vk_pipeline_robustness_state *rs,
542*61046927SAndroid Build Coastguard Worker const struct nak_fs_key *fs_key,
543*61046927SAndroid Build Coastguard Worker struct nvk_shader *shader)
544*61046927SAndroid Build Coastguard Worker {
545*61046927SAndroid Build Coastguard Worker const bool dump_asm =
546*61046927SAndroid Build Coastguard Worker shader_flags & VK_SHADER_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_MESA;
547*61046927SAndroid Build Coastguard Worker
548*61046927SAndroid Build Coastguard Worker nir_variable_mode robust2_modes = 0;
549*61046927SAndroid Build Coastguard Worker if (rs->uniform_buffers == VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT)
550*61046927SAndroid Build Coastguard Worker robust2_modes |= nir_var_mem_ubo;
551*61046927SAndroid Build Coastguard Worker if (rs->storage_buffers == VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT)
552*61046927SAndroid Build Coastguard Worker robust2_modes |= nir_var_mem_ssbo;
553*61046927SAndroid Build Coastguard Worker
554*61046927SAndroid Build Coastguard Worker shader->nak = nak_compile_shader(nir, dump_asm, pdev->nak, robust2_modes, fs_key);
555*61046927SAndroid Build Coastguard Worker shader->info = shader->nak->info;
556*61046927SAndroid Build Coastguard Worker shader->code_ptr = shader->nak->code;
557*61046927SAndroid Build Coastguard Worker shader->code_size = shader->nak->code_size;
558*61046927SAndroid Build Coastguard Worker
559*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
560*61046927SAndroid Build Coastguard Worker }
561*61046927SAndroid Build Coastguard Worker
562*61046927SAndroid Build Coastguard Worker static VkResult
nvk_compile_nir(struct nvk_device * dev,nir_shader * nir,VkShaderCreateFlagsEXT shader_flags,const struct vk_pipeline_robustness_state * rs,const struct nak_fs_key * fs_key,struct nvk_shader * shader)563*61046927SAndroid Build Coastguard Worker nvk_compile_nir(struct nvk_device *dev, nir_shader *nir,
564*61046927SAndroid Build Coastguard Worker VkShaderCreateFlagsEXT shader_flags,
565*61046927SAndroid Build Coastguard Worker const struct vk_pipeline_robustness_state *rs,
566*61046927SAndroid Build Coastguard Worker const struct nak_fs_key *fs_key,
567*61046927SAndroid Build Coastguard Worker struct nvk_shader *shader)
568*61046927SAndroid Build Coastguard Worker {
569*61046927SAndroid Build Coastguard Worker struct nvk_physical_device *pdev = nvk_device_physical(dev);
570*61046927SAndroid Build Coastguard Worker VkResult result;
571*61046927SAndroid Build Coastguard Worker
572*61046927SAndroid Build Coastguard Worker if (use_nak(pdev, nir->info.stage)) {
573*61046927SAndroid Build Coastguard Worker result = nvk_compile_nir_with_nak(pdev, nir, shader_flags, rs,
574*61046927SAndroid Build Coastguard Worker fs_key, shader);
575*61046927SAndroid Build Coastguard Worker } else {
576*61046927SAndroid Build Coastguard Worker result = nvk_cg_compile_nir(pdev, nir, fs_key, shader);
577*61046927SAndroid Build Coastguard Worker }
578*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
579*61046927SAndroid Build Coastguard Worker return result;
580*61046927SAndroid Build Coastguard Worker
581*61046927SAndroid Build Coastguard Worker if (nir->constant_data_size > 0) {
582*61046927SAndroid Build Coastguard Worker uint32_t data_align = nvk_min_cbuf_alignment(&pdev->info);
583*61046927SAndroid Build Coastguard Worker uint32_t data_size = align(nir->constant_data_size, data_align);
584*61046927SAndroid Build Coastguard Worker
585*61046927SAndroid Build Coastguard Worker void *data = malloc(data_size);
586*61046927SAndroid Build Coastguard Worker if (data == NULL)
587*61046927SAndroid Build Coastguard Worker return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
588*61046927SAndroid Build Coastguard Worker
589*61046927SAndroid Build Coastguard Worker memcpy(data, nir->constant_data, nir->constant_data_size);
590*61046927SAndroid Build Coastguard Worker
591*61046927SAndroid Build Coastguard Worker assert(nir->constant_data_size <= data_size);
592*61046927SAndroid Build Coastguard Worker memset(data + nir->constant_data_size, 0,
593*61046927SAndroid Build Coastguard Worker data_size - nir->constant_data_size);
594*61046927SAndroid Build Coastguard Worker
595*61046927SAndroid Build Coastguard Worker shader->data_ptr = data;
596*61046927SAndroid Build Coastguard Worker shader->data_size = data_size;
597*61046927SAndroid Build Coastguard Worker }
598*61046927SAndroid Build Coastguard Worker
599*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
600*61046927SAndroid Build Coastguard Worker }
601*61046927SAndroid Build Coastguard Worker
602*61046927SAndroid Build Coastguard Worker static VkResult
nvk_shader_upload(struct nvk_device * dev,struct nvk_shader * shader)603*61046927SAndroid Build Coastguard Worker nvk_shader_upload(struct nvk_device *dev, struct nvk_shader *shader)
604*61046927SAndroid Build Coastguard Worker {
605*61046927SAndroid Build Coastguard Worker struct nvk_physical_device *pdev = nvk_device_physical(dev);
606*61046927SAndroid Build Coastguard Worker
607*61046927SAndroid Build Coastguard Worker uint32_t hdr_size = 0;
608*61046927SAndroid Build Coastguard Worker if (shader->info.stage != MESA_SHADER_COMPUTE) {
609*61046927SAndroid Build Coastguard Worker if (pdev->info.cls_eng3d >= TURING_A)
610*61046927SAndroid Build Coastguard Worker hdr_size = TU102_SHADER_HEADER_SIZE;
611*61046927SAndroid Build Coastguard Worker else
612*61046927SAndroid Build Coastguard Worker hdr_size = GF100_SHADER_HEADER_SIZE;
613*61046927SAndroid Build Coastguard Worker }
614*61046927SAndroid Build Coastguard Worker
615*61046927SAndroid Build Coastguard Worker /* Fermi needs 0x40 alignment
616*61046927SAndroid Build Coastguard Worker * Kepler+ needs the first instruction to be 0x80 aligned, so we waste 0x30 bytes
617*61046927SAndroid Build Coastguard Worker */
618*61046927SAndroid Build Coastguard Worker int alignment = pdev->info.cls_eng3d >= KEPLER_A ? 0x80 : 0x40;
619*61046927SAndroid Build Coastguard Worker
620*61046927SAndroid Build Coastguard Worker uint32_t total_size = 0;
621*61046927SAndroid Build Coastguard Worker if (pdev->info.cls_eng3d >= KEPLER_A &&
622*61046927SAndroid Build Coastguard Worker pdev->info.cls_eng3d < TURING_A &&
623*61046927SAndroid Build Coastguard Worker hdr_size > 0) {
624*61046927SAndroid Build Coastguard Worker /* The instructions are what has to be aligned so we need to start at a
625*61046927SAndroid Build Coastguard Worker * small offset (0x30 B) into the upload area.
626*61046927SAndroid Build Coastguard Worker */
627*61046927SAndroid Build Coastguard Worker total_size = alignment - hdr_size;
628*61046927SAndroid Build Coastguard Worker }
629*61046927SAndroid Build Coastguard Worker
630*61046927SAndroid Build Coastguard Worker const uint32_t hdr_offset = total_size;
631*61046927SAndroid Build Coastguard Worker total_size += hdr_size;
632*61046927SAndroid Build Coastguard Worker
633*61046927SAndroid Build Coastguard Worker const uint32_t code_offset = total_size;
634*61046927SAndroid Build Coastguard Worker assert(code_offset % alignment == 0);
635*61046927SAndroid Build Coastguard Worker total_size += shader->code_size;
636*61046927SAndroid Build Coastguard Worker
637*61046927SAndroid Build Coastguard Worker uint32_t data_offset = 0;
638*61046927SAndroid Build Coastguard Worker if (shader->data_size > 0) {
639*61046927SAndroid Build Coastguard Worker uint32_t cbuf_alignment = nvk_min_cbuf_alignment(&pdev->info);
640*61046927SAndroid Build Coastguard Worker alignment = MAX2(alignment, cbuf_alignment);
641*61046927SAndroid Build Coastguard Worker total_size = align(total_size, cbuf_alignment);
642*61046927SAndroid Build Coastguard Worker data_offset = total_size;
643*61046927SAndroid Build Coastguard Worker total_size += shader->data_size;
644*61046927SAndroid Build Coastguard Worker }
645*61046927SAndroid Build Coastguard Worker
646*61046927SAndroid Build Coastguard Worker char *data = malloc(total_size);
647*61046927SAndroid Build Coastguard Worker if (data == NULL)
648*61046927SAndroid Build Coastguard Worker return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
649*61046927SAndroid Build Coastguard Worker
650*61046927SAndroid Build Coastguard Worker assert(hdr_size <= sizeof(shader->info.hdr));
651*61046927SAndroid Build Coastguard Worker memcpy(data + hdr_offset, shader->info.hdr, hdr_size);
652*61046927SAndroid Build Coastguard Worker memcpy(data + code_offset, shader->code_ptr, shader->code_size);
653*61046927SAndroid Build Coastguard Worker if (shader->data_size > 0)
654*61046927SAndroid Build Coastguard Worker memcpy(data + data_offset, shader->data_ptr, shader->data_size);
655*61046927SAndroid Build Coastguard Worker
656*61046927SAndroid Build Coastguard Worker #ifndef NDEBUG
657*61046927SAndroid Build Coastguard Worker if (debug_get_bool_option("NV50_PROG_DEBUG", false))
658*61046927SAndroid Build Coastguard Worker nvk_shader_dump(shader);
659*61046927SAndroid Build Coastguard Worker #endif
660*61046927SAndroid Build Coastguard Worker
661*61046927SAndroid Build Coastguard Worker VkResult result = nvk_heap_upload(dev, &dev->shader_heap, data,
662*61046927SAndroid Build Coastguard Worker total_size, alignment,
663*61046927SAndroid Build Coastguard Worker &shader->upload_addr);
664*61046927SAndroid Build Coastguard Worker if (result == VK_SUCCESS) {
665*61046927SAndroid Build Coastguard Worker shader->upload_size = total_size;
666*61046927SAndroid Build Coastguard Worker
667*61046927SAndroid Build Coastguard Worker shader->hdr_addr = shader->upload_addr + hdr_offset;
668*61046927SAndroid Build Coastguard Worker if (pdev->info.cls_eng3d < VOLTA_A) {
669*61046927SAndroid Build Coastguard Worker const uint64_t heap_base_addr =
670*61046927SAndroid Build Coastguard Worker nvk_heap_contiguous_base_address(&dev->shader_heap);
671*61046927SAndroid Build Coastguard Worker assert(shader->upload_addr - heap_base_addr < UINT32_MAX);
672*61046927SAndroid Build Coastguard Worker shader->hdr_addr -= heap_base_addr;
673*61046927SAndroid Build Coastguard Worker }
674*61046927SAndroid Build Coastguard Worker shader->data_addr = shader->upload_addr + data_offset;
675*61046927SAndroid Build Coastguard Worker }
676*61046927SAndroid Build Coastguard Worker free(data);
677*61046927SAndroid Build Coastguard Worker
678*61046927SAndroid Build Coastguard Worker return result;
679*61046927SAndroid Build Coastguard Worker }
680*61046927SAndroid Build Coastguard Worker
681*61046927SAndroid Build Coastguard Worker static const struct vk_shader_ops nvk_shader_ops;
682*61046927SAndroid Build Coastguard Worker
683*61046927SAndroid Build Coastguard Worker static void
nvk_shader_destroy(struct vk_device * vk_dev,struct vk_shader * vk_shader,const VkAllocationCallbacks * pAllocator)684*61046927SAndroid Build Coastguard Worker nvk_shader_destroy(struct vk_device *vk_dev,
685*61046927SAndroid Build Coastguard Worker struct vk_shader *vk_shader,
686*61046927SAndroid Build Coastguard Worker const VkAllocationCallbacks* pAllocator)
687*61046927SAndroid Build Coastguard Worker {
688*61046927SAndroid Build Coastguard Worker struct nvk_device *dev = container_of(vk_dev, struct nvk_device, vk);
689*61046927SAndroid Build Coastguard Worker struct nvk_shader *shader = container_of(vk_shader, struct nvk_shader, vk);
690*61046927SAndroid Build Coastguard Worker
691*61046927SAndroid Build Coastguard Worker if (shader->upload_size > 0) {
692*61046927SAndroid Build Coastguard Worker nvk_heap_free(dev, &dev->shader_heap,
693*61046927SAndroid Build Coastguard Worker shader->upload_addr,
694*61046927SAndroid Build Coastguard Worker shader->upload_size);
695*61046927SAndroid Build Coastguard Worker }
696*61046927SAndroid Build Coastguard Worker
697*61046927SAndroid Build Coastguard Worker if (shader->nak) {
698*61046927SAndroid Build Coastguard Worker nak_shader_bin_destroy(shader->nak);
699*61046927SAndroid Build Coastguard Worker } else {
700*61046927SAndroid Build Coastguard Worker /* This came from codegen or deserialize, just free it */
701*61046927SAndroid Build Coastguard Worker free((void *)shader->code_ptr);
702*61046927SAndroid Build Coastguard Worker }
703*61046927SAndroid Build Coastguard Worker
704*61046927SAndroid Build Coastguard Worker free((void *)shader->data_ptr);
705*61046927SAndroid Build Coastguard Worker
706*61046927SAndroid Build Coastguard Worker vk_shader_free(&dev->vk, pAllocator, &shader->vk);
707*61046927SAndroid Build Coastguard Worker }
708*61046927SAndroid Build Coastguard Worker
709*61046927SAndroid Build Coastguard Worker static VkResult
nvk_compile_shader(struct nvk_device * dev,struct vk_shader_compile_info * info,const struct vk_graphics_pipeline_state * state,const VkAllocationCallbacks * pAllocator,struct vk_shader ** shader_out)710*61046927SAndroid Build Coastguard Worker nvk_compile_shader(struct nvk_device *dev,
711*61046927SAndroid Build Coastguard Worker struct vk_shader_compile_info *info,
712*61046927SAndroid Build Coastguard Worker const struct vk_graphics_pipeline_state *state,
713*61046927SAndroid Build Coastguard Worker const VkAllocationCallbacks* pAllocator,
714*61046927SAndroid Build Coastguard Worker struct vk_shader **shader_out)
715*61046927SAndroid Build Coastguard Worker {
716*61046927SAndroid Build Coastguard Worker struct nvk_shader *shader;
717*61046927SAndroid Build Coastguard Worker VkResult result;
718*61046927SAndroid Build Coastguard Worker
719*61046927SAndroid Build Coastguard Worker /* We consume the NIR, regardless of success or failure */
720*61046927SAndroid Build Coastguard Worker nir_shader *nir = info->nir;
721*61046927SAndroid Build Coastguard Worker
722*61046927SAndroid Build Coastguard Worker shader = vk_shader_zalloc(&dev->vk, &nvk_shader_ops, info->stage,
723*61046927SAndroid Build Coastguard Worker pAllocator, sizeof(*shader));
724*61046927SAndroid Build Coastguard Worker if (shader == NULL) {
725*61046927SAndroid Build Coastguard Worker ralloc_free(nir);
726*61046927SAndroid Build Coastguard Worker return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
727*61046927SAndroid Build Coastguard Worker }
728*61046927SAndroid Build Coastguard Worker
729*61046927SAndroid Build Coastguard Worker /* TODO: Multiview with ESO */
730*61046927SAndroid Build Coastguard Worker const bool is_multiview = state && state->rp->view_mask != 0;
731*61046927SAndroid Build Coastguard Worker
732*61046927SAndroid Build Coastguard Worker nvk_lower_nir(dev, nir, info->robustness, is_multiview,
733*61046927SAndroid Build Coastguard Worker info->set_layout_count, info->set_layouts,
734*61046927SAndroid Build Coastguard Worker &shader->cbuf_map);
735*61046927SAndroid Build Coastguard Worker
736*61046927SAndroid Build Coastguard Worker struct nak_fs_key fs_key_tmp, *fs_key = NULL;
737*61046927SAndroid Build Coastguard Worker if (nir->info.stage == MESA_SHADER_FRAGMENT) {
738*61046927SAndroid Build Coastguard Worker nvk_populate_fs_key(&fs_key_tmp, state);
739*61046927SAndroid Build Coastguard Worker fs_key = &fs_key_tmp;
740*61046927SAndroid Build Coastguard Worker }
741*61046927SAndroid Build Coastguard Worker
742*61046927SAndroid Build Coastguard Worker result = nvk_compile_nir(dev, nir, info->flags, info->robustness,
743*61046927SAndroid Build Coastguard Worker fs_key, shader);
744*61046927SAndroid Build Coastguard Worker ralloc_free(nir);
745*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
746*61046927SAndroid Build Coastguard Worker nvk_shader_destroy(&dev->vk, &shader->vk, pAllocator);
747*61046927SAndroid Build Coastguard Worker return result;
748*61046927SAndroid Build Coastguard Worker }
749*61046927SAndroid Build Coastguard Worker
750*61046927SAndroid Build Coastguard Worker result = nvk_shader_upload(dev, shader);
751*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
752*61046927SAndroid Build Coastguard Worker nvk_shader_destroy(&dev->vk, &shader->vk, pAllocator);
753*61046927SAndroid Build Coastguard Worker return result;
754*61046927SAndroid Build Coastguard Worker }
755*61046927SAndroid Build Coastguard Worker
756*61046927SAndroid Build Coastguard Worker if (info->stage == MESA_SHADER_FRAGMENT) {
757*61046927SAndroid Build Coastguard Worker if (shader->info.fs.uses_sample_shading) {
758*61046927SAndroid Build Coastguard Worker shader->min_sample_shading = 1;
759*61046927SAndroid Build Coastguard Worker } else if (state != NULL && state->ms != NULL &&
760*61046927SAndroid Build Coastguard Worker state->ms->sample_shading_enable) {
761*61046927SAndroid Build Coastguard Worker shader->min_sample_shading =
762*61046927SAndroid Build Coastguard Worker CLAMP(state->ms->min_sample_shading, 0, 1);
763*61046927SAndroid Build Coastguard Worker } else {
764*61046927SAndroid Build Coastguard Worker shader->min_sample_shading = 0;
765*61046927SAndroid Build Coastguard Worker }
766*61046927SAndroid Build Coastguard Worker }
767*61046927SAndroid Build Coastguard Worker
768*61046927SAndroid Build Coastguard Worker *shader_out = &shader->vk;
769*61046927SAndroid Build Coastguard Worker
770*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
771*61046927SAndroid Build Coastguard Worker }
772*61046927SAndroid Build Coastguard Worker
773*61046927SAndroid Build Coastguard Worker VkResult
nvk_compile_nir_shader(struct nvk_device * dev,nir_shader * nir,const VkAllocationCallbacks * alloc,struct nvk_shader ** shader_out)774*61046927SAndroid Build Coastguard Worker nvk_compile_nir_shader(struct nvk_device *dev, nir_shader *nir,
775*61046927SAndroid Build Coastguard Worker const VkAllocationCallbacks *alloc,
776*61046927SAndroid Build Coastguard Worker struct nvk_shader **shader_out)
777*61046927SAndroid Build Coastguard Worker {
778*61046927SAndroid Build Coastguard Worker struct nvk_physical_device *pdev = nvk_device_physical(dev);
779*61046927SAndroid Build Coastguard Worker
780*61046927SAndroid Build Coastguard Worker const struct vk_pipeline_robustness_state rs_none = {
781*61046927SAndroid Build Coastguard Worker .uniform_buffers = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT,
782*61046927SAndroid Build Coastguard Worker .storage_buffers = VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT,
783*61046927SAndroid Build Coastguard Worker .images = VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2_EXT,
784*61046927SAndroid Build Coastguard Worker };
785*61046927SAndroid Build Coastguard Worker
786*61046927SAndroid Build Coastguard Worker assert(nir->info.stage == MESA_SHADER_COMPUTE);
787*61046927SAndroid Build Coastguard Worker if (nir->options == NULL)
788*61046927SAndroid Build Coastguard Worker nir->options = nvk_get_nir_options(&pdev->vk, nir->info.stage, &rs_none);
789*61046927SAndroid Build Coastguard Worker
790*61046927SAndroid Build Coastguard Worker struct vk_shader_compile_info info = {
791*61046927SAndroid Build Coastguard Worker .stage = nir->info.stage,
792*61046927SAndroid Build Coastguard Worker .nir = nir,
793*61046927SAndroid Build Coastguard Worker .robustness = &rs_none,
794*61046927SAndroid Build Coastguard Worker };
795*61046927SAndroid Build Coastguard Worker
796*61046927SAndroid Build Coastguard Worker struct vk_shader *shader;
797*61046927SAndroid Build Coastguard Worker VkResult result = nvk_compile_shader(dev, &info, NULL, alloc, &shader);
798*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS)
799*61046927SAndroid Build Coastguard Worker return result;
800*61046927SAndroid Build Coastguard Worker
801*61046927SAndroid Build Coastguard Worker *shader_out = container_of(shader, struct nvk_shader, vk);
802*61046927SAndroid Build Coastguard Worker
803*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
804*61046927SAndroid Build Coastguard Worker }
805*61046927SAndroid Build Coastguard Worker
806*61046927SAndroid Build Coastguard Worker static VkResult
nvk_compile_shaders(struct vk_device * vk_dev,uint32_t shader_count,struct vk_shader_compile_info * infos,const struct vk_graphics_pipeline_state * state,const VkAllocationCallbacks * pAllocator,struct vk_shader ** shaders_out)807*61046927SAndroid Build Coastguard Worker nvk_compile_shaders(struct vk_device *vk_dev,
808*61046927SAndroid Build Coastguard Worker uint32_t shader_count,
809*61046927SAndroid Build Coastguard Worker struct vk_shader_compile_info *infos,
810*61046927SAndroid Build Coastguard Worker const struct vk_graphics_pipeline_state *state,
811*61046927SAndroid Build Coastguard Worker const VkAllocationCallbacks* pAllocator,
812*61046927SAndroid Build Coastguard Worker struct vk_shader **shaders_out)
813*61046927SAndroid Build Coastguard Worker {
814*61046927SAndroid Build Coastguard Worker struct nvk_device *dev = container_of(vk_dev, struct nvk_device, vk);
815*61046927SAndroid Build Coastguard Worker
816*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < shader_count; i++) {
817*61046927SAndroid Build Coastguard Worker VkResult result = nvk_compile_shader(dev, &infos[i], state,
818*61046927SAndroid Build Coastguard Worker pAllocator, &shaders_out[i]);
819*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
820*61046927SAndroid Build Coastguard Worker /* Clean up all the shaders before this point */
821*61046927SAndroid Build Coastguard Worker for (uint32_t j = 0; j < i; j++)
822*61046927SAndroid Build Coastguard Worker nvk_shader_destroy(&dev->vk, shaders_out[j], pAllocator);
823*61046927SAndroid Build Coastguard Worker
824*61046927SAndroid Build Coastguard Worker /* Clean up all the NIR after this point */
825*61046927SAndroid Build Coastguard Worker for (uint32_t j = i + 1; j < shader_count; j++)
826*61046927SAndroid Build Coastguard Worker ralloc_free(infos[j].nir);
827*61046927SAndroid Build Coastguard Worker
828*61046927SAndroid Build Coastguard Worker /* Memset the output array */
829*61046927SAndroid Build Coastguard Worker memset(shaders_out, 0, shader_count * sizeof(*shaders_out));
830*61046927SAndroid Build Coastguard Worker
831*61046927SAndroid Build Coastguard Worker return result;
832*61046927SAndroid Build Coastguard Worker }
833*61046927SAndroid Build Coastguard Worker }
834*61046927SAndroid Build Coastguard Worker
835*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
836*61046927SAndroid Build Coastguard Worker }
837*61046927SAndroid Build Coastguard Worker
838*61046927SAndroid Build Coastguard Worker static VkResult
nvk_deserialize_shader(struct vk_device * vk_dev,struct blob_reader * blob,uint32_t binary_version,const VkAllocationCallbacks * pAllocator,struct vk_shader ** shader_out)839*61046927SAndroid Build Coastguard Worker nvk_deserialize_shader(struct vk_device *vk_dev,
840*61046927SAndroid Build Coastguard Worker struct blob_reader *blob,
841*61046927SAndroid Build Coastguard Worker uint32_t binary_version,
842*61046927SAndroid Build Coastguard Worker const VkAllocationCallbacks* pAllocator,
843*61046927SAndroid Build Coastguard Worker struct vk_shader **shader_out)
844*61046927SAndroid Build Coastguard Worker {
845*61046927SAndroid Build Coastguard Worker struct nvk_device *dev = container_of(vk_dev, struct nvk_device, vk);
846*61046927SAndroid Build Coastguard Worker struct nvk_shader *shader;
847*61046927SAndroid Build Coastguard Worker VkResult result;
848*61046927SAndroid Build Coastguard Worker
849*61046927SAndroid Build Coastguard Worker struct nak_shader_info info;
850*61046927SAndroid Build Coastguard Worker blob_copy_bytes(blob, &info, sizeof(info));
851*61046927SAndroid Build Coastguard Worker
852*61046927SAndroid Build Coastguard Worker struct nvk_cbuf_map cbuf_map;
853*61046927SAndroid Build Coastguard Worker blob_copy_bytes(blob, &cbuf_map, sizeof(cbuf_map));
854*61046927SAndroid Build Coastguard Worker
855*61046927SAndroid Build Coastguard Worker float min_sample_shading;
856*61046927SAndroid Build Coastguard Worker blob_copy_bytes(blob, &min_sample_shading, sizeof(min_sample_shading));
857*61046927SAndroid Build Coastguard Worker
858*61046927SAndroid Build Coastguard Worker const uint32_t code_size = blob_read_uint32(blob);
859*61046927SAndroid Build Coastguard Worker const uint32_t data_size = blob_read_uint32(blob);
860*61046927SAndroid Build Coastguard Worker if (blob->overrun)
861*61046927SAndroid Build Coastguard Worker return vk_error(dev, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
862*61046927SAndroid Build Coastguard Worker
863*61046927SAndroid Build Coastguard Worker shader = vk_shader_zalloc(&dev->vk, &nvk_shader_ops, info.stage,
864*61046927SAndroid Build Coastguard Worker pAllocator, sizeof(*shader));
865*61046927SAndroid Build Coastguard Worker if (shader == NULL)
866*61046927SAndroid Build Coastguard Worker return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
867*61046927SAndroid Build Coastguard Worker
868*61046927SAndroid Build Coastguard Worker shader->info = info;
869*61046927SAndroid Build Coastguard Worker shader->cbuf_map = cbuf_map;
870*61046927SAndroid Build Coastguard Worker shader->min_sample_shading = min_sample_shading;
871*61046927SAndroid Build Coastguard Worker shader->code_size = code_size;
872*61046927SAndroid Build Coastguard Worker shader->data_size = data_size;
873*61046927SAndroid Build Coastguard Worker
874*61046927SAndroid Build Coastguard Worker shader->code_ptr = malloc(code_size);
875*61046927SAndroid Build Coastguard Worker if (shader->code_ptr == NULL) {
876*61046927SAndroid Build Coastguard Worker nvk_shader_destroy(&dev->vk, &shader->vk, pAllocator);
877*61046927SAndroid Build Coastguard Worker return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
878*61046927SAndroid Build Coastguard Worker }
879*61046927SAndroid Build Coastguard Worker
880*61046927SAndroid Build Coastguard Worker shader->data_ptr = malloc(data_size);
881*61046927SAndroid Build Coastguard Worker if (shader->data_ptr == NULL) {
882*61046927SAndroid Build Coastguard Worker nvk_shader_destroy(&dev->vk, &shader->vk, pAllocator);
883*61046927SAndroid Build Coastguard Worker return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY);
884*61046927SAndroid Build Coastguard Worker }
885*61046927SAndroid Build Coastguard Worker
886*61046927SAndroid Build Coastguard Worker blob_copy_bytes(blob, (void *)shader->code_ptr, shader->code_size);
887*61046927SAndroid Build Coastguard Worker blob_copy_bytes(blob, (void *)shader->data_ptr, shader->data_size);
888*61046927SAndroid Build Coastguard Worker if (blob->overrun) {
889*61046927SAndroid Build Coastguard Worker nvk_shader_destroy(&dev->vk, &shader->vk, pAllocator);
890*61046927SAndroid Build Coastguard Worker return vk_error(dev, VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT);
891*61046927SAndroid Build Coastguard Worker }
892*61046927SAndroid Build Coastguard Worker
893*61046927SAndroid Build Coastguard Worker result = nvk_shader_upload(dev, shader);
894*61046927SAndroid Build Coastguard Worker if (result != VK_SUCCESS) {
895*61046927SAndroid Build Coastguard Worker nvk_shader_destroy(&dev->vk, &shader->vk, pAllocator);
896*61046927SAndroid Build Coastguard Worker return result;
897*61046927SAndroid Build Coastguard Worker }
898*61046927SAndroid Build Coastguard Worker
899*61046927SAndroid Build Coastguard Worker *shader_out = &shader->vk;
900*61046927SAndroid Build Coastguard Worker
901*61046927SAndroid Build Coastguard Worker return VK_SUCCESS;
902*61046927SAndroid Build Coastguard Worker }
903*61046927SAndroid Build Coastguard Worker
904*61046927SAndroid Build Coastguard Worker static bool
nvk_shader_serialize(struct vk_device * vk_dev,const struct vk_shader * vk_shader,struct blob * blob)905*61046927SAndroid Build Coastguard Worker nvk_shader_serialize(struct vk_device *vk_dev,
906*61046927SAndroid Build Coastguard Worker const struct vk_shader *vk_shader,
907*61046927SAndroid Build Coastguard Worker struct blob *blob)
908*61046927SAndroid Build Coastguard Worker {
909*61046927SAndroid Build Coastguard Worker struct nvk_shader *shader = container_of(vk_shader, struct nvk_shader, vk);
910*61046927SAndroid Build Coastguard Worker
911*61046927SAndroid Build Coastguard Worker /* We can't currently cache assmbly */
912*61046927SAndroid Build Coastguard Worker if (shader->nak != NULL && shader->nak->asm_str != NULL)
913*61046927SAndroid Build Coastguard Worker return false;
914*61046927SAndroid Build Coastguard Worker
915*61046927SAndroid Build Coastguard Worker blob_write_bytes(blob, &shader->info, sizeof(shader->info));
916*61046927SAndroid Build Coastguard Worker blob_write_bytes(blob, &shader->cbuf_map, sizeof(shader->cbuf_map));
917*61046927SAndroid Build Coastguard Worker blob_write_bytes(blob, &shader->min_sample_shading,
918*61046927SAndroid Build Coastguard Worker sizeof(shader->min_sample_shading));
919*61046927SAndroid Build Coastguard Worker
920*61046927SAndroid Build Coastguard Worker blob_write_uint32(blob, shader->code_size);
921*61046927SAndroid Build Coastguard Worker blob_write_uint32(blob, shader->data_size);
922*61046927SAndroid Build Coastguard Worker blob_write_bytes(blob, shader->code_ptr, shader->code_size);
923*61046927SAndroid Build Coastguard Worker blob_write_bytes(blob, shader->data_ptr, shader->data_size);
924*61046927SAndroid Build Coastguard Worker
925*61046927SAndroid Build Coastguard Worker return !blob->out_of_memory;
926*61046927SAndroid Build Coastguard Worker }
927*61046927SAndroid Build Coastguard Worker
928*61046927SAndroid Build Coastguard Worker #define WRITE_STR(field, ...) ({ \
929*61046927SAndroid Build Coastguard Worker memset(field, 0, sizeof(field)); \
930*61046927SAndroid Build Coastguard Worker UNUSED int i = snprintf(field, sizeof(field), __VA_ARGS__); \
931*61046927SAndroid Build Coastguard Worker assert(i > 0 && i < sizeof(field)); \
932*61046927SAndroid Build Coastguard Worker })
933*61046927SAndroid Build Coastguard Worker
934*61046927SAndroid Build Coastguard Worker static VkResult
nvk_shader_get_executable_properties(UNUSED struct vk_device * device,const struct vk_shader * vk_shader,uint32_t * executable_count,VkPipelineExecutablePropertiesKHR * properties)935*61046927SAndroid Build Coastguard Worker nvk_shader_get_executable_properties(
936*61046927SAndroid Build Coastguard Worker UNUSED struct vk_device *device,
937*61046927SAndroid Build Coastguard Worker const struct vk_shader *vk_shader,
938*61046927SAndroid Build Coastguard Worker uint32_t *executable_count,
939*61046927SAndroid Build Coastguard Worker VkPipelineExecutablePropertiesKHR *properties)
940*61046927SAndroid Build Coastguard Worker {
941*61046927SAndroid Build Coastguard Worker struct nvk_shader *shader = container_of(vk_shader, struct nvk_shader, vk);
942*61046927SAndroid Build Coastguard Worker VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutablePropertiesKHR, out,
943*61046927SAndroid Build Coastguard Worker properties, executable_count);
944*61046927SAndroid Build Coastguard Worker
945*61046927SAndroid Build Coastguard Worker vk_outarray_append_typed(VkPipelineExecutablePropertiesKHR, &out, props) {
946*61046927SAndroid Build Coastguard Worker props->stages = mesa_to_vk_shader_stage(shader->info.stage);
947*61046927SAndroid Build Coastguard Worker props->subgroupSize = 32;
948*61046927SAndroid Build Coastguard Worker WRITE_STR(props->name, "%s",
949*61046927SAndroid Build Coastguard Worker _mesa_shader_stage_to_string(shader->info.stage));
950*61046927SAndroid Build Coastguard Worker WRITE_STR(props->description, "%s shader",
951*61046927SAndroid Build Coastguard Worker _mesa_shader_stage_to_string(shader->info.stage));
952*61046927SAndroid Build Coastguard Worker }
953*61046927SAndroid Build Coastguard Worker
954*61046927SAndroid Build Coastguard Worker return vk_outarray_status(&out);
955*61046927SAndroid Build Coastguard Worker }
956*61046927SAndroid Build Coastguard Worker
957*61046927SAndroid Build Coastguard Worker static VkResult
nvk_shader_get_executable_statistics(UNUSED struct vk_device * device,const struct vk_shader * vk_shader,uint32_t executable_index,uint32_t * statistic_count,VkPipelineExecutableStatisticKHR * statistics)958*61046927SAndroid Build Coastguard Worker nvk_shader_get_executable_statistics(
959*61046927SAndroid Build Coastguard Worker UNUSED struct vk_device *device,
960*61046927SAndroid Build Coastguard Worker const struct vk_shader *vk_shader,
961*61046927SAndroid Build Coastguard Worker uint32_t executable_index,
962*61046927SAndroid Build Coastguard Worker uint32_t *statistic_count,
963*61046927SAndroid Build Coastguard Worker VkPipelineExecutableStatisticKHR *statistics)
964*61046927SAndroid Build Coastguard Worker {
965*61046927SAndroid Build Coastguard Worker struct nvk_shader *shader = container_of(vk_shader, struct nvk_shader, vk);
966*61046927SAndroid Build Coastguard Worker VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutableStatisticKHR, out,
967*61046927SAndroid Build Coastguard Worker statistics, statistic_count);
968*61046927SAndroid Build Coastguard Worker
969*61046927SAndroid Build Coastguard Worker assert(executable_index == 0);
970*61046927SAndroid Build Coastguard Worker
971*61046927SAndroid Build Coastguard Worker vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat) {
972*61046927SAndroid Build Coastguard Worker WRITE_STR(stat->name, "Instruction count");
973*61046927SAndroid Build Coastguard Worker WRITE_STR(stat->description, "Number of instructions used by this shader");
974*61046927SAndroid Build Coastguard Worker stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
975*61046927SAndroid Build Coastguard Worker stat->value.u64 = shader->info.num_instrs;
976*61046927SAndroid Build Coastguard Worker }
977*61046927SAndroid Build Coastguard Worker
978*61046927SAndroid Build Coastguard Worker vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat) {
979*61046927SAndroid Build Coastguard Worker WRITE_STR(stat->name, "Code Size");
980*61046927SAndroid Build Coastguard Worker WRITE_STR(stat->description,
981*61046927SAndroid Build Coastguard Worker "Size of the compiled shader binary, in bytes");
982*61046927SAndroid Build Coastguard Worker stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
983*61046927SAndroid Build Coastguard Worker stat->value.u64 = shader->code_size;
984*61046927SAndroid Build Coastguard Worker }
985*61046927SAndroid Build Coastguard Worker
986*61046927SAndroid Build Coastguard Worker vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat) {
987*61046927SAndroid Build Coastguard Worker WRITE_STR(stat->name, "Number of GPRs");
988*61046927SAndroid Build Coastguard Worker WRITE_STR(stat->description, "Number of GPRs used by this pipeline");
989*61046927SAndroid Build Coastguard Worker stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
990*61046927SAndroid Build Coastguard Worker stat->value.u64 = shader->info.num_gprs;
991*61046927SAndroid Build Coastguard Worker }
992*61046927SAndroid Build Coastguard Worker
993*61046927SAndroid Build Coastguard Worker vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat) {
994*61046927SAndroid Build Coastguard Worker WRITE_STR(stat->name, "SLM Size");
995*61046927SAndroid Build Coastguard Worker WRITE_STR(stat->description,
996*61046927SAndroid Build Coastguard Worker "Size of shader local (scratch) memory, in bytes");
997*61046927SAndroid Build Coastguard Worker stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR;
998*61046927SAndroid Build Coastguard Worker stat->value.u64 = shader->info.slm_size;
999*61046927SAndroid Build Coastguard Worker }
1000*61046927SAndroid Build Coastguard Worker
1001*61046927SAndroid Build Coastguard Worker return vk_outarray_status(&out);
1002*61046927SAndroid Build Coastguard Worker }
1003*61046927SAndroid Build Coastguard Worker
1004*61046927SAndroid Build Coastguard Worker static bool
write_ir_text(VkPipelineExecutableInternalRepresentationKHR * ir,const char * data)1005*61046927SAndroid Build Coastguard Worker write_ir_text(VkPipelineExecutableInternalRepresentationKHR* ir,
1006*61046927SAndroid Build Coastguard Worker const char *data)
1007*61046927SAndroid Build Coastguard Worker {
1008*61046927SAndroid Build Coastguard Worker ir->isText = VK_TRUE;
1009*61046927SAndroid Build Coastguard Worker
1010*61046927SAndroid Build Coastguard Worker size_t data_len = strlen(data) + 1;
1011*61046927SAndroid Build Coastguard Worker
1012*61046927SAndroid Build Coastguard Worker if (ir->pData == NULL) {
1013*61046927SAndroid Build Coastguard Worker ir->dataSize = data_len;
1014*61046927SAndroid Build Coastguard Worker return true;
1015*61046927SAndroid Build Coastguard Worker }
1016*61046927SAndroid Build Coastguard Worker
1017*61046927SAndroid Build Coastguard Worker strncpy(ir->pData, data, ir->dataSize);
1018*61046927SAndroid Build Coastguard Worker if (ir->dataSize < data_len)
1019*61046927SAndroid Build Coastguard Worker return false;
1020*61046927SAndroid Build Coastguard Worker
1021*61046927SAndroid Build Coastguard Worker ir->dataSize = data_len;
1022*61046927SAndroid Build Coastguard Worker return true;
1023*61046927SAndroid Build Coastguard Worker }
1024*61046927SAndroid Build Coastguard Worker
1025*61046927SAndroid Build Coastguard Worker static VkResult
nvk_shader_get_executable_internal_representations(UNUSED struct vk_device * device,const struct vk_shader * vk_shader,uint32_t executable_index,uint32_t * internal_representation_count,VkPipelineExecutableInternalRepresentationKHR * internal_representations)1026*61046927SAndroid Build Coastguard Worker nvk_shader_get_executable_internal_representations(
1027*61046927SAndroid Build Coastguard Worker UNUSED struct vk_device *device,
1028*61046927SAndroid Build Coastguard Worker const struct vk_shader *vk_shader,
1029*61046927SAndroid Build Coastguard Worker uint32_t executable_index,
1030*61046927SAndroid Build Coastguard Worker uint32_t *internal_representation_count,
1031*61046927SAndroid Build Coastguard Worker VkPipelineExecutableInternalRepresentationKHR *internal_representations)
1032*61046927SAndroid Build Coastguard Worker {
1033*61046927SAndroid Build Coastguard Worker struct nvk_shader *shader = container_of(vk_shader, struct nvk_shader, vk);
1034*61046927SAndroid Build Coastguard Worker VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutableInternalRepresentationKHR, out,
1035*61046927SAndroid Build Coastguard Worker internal_representations,
1036*61046927SAndroid Build Coastguard Worker internal_representation_count);
1037*61046927SAndroid Build Coastguard Worker bool incomplete_text = false;
1038*61046927SAndroid Build Coastguard Worker
1039*61046927SAndroid Build Coastguard Worker assert(executable_index == 0);
1040*61046927SAndroid Build Coastguard Worker
1041*61046927SAndroid Build Coastguard Worker if (shader->nak != NULL && shader->nak->asm_str != NULL) {
1042*61046927SAndroid Build Coastguard Worker vk_outarray_append_typed(VkPipelineExecutableInternalRepresentationKHR, &out, ir) {
1043*61046927SAndroid Build Coastguard Worker WRITE_STR(ir->name, "NAK assembly");
1044*61046927SAndroid Build Coastguard Worker WRITE_STR(ir->description, "NAK assembly");
1045*61046927SAndroid Build Coastguard Worker if (!write_ir_text(ir, shader->nak->asm_str))
1046*61046927SAndroid Build Coastguard Worker incomplete_text = true;
1047*61046927SAndroid Build Coastguard Worker }
1048*61046927SAndroid Build Coastguard Worker }
1049*61046927SAndroid Build Coastguard Worker
1050*61046927SAndroid Build Coastguard Worker return incomplete_text ? VK_INCOMPLETE : vk_outarray_status(&out);
1051*61046927SAndroid Build Coastguard Worker }
1052*61046927SAndroid Build Coastguard Worker
1053*61046927SAndroid Build Coastguard Worker static const struct vk_shader_ops nvk_shader_ops = {
1054*61046927SAndroid Build Coastguard Worker .destroy = nvk_shader_destroy,
1055*61046927SAndroid Build Coastguard Worker .serialize = nvk_shader_serialize,
1056*61046927SAndroid Build Coastguard Worker .get_executable_properties = nvk_shader_get_executable_properties,
1057*61046927SAndroid Build Coastguard Worker .get_executable_statistics = nvk_shader_get_executable_statistics,
1058*61046927SAndroid Build Coastguard Worker .get_executable_internal_representations =
1059*61046927SAndroid Build Coastguard Worker nvk_shader_get_executable_internal_representations,
1060*61046927SAndroid Build Coastguard Worker };
1061*61046927SAndroid Build Coastguard Worker
1062*61046927SAndroid Build Coastguard Worker const struct vk_device_shader_ops nvk_device_shader_ops = {
1063*61046927SAndroid Build Coastguard Worker .get_nir_options = nvk_get_nir_options,
1064*61046927SAndroid Build Coastguard Worker .get_spirv_options = nvk_get_spirv_options,
1065*61046927SAndroid Build Coastguard Worker .preprocess_nir = nvk_preprocess_nir,
1066*61046927SAndroid Build Coastguard Worker .hash_graphics_state = nvk_hash_graphics_state,
1067*61046927SAndroid Build Coastguard Worker .compile = nvk_compile_shaders,
1068*61046927SAndroid Build Coastguard Worker .deserialize = nvk_deserialize_shader,
1069*61046927SAndroid Build Coastguard Worker .cmd_set_dynamic_graphics_state = vk_cmd_set_dynamic_graphics_state,
1070*61046927SAndroid Build Coastguard Worker .cmd_bind_shaders = nvk_cmd_bind_shaders,
1071*61046927SAndroid Build Coastguard Worker };
1072