2 * Copyright © 2016-2017 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 "broadcom/common/v3d_device_info.h"
25 #include "v3d_compiler.h"
28 vir_get_non_sideband_nsrc(struct qinst
*inst
)
30 switch (inst
->qpu
.type
) {
31 case V3D_QPU_INSTR_TYPE_BRANCH
:
33 case V3D_QPU_INSTR_TYPE_ALU
:
34 if (inst
->qpu
.alu
.add
.op
!= V3D_QPU_A_NOP
)
35 return v3d_qpu_add_op_num_src(inst
->qpu
.alu
.add
.op
);
37 return v3d_qpu_mul_op_num_src(inst
->qpu
.alu
.mul
.op
);
44 vir_get_nsrc(struct qinst
*inst
)
46 int nsrc
= vir_get_non_sideband_nsrc(inst
);
48 if (vir_has_implicit_uniform(inst
))
55 vir_has_implicit_uniform(struct qinst
*inst
)
57 switch (inst
->qpu
.type
) {
58 case V3D_QPU_INSTR_TYPE_BRANCH
:
60 case V3D_QPU_INSTR_TYPE_ALU
:
61 switch (inst
->dst
.file
) {
65 return inst
->has_implicit_uniform
;
71 /* The sideband uniform for textures gets stored after the normal ALU
75 vir_get_implicit_uniform_src(struct qinst
*inst
)
77 return vir_get_nsrc(inst
) - 1;
81 * Returns whether the instruction has any side effects that must be
85 vir_has_side_effects(struct v3d_compile
*c
, struct qinst
*inst
)
87 switch (inst
->qpu
.type
) {
88 case V3D_QPU_INSTR_TYPE_BRANCH
:
90 case V3D_QPU_INSTR_TYPE_ALU
:
91 switch (inst
->qpu
.alu
.add
.op
) {
92 case V3D_QPU_A_SETREVF
:
93 case V3D_QPU_A_SETMSF
:
94 case V3D_QPU_A_VPMSETUP
:
95 case V3D_QPU_A_STVPMV
:
96 case V3D_QPU_A_STVPMD
:
97 case V3D_QPU_A_STVPMP
:
104 switch (inst
->qpu
.alu
.mul
.op
) {
105 case V3D_QPU_M_MULTOP
:
112 if (inst
->qpu
.sig
.ldtmu
||
113 inst
->qpu
.sig
.ldvary
||
114 inst
->qpu
.sig
.wrtmuc
||
115 inst
->qpu
.sig
.thrsw
) {
123 vir_is_float_input(struct qinst
*inst
)
125 /* XXX: More instrs */
126 switch (inst
->qpu
.type
) {
127 case V3D_QPU_INSTR_TYPE_BRANCH
:
129 case V3D_QPU_INSTR_TYPE_ALU
:
130 switch (inst
->qpu
.alu
.add
.op
) {
135 case V3D_QPU_A_FTOIN
:
141 switch (inst
->qpu
.alu
.mul
.op
) {
143 case V3D_QPU_M_VFMUL
:
155 vir_is_raw_mov(struct qinst
*inst
)
157 if (inst
->qpu
.type
!= V3D_QPU_INSTR_TYPE_ALU
||
158 (inst
->qpu
.alu
.mul
.op
!= V3D_QPU_M_FMOV
&&
159 inst
->qpu
.alu
.mul
.op
!= V3D_QPU_M_MOV
)) {
163 if (inst
->qpu
.alu
.add
.output_pack
!= V3D_QPU_PACK_NONE
||
164 inst
->qpu
.alu
.mul
.output_pack
!= V3D_QPU_PACK_NONE
) {
168 if (inst
->qpu
.flags
.ac
!= V3D_QPU_COND_NONE
||
169 inst
->qpu
.flags
.mc
!= V3D_QPU_COND_NONE
)
176 vir_is_add(struct qinst
*inst
)
178 return (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_ALU
&&
179 inst
->qpu
.alu
.add
.op
!= V3D_QPU_A_NOP
);
183 vir_is_mul(struct qinst
*inst
)
185 return (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_ALU
&&
186 inst
->qpu
.alu
.mul
.op
!= V3D_QPU_M_NOP
);
190 vir_is_tex(struct qinst
*inst
)
192 if (inst
->dst
.file
== QFILE_MAGIC
)
193 return v3d_qpu_magic_waddr_is_tmu(inst
->dst
.index
);
199 vir_depends_on_flags(struct qinst
*inst
)
201 if (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_BRANCH
) {
202 return (inst
->qpu
.branch
.cond
!= V3D_QPU_BRANCH_COND_ALWAYS
);
204 return (inst
->qpu
.flags
.ac
!= V3D_QPU_COND_NONE
&&
205 inst
->qpu
.flags
.mc
!= V3D_QPU_COND_NONE
);
210 vir_writes_r3(const struct v3d_device_info
*devinfo
, struct qinst
*inst
)
212 for (int i
= 0; i
< vir_get_nsrc(inst
); i
++) {
213 switch (inst
->src
[i
].file
) {
221 if (devinfo
->ver
< 41 && (inst
->qpu
.sig
.ldvary
||
222 inst
->qpu
.sig
.ldtlb
||
223 inst
->qpu
.sig
.ldtlbu
||
224 inst
->qpu
.sig
.ldvpm
)) {
232 vir_writes_r4(const struct v3d_device_info
*devinfo
, struct qinst
*inst
)
234 switch (inst
->dst
.file
) {
236 switch (inst
->dst
.index
) {
237 case V3D_QPU_WADDR_RECIP
:
238 case V3D_QPU_WADDR_RSQRT
:
239 case V3D_QPU_WADDR_EXP
:
240 case V3D_QPU_WADDR_LOG
:
241 case V3D_QPU_WADDR_SIN
:
249 if (devinfo
->ver
< 41 && inst
->qpu
.sig
.ldtmu
)
256 vir_set_unpack(struct qinst
*inst
, int src
,
257 enum v3d_qpu_input_unpack unpack
)
259 assert(src
== 0 || src
== 1);
261 if (vir_is_add(inst
)) {
263 inst
->qpu
.alu
.add
.a_unpack
= unpack
;
265 inst
->qpu
.alu
.add
.b_unpack
= unpack
;
267 assert(vir_is_mul(inst
));
269 inst
->qpu
.alu
.mul
.a_unpack
= unpack
;
271 inst
->qpu
.alu
.mul
.b_unpack
= unpack
;
276 vir_set_cond(struct qinst
*inst
, enum v3d_qpu_cond cond
)
278 if (vir_is_add(inst
)) {
279 inst
->qpu
.flags
.ac
= cond
;
281 assert(vir_is_mul(inst
));
282 inst
->qpu
.flags
.mc
= cond
;
287 vir_set_pf(struct qinst
*inst
, enum v3d_qpu_pf pf
)
289 if (vir_is_add(inst
)) {
290 inst
->qpu
.flags
.apf
= pf
;
292 assert(vir_is_mul(inst
));
293 inst
->qpu
.flags
.mpf
= pf
;
299 vir_channels_written(struct qinst
*inst
)
301 if (vir_is_mul(inst
)) {
302 switch (inst
->dst
.pack
) {
303 case QPU_PACK_MUL_NOP
:
304 case QPU_PACK_MUL_8888
:
306 case QPU_PACK_MUL_8A
:
308 case QPU_PACK_MUL_8B
:
310 case QPU_PACK_MUL_8C
:
312 case QPU_PACK_MUL_8D
:
316 switch (inst
->dst
.pack
) {
318 case QPU_PACK_A_8888
:
319 case QPU_PACK_A_8888_SAT
:
320 case QPU_PACK_A_32_SAT
:
323 case QPU_PACK_A_8A_SAT
:
326 case QPU_PACK_A_8B_SAT
:
329 case QPU_PACK_A_8C_SAT
:
332 case QPU_PACK_A_8D_SAT
:
335 case QPU_PACK_A_16A_SAT
:
338 case QPU_PACK_A_16B_SAT
:
342 unreachable("Bad pack field");
347 vir_get_temp(struct v3d_compile
*c
)
351 reg
.file
= QFILE_TEMP
;
352 reg
.index
= c
->num_temps
++;
354 if (c
->num_temps
> c
->defs_array_size
) {
355 uint32_t old_size
= c
->defs_array_size
;
356 c
->defs_array_size
= MAX2(old_size
* 2, 16);
358 c
->defs
= reralloc(c
, c
->defs
, struct qinst
*,
360 memset(&c
->defs
[old_size
], 0,
361 sizeof(c
->defs
[0]) * (c
->defs_array_size
- old_size
));
363 c
->spillable
= reralloc(c
, c
->spillable
,
365 BITSET_WORDS(c
->defs_array_size
));
366 for (int i
= old_size
; i
< c
->defs_array_size
; i
++)
367 BITSET_SET(c
->spillable
, i
);
374 vir_add_inst(enum v3d_qpu_add_op op
, struct qreg dst
, struct qreg src0
, struct qreg src1
)
376 struct qinst
*inst
= calloc(1, sizeof(*inst
));
378 inst
->qpu
= v3d_qpu_nop();
379 inst
->qpu
.alu
.add
.op
= op
;
390 vir_mul_inst(enum v3d_qpu_mul_op op
, struct qreg dst
, struct qreg src0
, struct qreg src1
)
392 struct qinst
*inst
= calloc(1, sizeof(*inst
));
394 inst
->qpu
= v3d_qpu_nop();
395 inst
->qpu
.alu
.mul
.op
= op
;
406 vir_branch_inst(enum v3d_qpu_branch_cond cond
, struct qreg src
)
408 struct qinst
*inst
= calloc(1, sizeof(*inst
));
410 inst
->qpu
= v3d_qpu_nop();
411 inst
->qpu
.type
= V3D_QPU_INSTR_TYPE_BRANCH
;
412 inst
->qpu
.branch
.cond
= cond
;
413 inst
->qpu
.branch
.msfign
= V3D_QPU_MSFIGN_NONE
;
414 inst
->qpu
.branch
.bdi
= V3D_QPU_BRANCH_DEST_REL
;
415 inst
->qpu
.branch
.ub
= true;
416 inst
->qpu
.branch
.bdu
= V3D_QPU_BRANCH_DEST_REL
;
418 inst
->dst
= vir_reg(QFILE_NULL
, 0);
426 vir_emit(struct v3d_compile
*c
, struct qinst
*inst
)
428 switch (c
->cursor
.mode
) {
430 list_add(&inst
->link
, c
->cursor
.link
);
432 case vir_cursor_addtail
:
433 list_addtail(&inst
->link
, c
->cursor
.link
);
437 c
->cursor
= vir_after_inst(inst
);
438 c
->live_intervals_valid
= false;
441 /* Updates inst to write to a new temporary, emits it, and notes the def. */
443 vir_emit_def(struct v3d_compile
*c
, struct qinst
*inst
)
445 assert(inst
->dst
.file
== QFILE_NULL
);
447 inst
->dst
= vir_get_temp(c
);
449 if (inst
->dst
.file
== QFILE_TEMP
)
450 c
->defs
[inst
->dst
.index
] = inst
;
458 vir_emit_nondef(struct v3d_compile
*c
, struct qinst
*inst
)
460 if (inst
->dst
.file
== QFILE_TEMP
)
461 c
->defs
[inst
->dst
.index
] = NULL
;
469 vir_new_block(struct v3d_compile
*c
)
471 struct qblock
*block
= rzalloc(c
, struct qblock
);
473 list_inithead(&block
->instructions
);
475 block
->predecessors
= _mesa_set_create(block
,
477 _mesa_key_pointer_equal
);
479 block
->index
= c
->next_block_index
++;
485 vir_set_emit_block(struct v3d_compile
*c
, struct qblock
*block
)
487 c
->cur_block
= block
;
488 c
->cursor
= vir_after_block(block
);
489 list_addtail(&block
->link
, &c
->blocks
);
493 vir_entry_block(struct v3d_compile
*c
)
495 return list_first_entry(&c
->blocks
, struct qblock
, link
);
499 vir_exit_block(struct v3d_compile
*c
)
501 return list_last_entry(&c
->blocks
, struct qblock
, link
);
505 vir_link_blocks(struct qblock
*predecessor
, struct qblock
*successor
)
507 _mesa_set_add(successor
->predecessors
, predecessor
);
508 if (predecessor
->successors
[0]) {
509 assert(!predecessor
->successors
[1]);
510 predecessor
->successors
[1] = successor
;
512 predecessor
->successors
[0] = successor
;
516 const struct v3d_compiler
*
517 v3d_compiler_init(const struct v3d_device_info
*devinfo
)
519 struct v3d_compiler
*compiler
= rzalloc(NULL
, struct v3d_compiler
);
523 compiler
->devinfo
= devinfo
;
525 if (!vir_init_reg_sets(compiler
)) {
526 ralloc_free(compiler
);
534 v3d_compiler_free(const struct v3d_compiler
*compiler
)
536 ralloc_free((void *)compiler
);
539 static struct v3d_compile
*
540 vir_compile_init(const struct v3d_compiler
*compiler
,
543 int program_id
, int variant_id
)
545 struct v3d_compile
*c
= rzalloc(NULL
, struct v3d_compile
);
547 c
->compiler
= compiler
;
548 c
->devinfo
= compiler
->devinfo
;
550 c
->program_id
= program_id
;
551 c
->variant_id
= variant_id
;
554 s
= nir_shader_clone(c
, s
);
557 list_inithead(&c
->blocks
);
558 vir_set_emit_block(c
, vir_new_block(c
));
560 c
->output_position_index
= -1;
561 c
->output_point_size_index
= -1;
562 c
->output_sample_mask_index
= -1;
564 c
->def_ht
= _mesa_hash_table_create(c
, _mesa_hash_pointer
,
565 _mesa_key_pointer_equal
);
571 v3d_lower_nir(struct v3d_compile
*c
)
573 struct nir_lower_tex_options tex_options
= {
575 .lower_rect
= false, /* XXX: Use this on V3D 3.x */
577 /* Apply swizzles to all samplers. */
578 .swizzle_result
= ~0,
581 /* Lower the format swizzle and (for 32-bit returns)
582 * ARB_texture_swizzle-style swizzle.
584 for (int i
= 0; i
< ARRAY_SIZE(c
->key
->tex
); i
++) {
585 for (int j
= 0; j
< 4; j
++)
586 tex_options
.swizzles
[i
][j
] = c
->key
->tex
[i
].swizzle
[j
];
588 if (c
->key
->tex
[i
].clamp_s
)
589 tex_options
.saturate_s
|= 1 << i
;
590 if (c
->key
->tex
[i
].clamp_t
)
591 tex_options
.saturate_t
|= 1 << i
;
592 if (c
->key
->tex
[i
].clamp_r
)
593 tex_options
.saturate_r
|= 1 << i
;
596 NIR_PASS_V(c
->s
, nir_lower_tex
, &tex_options
);
600 v3d_lower_nir_late(struct v3d_compile
*c
)
602 NIR_PASS_V(c
->s
, v3d_nir_lower_io
, c
);
603 NIR_PASS_V(c
->s
, v3d_nir_lower_txf_ms
, c
);
604 NIR_PASS_V(c
->s
, nir_lower_idiv
);
608 v3d_set_prog_data_uniforms(struct v3d_compile
*c
,
609 struct v3d_prog_data
*prog_data
)
611 int count
= c
->num_uniforms
;
612 struct v3d_uniform_list
*ulist
= &prog_data
->uniforms
;
614 ulist
->count
= count
;
615 ulist
->data
= ralloc_array(prog_data
, uint32_t, count
);
616 memcpy(ulist
->data
, c
->uniform_data
,
617 count
* sizeof(*ulist
->data
));
618 ulist
->contents
= ralloc_array(prog_data
, enum quniform_contents
, count
);
619 memcpy(ulist
->contents
, c
->uniform_contents
,
620 count
* sizeof(*ulist
->contents
));
623 /* Copy the compiler UBO range state to the compiled shader, dropping out
624 * arrays that were never referenced by an indirect load.
626 * (Note that QIR dead code elimination of an array access still leaves that
627 * array alive, though)
630 v3d_set_prog_data_ubo(struct v3d_compile
*c
,
631 struct v3d_prog_data
*prog_data
)
633 if (!c
->num_ubo_ranges
)
636 prog_data
->num_ubo_ranges
= 0;
637 prog_data
->ubo_ranges
= ralloc_array(prog_data
, struct v3d_ubo_range
,
639 for (int i
= 0; i
< c
->num_ubo_ranges
; i
++) {
640 if (!c
->ubo_range_used
[i
])
643 struct v3d_ubo_range
*range
= &c
->ubo_ranges
[i
];
644 prog_data
->ubo_ranges
[prog_data
->num_ubo_ranges
++] = *range
;
645 prog_data
->ubo_size
+= range
->size
;
648 if (prog_data
->ubo_size
) {
649 if (V3D_DEBUG
& V3D_DEBUG_SHADERDB
) {
650 fprintf(stderr
, "SHADER-DB: %s prog %d/%d: %d UBO uniforms\n",
651 vir_get_stage_name(c
),
652 c
->program_id
, c
->variant_id
,
653 prog_data
->ubo_size
/ 4);
659 v3d_set_prog_data(struct v3d_compile
*c
,
660 struct v3d_prog_data
*prog_data
)
662 prog_data
->threads
= c
->threads
;
663 prog_data
->single_seg
= !c
->last_thrsw
;
664 prog_data
->spill_size
= c
->spill_size
;
666 v3d_set_prog_data_uniforms(c
, prog_data
);
667 v3d_set_prog_data_ubo(c
, prog_data
);
671 v3d_return_qpu_insts(struct v3d_compile
*c
, uint32_t *final_assembly_size
)
673 *final_assembly_size
= c
->qpu_inst_count
* sizeof(uint64_t);
675 uint64_t *qpu_insts
= malloc(*final_assembly_size
);
679 memcpy(qpu_insts
, c
->qpu_insts
, *final_assembly_size
);
681 vir_compile_destroy(c
);
686 uint64_t *v3d_compile_vs(const struct v3d_compiler
*compiler
,
687 struct v3d_vs_key
*key
,
688 struct v3d_vs_prog_data
*prog_data
,
690 int program_id
, int variant_id
,
691 uint32_t *final_assembly_size
)
693 struct v3d_compile
*c
= vir_compile_init(compiler
, &key
->base
, s
,
694 program_id
, variant_id
);
700 if (key
->clamp_color
)
701 NIR_PASS_V(c
->s
, nir_lower_clamp_color_outputs
);
703 if (key
->base
.ucp_enables
) {
704 NIR_PASS_V(c
->s
, nir_lower_clip_vs
, key
->base
.ucp_enables
);
705 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar
,
709 /* Note: VS output scalarizing must happen after nir_lower_clip_vs. */
710 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar
, nir_var_shader_out
);
712 v3d_lower_nir_late(c
);
713 v3d_optimize_nir(c
->s
);
714 NIR_PASS_V(c
->s
, nir_convert_from_ssa
, true);
718 v3d_set_prog_data(c
, &prog_data
->base
);
720 prog_data
->base
.num_inputs
= c
->num_inputs
;
722 /* The vertex data gets format converted by the VPM so that
723 * each attribute channel takes up a VPM column. Precompute
724 * the sizes for the shader record.
726 for (int i
= 0; i
< ARRAY_SIZE(prog_data
->vattr_sizes
); i
++) {
727 prog_data
->vattr_sizes
[i
] = c
->vattr_sizes
[i
];
728 prog_data
->vpm_input_size
+= c
->vattr_sizes
[i
];
731 prog_data
->uses_vid
= (s
->info
.system_values_read
&
732 (1ull << SYSTEM_VALUE_VERTEX_ID
));
733 prog_data
->uses_iid
= (s
->info
.system_values_read
&
734 (1ull << SYSTEM_VALUE_INSTANCE_ID
));
736 if (prog_data
->uses_vid
)
737 prog_data
->vpm_input_size
++;
738 if (prog_data
->uses_iid
)
739 prog_data
->vpm_input_size
++;
741 /* Input/output segment size are in 8x32-bit multiples. */
742 prog_data
->vpm_input_size
= align(prog_data
->vpm_input_size
, 8) / 8;
743 prog_data
->vpm_output_size
= align(c
->num_vpm_writes
, 8) / 8;
745 return v3d_return_qpu_insts(c
, final_assembly_size
);
749 v3d_set_fs_prog_data_inputs(struct v3d_compile
*c
,
750 struct v3d_fs_prog_data
*prog_data
)
752 prog_data
->base
.num_inputs
= c
->num_inputs
;
753 memcpy(prog_data
->input_slots
, c
->input_slots
,
754 c
->num_inputs
* sizeof(*c
->input_slots
));
756 STATIC_ASSERT(ARRAY_SIZE(prog_data
->flat_shade_flags
) >
757 (V3D_MAX_FS_INPUTS
- 1) / 24);
758 for (int i
= 0; i
< V3D_MAX_FS_INPUTS
; i
++) {
759 if (BITSET_TEST(c
->flat_shade_flags
, i
))
760 prog_data
->flat_shade_flags
[i
/ 24] |= 1 << (i
% 24);
762 if (BITSET_TEST(c
->noperspective_flags
, i
))
763 prog_data
->noperspective_flags
[i
/ 24] |= 1 << (i
% 24);
765 if (BITSET_TEST(c
->centroid_flags
, i
))
766 prog_data
->centroid_flags
[i
/ 24] |= 1 << (i
% 24);
771 v3d_fixup_fs_output_types(struct v3d_compile
*c
)
773 nir_foreach_variable(var
, &c
->s
->outputs
) {
776 switch (var
->data
.location
) {
777 case FRAG_RESULT_COLOR
:
780 case FRAG_RESULT_DATA0
:
781 case FRAG_RESULT_DATA1
:
782 case FRAG_RESULT_DATA2
:
783 case FRAG_RESULT_DATA3
:
784 mask
= 1 << (var
->data
.location
- FRAG_RESULT_DATA0
);
788 if (c
->fs_key
->int_color_rb
& mask
) {
790 glsl_vector_type(GLSL_TYPE_INT
,
791 glsl_get_components(var
->type
));
792 } else if (c
->fs_key
->uint_color_rb
& mask
) {
794 glsl_vector_type(GLSL_TYPE_UINT
,
795 glsl_get_components(var
->type
));
800 uint64_t *v3d_compile_fs(const struct v3d_compiler
*compiler
,
801 struct v3d_fs_key
*key
,
802 struct v3d_fs_prog_data
*prog_data
,
804 int program_id
, int variant_id
,
805 uint32_t *final_assembly_size
)
807 struct v3d_compile
*c
= vir_compile_init(compiler
, &key
->base
, s
,
808 program_id
, variant_id
);
812 if (key
->int_color_rb
|| key
->uint_color_rb
)
813 v3d_fixup_fs_output_types(c
);
817 if (key
->light_twoside
)
818 NIR_PASS_V(c
->s
, nir_lower_two_sided_color
);
820 if (key
->clamp_color
)
821 NIR_PASS_V(c
->s
, nir_lower_clamp_color_outputs
);
823 if (key
->alpha_test
) {
824 NIR_PASS_V(c
->s
, nir_lower_alpha_test
, key
->alpha_test_func
,
828 if (key
->base
.ucp_enables
)
829 NIR_PASS_V(c
->s
, nir_lower_clip_fs
, key
->base
.ucp_enables
);
831 /* Note: FS input scalarizing must happen after
832 * nir_lower_two_sided_color, which only handles a vec4 at a time.
834 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar
, nir_var_shader_in
);
836 v3d_lower_nir_late(c
);
837 v3d_optimize_nir(c
->s
);
838 NIR_PASS_V(c
->s
, nir_convert_from_ssa
, true);
842 v3d_set_prog_data(c
, &prog_data
->base
);
843 v3d_set_fs_prog_data_inputs(c
, prog_data
);
844 prog_data
->writes_z
= (c
->s
->info
.outputs_written
&
845 (1 << FRAG_RESULT_DEPTH
));
846 prog_data
->discard
= (c
->s
->info
.fs
.uses_discard
||
847 c
->fs_key
->sample_alpha_to_coverage
);
848 prog_data
->uses_center_w
= c
->uses_center_w
;
850 return v3d_return_qpu_insts(c
, final_assembly_size
);
854 vir_remove_instruction(struct v3d_compile
*c
, struct qinst
*qinst
)
856 if (qinst
->dst
.file
== QFILE_TEMP
)
857 c
->defs
[qinst
->dst
.index
] = NULL
;
859 assert(&qinst
->link
!= c
->cursor
.link
);
861 list_del(&qinst
->link
);
864 c
->live_intervals_valid
= false;
868 vir_follow_movs(struct v3d_compile
*c
, struct qreg reg
)
873 while (reg.file == QFILE_TEMP &&
874 c->defs[reg.index] &&
875 (c->defs[reg.index]->op == QOP_MOV ||
876 c->defs[reg.index]->op == QOP_FMOV) &&
877 !c->defs[reg.index]->dst.pack &&
878 !c->defs[reg.index]->src[0].pack) {
879 reg = c->defs[reg.index]->src[0];
888 vir_compile_destroy(struct v3d_compile
*c
)
890 /* Defuse the assert that we aren't removing the cursor's instruction.
892 c
->cursor
.link
= NULL
;
894 vir_for_each_block(block
, c
) {
895 while (!list_empty(&block
->instructions
)) {
896 struct qinst
*qinst
=
897 list_first_entry(&block
->instructions
,
899 vir_remove_instruction(c
, qinst
);
907 vir_uniform(struct v3d_compile
*c
,
908 enum quniform_contents contents
,
911 for (int i
= 0; i
< c
->num_uniforms
; i
++) {
912 if (c
->uniform_contents
[i
] == contents
&&
913 c
->uniform_data
[i
] == data
) {
914 return vir_reg(QFILE_UNIF
, i
);
918 uint32_t uniform
= c
->num_uniforms
++;
920 if (uniform
>= c
->uniform_array_size
) {
921 c
->uniform_array_size
= MAX2(MAX2(16, uniform
+ 1),
922 c
->uniform_array_size
* 2);
924 c
->uniform_data
= reralloc(c
, c
->uniform_data
,
926 c
->uniform_array_size
);
927 c
->uniform_contents
= reralloc(c
, c
->uniform_contents
,
928 enum quniform_contents
,
929 c
->uniform_array_size
);
932 c
->uniform_contents
[uniform
] = contents
;
933 c
->uniform_data
[uniform
] = data
;
935 return vir_reg(QFILE_UNIF
, uniform
);
939 vir_can_set_flags(struct v3d_compile
*c
, struct qinst
*inst
)
941 if (c
->devinfo
->ver
>= 40 && (v3d_qpu_reads_vpm(&inst
->qpu
) ||
942 v3d_qpu_uses_sfu(&inst
->qpu
))) {
950 vir_PF(struct v3d_compile
*c
, struct qreg src
, enum v3d_qpu_pf pf
)
952 struct qinst
*last_inst
= NULL
;
954 if (!list_empty(&c
->cur_block
->instructions
)) {
955 last_inst
= (struct qinst
*)c
->cur_block
->instructions
.prev
;
957 /* Can't stuff the PF into the last last inst if our cursor
958 * isn't pointing after it.
960 struct vir_cursor after_inst
= vir_after_inst(last_inst
);
961 if (c
->cursor
.mode
!= after_inst
.mode
||
962 c
->cursor
.link
!= after_inst
.link
)
966 if (src
.file
!= QFILE_TEMP
||
967 !c
->defs
[src
.index
] ||
968 last_inst
!= c
->defs
[src
.index
] ||
969 !vir_can_set_flags(c
, last_inst
)) {
970 /* XXX: Make the MOV be the appropriate type */
971 last_inst
= vir_MOV_dest(c
, vir_reg(QFILE_NULL
, 0), src
);
974 vir_set_pf(last_inst
, pf
);
977 #define OPTPASS(func) \
979 bool stage_progress = func(c); \
980 if (stage_progress) { \
982 if (print_opt_debug) { \
984 "VIR opt pass %2d: %s progress\n", \
987 /*XXX vir_validate(c);*/ \
992 vir_optimize(struct v3d_compile
*c
)
994 bool print_opt_debug
= false;
998 bool progress
= false;
1000 OPTPASS(vir_opt_copy_propagate
);
1001 OPTPASS(vir_opt_dead_code
);
1011 vir_get_stage_name(struct v3d_compile
*c
)
1013 if (c
->vs_key
&& c
->vs_key
->is_coord
)
1014 return "MESA_SHADER_COORD";
1016 return gl_shader_stage_name(c
->s
->info
.stage
);