2 * Copyright © 2015 Broadcom
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include "compiler/v3d_compiler.h"
25 #include "compiler/nir/nir_builder.h"
28 * Walks the NIR generated by TGSI-to-NIR or GLSL-to-NIR to lower its io
29 * intrinsics into something amenable to the V3D architecture.
31 * Most of the work is turning the VS's store_output intrinsics from working
32 * on a base representing the gallium-level vec4 driver_location to an offset
33 * within the VPM, and emitting the header that's read by the fixed function
34 * hardware between the VS and FS.
36 * We also adjust the offsets on uniform loads to be in bytes, since that's
37 * what we need for indirect addressing with general TMU access.
40 struct v3d_nir_lower_io_state
{
44 int rcp_wc_vpm_offset
;
46 int varyings_vpm_offset
;
48 /* Geometry shader state */
50 /* VPM offset for the current vertex data output */
51 nir_variable
*output_offset_var
;
52 /* VPM offset for the current vertex header */
53 nir_variable
*header_offset_var
;
54 /* VPM header for the current vertex */
55 nir_variable
*header_var
;
57 /* Size of the complete VPM output header */
58 uint32_t output_header_size
;
59 /* Size of the output data for a single vertex */
60 uint32_t output_vertex_data_size
;
63 BITSET_WORD varyings_stored
[BITSET_WORDS(V3D_MAX_ANY_STAGE_INPUTS
)];
69 v3d_nir_emit_ff_vpm_outputs(struct v3d_compile
*c
, nir_builder
*b
,
70 struct v3d_nir_lower_io_state
*state
);
73 v3d_nir_store_output(nir_builder
*b
, int base
, nir_ssa_def
*offset
,
76 nir_intrinsic_instr
*intr
=
77 nir_intrinsic_instr_create(b
->shader
,
78 nir_intrinsic_store_output
);
79 nir_ssa_dest_init(&intr
->instr
, &intr
->dest
,
80 1, intr
->dest
.ssa
.bit_size
, NULL
);
81 intr
->num_components
= 1;
83 intr
->src
[0] = nir_src_for_ssa(chan
);
85 /* When generating the VIR instruction, the base and the offset
86 * are just going to get added together with an ADD instruction
87 * so we might as well do the add here at the NIR level instead
88 * and let the constant folding do its magic.
90 intr
->src
[1] = nir_src_for_ssa(nir_iadd_imm(b
, offset
, base
));
93 intr
->src
[1] = nir_src_for_ssa(nir_imm_int(b
, 0));
96 nir_intrinsic_set_base(intr
, base
);
97 nir_intrinsic_set_write_mask(intr
, 0x1);
98 nir_intrinsic_set_component(intr
, 0);
100 nir_builder_instr_insert(b
, &intr
->instr
);
103 /* Convert the uniform offset to bytes. If it happens to be a constant,
104 * constant-folding will clean up the shift for us.
107 v3d_nir_lower_uniform(struct v3d_compile
*c
, nir_builder
*b
,
108 nir_intrinsic_instr
*intr
)
110 b
->cursor
= nir_before_instr(&intr
->instr
);
112 nir_intrinsic_set_base(intr
, nir_intrinsic_base(intr
) * 16);
114 nir_instr_rewrite_src(&intr
->instr
,
116 nir_src_for_ssa(nir_ishl(b
, intr
->src
[0].ssa
,
117 nir_imm_int(b
, 4))));
121 v3d_varying_slot_vpm_offset(struct v3d_compile
*c
, nir_variable
*var
, int chan
)
123 int component
= var
->data
.location_frac
+ chan
;
125 uint32_t num_used_outputs
= 0;
126 struct v3d_varying_slot
*used_outputs
= NULL
;
127 switch (c
->s
->info
.stage
) {
128 case MESA_SHADER_VERTEX
:
129 num_used_outputs
= c
->vs_key
->num_used_outputs
;
130 used_outputs
= c
->vs_key
->used_outputs
;
132 case MESA_SHADER_GEOMETRY
:
133 num_used_outputs
= c
->gs_key
->num_used_outputs
;
134 used_outputs
= c
->gs_key
->used_outputs
;
137 unreachable("Unsupported shader stage");
140 for (int i
= 0; i
< num_used_outputs
; i
++) {
141 struct v3d_varying_slot slot
= used_outputs
[i
];
143 if (v3d_slot_get_slot(slot
) == var
->data
.location
&&
144 v3d_slot_get_component(slot
) == component
) {
152 /* Lowers a store_output(gallium driver location) to a series of store_outputs
153 * with a driver_location equal to the offset in the VPM.
155 * For geometry shaders we need to emit multiple vertices so the VPM offsets
156 * need to be computed in the shader code based on the current vertex index.
159 v3d_nir_lower_vpm_output(struct v3d_compile
*c
, nir_builder
*b
,
160 nir_intrinsic_instr
*intr
,
161 struct v3d_nir_lower_io_state
*state
)
163 b
->cursor
= nir_before_instr(&intr
->instr
);
165 /* If this is a geometry shader we need to emit our outputs
166 * to the current vertex offset in the VPM.
168 nir_ssa_def
*offset_reg
=
169 c
->s
->info
.stage
== MESA_SHADER_GEOMETRY
?
170 nir_load_var(b
, state
->gs
.output_offset_var
) : NULL
;
172 int start_comp
= nir_intrinsic_component(intr
);
173 nir_ssa_def
*src
= nir_ssa_for_src(b
, intr
->src
[0],
174 intr
->num_components
);
175 nir_variable
*var
= NULL
;
176 nir_foreach_shader_out_variable(scan_var
, c
->s
) {
177 int components
= scan_var
->data
.compact
?
178 glsl_get_length(scan_var
->type
) :
179 glsl_get_components(scan_var
->type
);
180 if (scan_var
->data
.driver_location
!= nir_intrinsic_base(intr
) ||
181 start_comp
< scan_var
->data
.location_frac
||
182 start_comp
>= scan_var
->data
.location_frac
+ components
) {
189 /* Save off the components of the position for the setup of VPM inputs
190 * read by fixed function HW.
192 if (var
->data
.location
== VARYING_SLOT_POS
) {
193 for (int i
= 0; i
< intr
->num_components
; i
++) {
194 state
->pos
[start_comp
+ i
] = nir_channel(b
, src
, i
);
198 /* Just psiz to the position in the FF header right now. */
199 if (var
->data
.location
== VARYING_SLOT_PSIZ
&&
200 state
->psiz_vpm_offset
!= -1) {
201 v3d_nir_store_output(b
, state
->psiz_vpm_offset
, offset_reg
, src
);
204 if (var
->data
.location
== VARYING_SLOT_LAYER
) {
205 assert(c
->s
->info
.stage
== MESA_SHADER_GEOMETRY
);
206 nir_ssa_def
*header
= nir_load_var(b
, state
->gs
.header_var
);
207 header
= nir_iand(b
, header
, nir_imm_int(b
, 0xff00ffff));
209 /* From the GLES 3.2 spec:
211 * "When fragments are written to a layered framebuffer, the
212 * fragment’s layer number selects an image from the array
213 * of images at each attachment (...). If the fragment’s
214 * layer number is negative, or greater than or equal to
215 * the minimum number of layers of any attachment, the
216 * effects of the fragment on the framebuffer contents are
219 * This suggests we can just ignore that situation, however,
220 * for V3D an out-of-bounds layer index means that the binner
221 * might do out-of-bounds writes access to the tile state. The
222 * simulator has an assert to catch this, so we play safe here
223 * and we make sure that doesn't happen by setting gl_Layer
224 * to 0 in that case (we always allocate tile state for at
227 nir_intrinsic_instr
*load
=
228 nir_intrinsic_instr_create(b
->shader
,
229 nir_intrinsic_load_fb_layers_v3d
);
230 nir_ssa_dest_init(&load
->instr
, &load
->dest
, 1, 32, NULL
);
231 nir_builder_instr_insert(b
, &load
->instr
);
232 nir_ssa_def
*fb_layers
= &load
->dest
.ssa
;
234 nir_ssa_def
*cond
= nir_ige(b
, src
, fb_layers
);
235 nir_ssa_def
*layer_id
=
238 nir_ishl(b
, src
, nir_imm_int(b
, 16)));
239 header
= nir_ior(b
, header
, layer_id
);
240 nir_store_var(b
, state
->gs
.header_var
, header
, 0x1);
243 /* Scalarize outputs if it hasn't happened already, since we want to
244 * schedule each VPM write individually. We can skip any outut
245 * components not read by the FS.
247 for (int i
= 0; i
< intr
->num_components
; i
++) {
249 v3d_varying_slot_vpm_offset(c
, var
,
252 var
->data
.location_frac
);
254 if (vpm_offset
== -1)
257 if (var
->data
.compact
)
258 vpm_offset
+= nir_src_as_uint(intr
->src
[1]) * 4;
260 BITSET_SET(state
->varyings_stored
, vpm_offset
);
262 v3d_nir_store_output(b
, state
->varyings_vpm_offset
+ vpm_offset
,
263 offset_reg
, nir_channel(b
, src
, i
));
266 nir_instr_remove(&intr
->instr
);
270 reset_gs_header(nir_builder
*b
, struct v3d_nir_lower_io_state
*state
)
272 const uint8_t NEW_PRIMITIVE_OFFSET
= 0;
273 const uint8_t VERTEX_DATA_LENGTH_OFFSET
= 8;
275 uint32_t vertex_data_size
= state
->gs
.output_vertex_data_size
;
276 assert((vertex_data_size
& 0xffffff00) == 0);
279 header
= 1 << NEW_PRIMITIVE_OFFSET
;
280 header
|= vertex_data_size
<< VERTEX_DATA_LENGTH_OFFSET
;
281 nir_store_var(b
, state
->gs
.header_var
, nir_imm_int(b
, header
), 0x1);
285 v3d_nir_lower_emit_vertex(struct v3d_compile
*c
, nir_builder
*b
,
286 nir_intrinsic_instr
*instr
,
287 struct v3d_nir_lower_io_state
*state
)
289 b
->cursor
= nir_before_instr(&instr
->instr
);
291 nir_ssa_def
*header
= nir_load_var(b
, state
->gs
.header_var
);
292 nir_ssa_def
*header_offset
= nir_load_var(b
, state
->gs
.header_offset_var
);
293 nir_ssa_def
*output_offset
= nir_load_var(b
, state
->gs
.output_offset_var
);
295 /* Emit fixed function outputs */
296 v3d_nir_emit_ff_vpm_outputs(c
, b
, state
);
298 /* Emit vertex header */
299 v3d_nir_store_output(b
, 0, header_offset
, header
);
301 /* Update VPM offset for next vertex output data and header */
303 nir_iadd(b
, output_offset
,
304 nir_imm_int(b
, state
->gs
.output_vertex_data_size
));
306 header_offset
= nir_iadd(b
, header_offset
, nir_imm_int(b
, 1));
308 /* Reset the New Primitive bit */
309 header
= nir_iand(b
, header
, nir_imm_int(b
, 0xfffffffe));
311 nir_store_var(b
, state
->gs
.output_offset_var
, output_offset
, 0x1);
312 nir_store_var(b
, state
->gs
.header_offset_var
, header_offset
, 0x1);
313 nir_store_var(b
, state
->gs
.header_var
, header
, 0x1);
315 nir_instr_remove(&instr
->instr
);
319 v3d_nir_lower_end_primitive(struct v3d_compile
*c
, nir_builder
*b
,
320 nir_intrinsic_instr
*instr
,
321 struct v3d_nir_lower_io_state
*state
)
323 assert(state
->gs
.header_var
);
324 b
->cursor
= nir_before_instr(&instr
->instr
);
325 reset_gs_header(b
, state
);
327 nir_instr_remove(&instr
->instr
);
331 v3d_nir_lower_io_instr(struct v3d_compile
*c
, nir_builder
*b
,
332 struct nir_instr
*instr
,
333 struct v3d_nir_lower_io_state
*state
)
335 if (instr
->type
!= nir_instr_type_intrinsic
)
337 nir_intrinsic_instr
*intr
= nir_instr_as_intrinsic(instr
);
339 switch (intr
->intrinsic
) {
340 case nir_intrinsic_load_uniform
:
341 v3d_nir_lower_uniform(c
, b
, intr
);
344 case nir_intrinsic_store_output
:
345 if (c
->s
->info
.stage
== MESA_SHADER_VERTEX
||
346 c
->s
->info
.stage
== MESA_SHADER_GEOMETRY
) {
347 v3d_nir_lower_vpm_output(c
, b
, intr
, state
);
351 case nir_intrinsic_emit_vertex
:
352 v3d_nir_lower_emit_vertex(c
, b
, intr
, state
);
355 case nir_intrinsic_end_primitive
:
356 v3d_nir_lower_end_primitive(c
, b
, intr
, state
);
364 /* Remap the output var's .driver_location. This is purely for
365 * nir_print_shader() so that store_output can map back to a variable name.
368 v3d_nir_lower_io_update_output_var_base(struct v3d_compile
*c
,
369 struct v3d_nir_lower_io_state
*state
)
371 nir_foreach_shader_out_variable_safe(var
, c
->s
) {
372 if (var
->data
.location
== VARYING_SLOT_POS
&&
373 state
->pos_vpm_offset
!= -1) {
374 var
->data
.driver_location
= state
->pos_vpm_offset
;
378 if (var
->data
.location
== VARYING_SLOT_PSIZ
&&
379 state
->psiz_vpm_offset
!= -1) {
380 var
->data
.driver_location
= state
->psiz_vpm_offset
;
384 int vpm_offset
= v3d_varying_slot_vpm_offset(c
, var
, 0);
385 if (vpm_offset
!= -1) {
386 var
->data
.driver_location
=
387 state
->varyings_vpm_offset
+ vpm_offset
;
389 /* If we couldn't find a mapping for the var, delete
390 * it so that its old .driver_location doesn't confuse
391 * nir_print_shader().
393 exec_node_remove(&var
->node
);
399 v3d_nir_setup_vpm_layout_vs(struct v3d_compile
*c
,
400 struct v3d_nir_lower_io_state
*state
)
402 uint32_t vpm_offset
= 0;
404 state
->pos_vpm_offset
= -1;
405 state
->vp_vpm_offset
= -1;
406 state
->zs_vpm_offset
= -1;
407 state
->rcp_wc_vpm_offset
= -1;
408 state
->psiz_vpm_offset
= -1;
410 bool needs_ff_outputs
= c
->vs_key
->base
.is_last_geometry_stage
;
411 if (needs_ff_outputs
) {
412 if (c
->vs_key
->is_coord
) {
413 state
->pos_vpm_offset
= vpm_offset
;
417 state
->vp_vpm_offset
= vpm_offset
;
420 if (!c
->vs_key
->is_coord
) {
421 state
->zs_vpm_offset
= vpm_offset
++;
422 state
->rcp_wc_vpm_offset
= vpm_offset
++;
425 if (c
->vs_key
->per_vertex_point_size
)
426 state
->psiz_vpm_offset
= vpm_offset
++;
429 state
->varyings_vpm_offset
= vpm_offset
;
431 c
->vpm_output_size
= MAX2(1, vpm_offset
+ c
->vs_key
->num_used_outputs
);
435 v3d_nir_setup_vpm_layout_gs(struct v3d_compile
*c
,
436 struct v3d_nir_lower_io_state
*state
)
438 /* 1 header slot for number of output vertices */
439 uint32_t vpm_offset
= 1;
441 /* 1 header slot per output vertex */
442 const uint32_t num_vertices
= c
->s
->info
.gs
.vertices_out
;
443 vpm_offset
+= num_vertices
;
445 state
->gs
.output_header_size
= vpm_offset
;
447 /* Vertex data: here we only compute offsets into a generic vertex data
448 * elements. When it is time to actually write a particular vertex to
449 * the VPM, we will add the offset for that vertex into the VPM output
452 * If geometry shaders are present, they are always the last shader
453 * stage before rasterization, so we always emit fixed function outputs.
456 if (c
->gs_key
->is_coord
) {
457 state
->pos_vpm_offset
= vpm_offset
;
460 state
->pos_vpm_offset
= -1;
463 state
->vp_vpm_offset
= vpm_offset
;
466 if (!c
->gs_key
->is_coord
) {
467 state
->zs_vpm_offset
= vpm_offset
++;
468 state
->rcp_wc_vpm_offset
= vpm_offset
++;
470 state
->zs_vpm_offset
= -1;
471 state
->rcp_wc_vpm_offset
= -1;
474 /* Mesa enables OES_geometry_shader_point_size automatically with
475 * OES_geometry_shader so we always need to handle point size
478 if (c
->gs_key
->per_vertex_point_size
)
479 state
->psiz_vpm_offset
= vpm_offset
++;
481 state
->varyings_vpm_offset
= vpm_offset
;
483 state
->gs
.output_vertex_data_size
=
484 state
->varyings_vpm_offset
+ c
->gs_key
->num_used_outputs
;
487 state
->gs
.output_header_size
+
488 state
->gs
.output_vertex_data_size
* num_vertices
;
492 v3d_nir_emit_ff_vpm_outputs(struct v3d_compile
*c
, nir_builder
*b
,
493 struct v3d_nir_lower_io_state
*state
)
495 /* If this is a geometry shader we need to emit our fixed function
496 * outputs to the current vertex offset in the VPM.
498 nir_ssa_def
*offset_reg
=
499 c
->s
->info
.stage
== MESA_SHADER_GEOMETRY
?
500 nir_load_var(b
, state
->gs
.output_offset_var
) : NULL
;
502 for (int i
= 0; i
< 4; i
++) {
504 state
->pos
[i
] = nir_ssa_undef(b
, 1, 32);
507 nir_ssa_def
*rcp_wc
= nir_frcp(b
, state
->pos
[3]);
509 if (state
->pos_vpm_offset
!= -1) {
510 for (int i
= 0; i
< 4; i
++) {
511 v3d_nir_store_output(b
, state
->pos_vpm_offset
+ i
,
512 offset_reg
, state
->pos
[i
]);
516 if (state
->vp_vpm_offset
!= -1) {
517 for (int i
= 0; i
< 2; i
++) {
522 scale
= nir_load_viewport_x_scale(b
);
524 scale
= nir_load_viewport_y_scale(b
);
525 pos
= nir_fmul(b
, pos
, scale
);
526 pos
= nir_fmul(b
, pos
, rcp_wc
);
527 pos
= nir_f2i32(b
, nir_fround_even(b
, pos
));
528 v3d_nir_store_output(b
, state
->vp_vpm_offset
+ i
,
533 if (state
->zs_vpm_offset
!= -1) {
534 nir_ssa_def
*z
= state
->pos
[2];
535 z
= nir_fmul(b
, z
, nir_load_viewport_z_scale(b
));
536 z
= nir_fmul(b
, z
, rcp_wc
);
537 z
= nir_fadd(b
, z
, nir_load_viewport_z_offset(b
));
538 v3d_nir_store_output(b
, state
->zs_vpm_offset
, offset_reg
, z
);
541 if (state
->rcp_wc_vpm_offset
!= -1) {
542 v3d_nir_store_output(b
, state
->rcp_wc_vpm_offset
,
546 /* Store 0 to varyings requested by the FS but not stored by the
547 * previous stage. This should be undefined behavior, but
548 * glsl-routing seems to rely on it.
550 uint32_t num_used_outputs
;
551 switch (c
->s
->info
.stage
) {
552 case MESA_SHADER_VERTEX
:
553 num_used_outputs
= c
->vs_key
->num_used_outputs
;
555 case MESA_SHADER_GEOMETRY
:
556 num_used_outputs
= c
->gs_key
->num_used_outputs
;
559 unreachable("Unsupported shader stage");
562 for (int i
= 0; i
< num_used_outputs
; i
++) {
563 if (!BITSET_TEST(state
->varyings_stored
, i
)) {
564 v3d_nir_store_output(b
, state
->varyings_vpm_offset
+ i
,
565 offset_reg
, nir_imm_int(b
, 0));
571 emit_gs_prolog(struct v3d_compile
*c
, nir_builder
*b
,
572 nir_function_impl
*impl
,
573 struct v3d_nir_lower_io_state
*state
)
575 nir_block
*first
= nir_start_block(impl
);
576 b
->cursor
= nir_before_block(first
);
578 const struct glsl_type
*uint_type
= glsl_uint_type();
580 assert(!state
->gs
.output_offset_var
);
581 state
->gs
.output_offset_var
=
582 nir_local_variable_create(impl
, uint_type
, "output_offset");
583 nir_store_var(b
, state
->gs
.output_offset_var
,
584 nir_imm_int(b
, state
->gs
.output_header_size
), 0x1);
586 assert(!state
->gs
.header_offset_var
);
587 state
->gs
.header_offset_var
=
588 nir_local_variable_create(impl
, uint_type
, "header_offset");
589 nir_store_var(b
, state
->gs
.header_offset_var
, nir_imm_int(b
, 1), 0x1);
591 assert(!state
->gs
.header_var
);
592 state
->gs
.header_var
=
593 nir_local_variable_create(impl
, uint_type
, "header");
594 reset_gs_header(b
, state
);
598 emit_gs_vpm_output_header_prolog(struct v3d_compile
*c
, nir_builder
*b
,
599 struct v3d_nir_lower_io_state
*state
)
601 const uint8_t VERTEX_COUNT_OFFSET
= 16;
603 /* Our GS header has 1 generic header slot (at VPM offset 0) and then
604 * one slot per output vertex after it. This means we don't need to
605 * have a variable just to keep track of the number of vertices we
606 * emitted and instead we can just compute it here from the header
607 * offset variable by removing the one generic header slot that always
608 * goes at the begining of out header.
610 nir_ssa_def
*header_offset
=
611 nir_load_var(b
, state
->gs
.header_offset_var
);
612 nir_ssa_def
*vertex_count
=
613 nir_isub(b
, header_offset
, nir_imm_int(b
, 1));
614 nir_ssa_def
*header
=
615 nir_ior(b
, nir_imm_int(b
, state
->gs
.output_header_size
),
616 nir_ishl(b
, vertex_count
,
617 nir_imm_int(b
, VERTEX_COUNT_OFFSET
)));
619 v3d_nir_store_output(b
, 0, NULL
, header
);
623 v3d_nir_lower_io(nir_shader
*s
, struct v3d_compile
*c
)
625 struct v3d_nir_lower_io_state state
= { 0 };
627 /* Set up the layout of the VPM outputs. */
628 switch (s
->info
.stage
) {
629 case MESA_SHADER_VERTEX
:
630 v3d_nir_setup_vpm_layout_vs(c
, &state
);
632 case MESA_SHADER_GEOMETRY
:
633 v3d_nir_setup_vpm_layout_gs(c
, &state
);
635 case MESA_SHADER_FRAGMENT
:
636 case MESA_SHADER_COMPUTE
:
639 unreachable("Unsupported shader stage");
642 nir_foreach_function(function
, s
) {
643 if (function
->impl
) {
645 nir_builder_init(&b
, function
->impl
);
647 if (c
->s
->info
.stage
== MESA_SHADER_GEOMETRY
)
648 emit_gs_prolog(c
, &b
, function
->impl
, &state
);
650 nir_foreach_block(block
, function
->impl
) {
651 nir_foreach_instr_safe(instr
, block
)
652 v3d_nir_lower_io_instr(c
, &b
, instr
,
656 nir_block
*last
= nir_impl_last_block(function
->impl
);
657 b
.cursor
= nir_after_block(last
);
658 if (s
->info
.stage
== MESA_SHADER_VERTEX
) {
659 v3d_nir_emit_ff_vpm_outputs(c
, &b
, &state
);
660 } else if (s
->info
.stage
== MESA_SHADER_GEOMETRY
) {
661 emit_gs_vpm_output_header_prolog(c
, &b
, &state
);
664 nir_metadata_preserve(function
->impl
,
665 nir_metadata_block_index
|
666 nir_metadata_dominance
);
670 if (s
->info
.stage
== MESA_SHADER_VERTEX
||
671 s
->info
.stage
== MESA_SHADER_GEOMETRY
) {
672 v3d_nir_lower_io_update_output_var_base(c
, &state
);