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_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 * Returns whether the instruction has any side effects that must be
48 vir_has_side_effects(struct v3d_compile
*c
, struct qinst
*inst
)
50 switch (inst
->qpu
.type
) {
51 case V3D_QPU_INSTR_TYPE_BRANCH
:
53 case V3D_QPU_INSTR_TYPE_ALU
:
54 switch (inst
->qpu
.alu
.add
.op
) {
55 case V3D_QPU_A_SETREVF
:
56 case V3D_QPU_A_SETMSF
:
57 case V3D_QPU_A_VPMSETUP
:
58 case V3D_QPU_A_STVPMV
:
59 case V3D_QPU_A_STVPMD
:
60 case V3D_QPU_A_STVPMP
:
68 switch (inst
->qpu
.alu
.mul
.op
) {
69 case V3D_QPU_M_MULTOP
:
76 if (inst
->qpu
.sig
.ldtmu
||
77 inst
->qpu
.sig
.ldvary
||
78 inst
->qpu
.sig
.wrtmuc
||
79 inst
->qpu
.sig
.thrsw
) {
87 vir_is_raw_mov(struct qinst
*inst
)
89 if (inst
->qpu
.type
!= V3D_QPU_INSTR_TYPE_ALU
||
90 (inst
->qpu
.alu
.mul
.op
!= V3D_QPU_M_FMOV
&&
91 inst
->qpu
.alu
.mul
.op
!= V3D_QPU_M_MOV
)) {
95 if (inst
->qpu
.alu
.add
.output_pack
!= V3D_QPU_PACK_NONE
||
96 inst
->qpu
.alu
.mul
.output_pack
!= V3D_QPU_PACK_NONE
) {
100 if (inst
->qpu
.alu
.add
.a_unpack
!= V3D_QPU_UNPACK_NONE
||
101 inst
->qpu
.alu
.add
.b_unpack
!= V3D_QPU_UNPACK_NONE
||
102 inst
->qpu
.alu
.mul
.a_unpack
!= V3D_QPU_UNPACK_NONE
||
103 inst
->qpu
.alu
.mul
.b_unpack
!= V3D_QPU_UNPACK_NONE
) {
107 if (inst
->qpu
.flags
.ac
!= V3D_QPU_COND_NONE
||
108 inst
->qpu
.flags
.mc
!= V3D_QPU_COND_NONE
)
115 vir_is_add(struct qinst
*inst
)
117 return (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_ALU
&&
118 inst
->qpu
.alu
.add
.op
!= V3D_QPU_A_NOP
);
122 vir_is_mul(struct qinst
*inst
)
124 return (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_ALU
&&
125 inst
->qpu
.alu
.mul
.op
!= V3D_QPU_M_NOP
);
129 vir_is_tex(struct qinst
*inst
)
131 if (inst
->dst
.file
== QFILE_MAGIC
)
132 return v3d_qpu_magic_waddr_is_tmu(inst
->dst
.index
);
134 if (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_ALU
&&
135 inst
->qpu
.alu
.add
.op
== V3D_QPU_A_TMUWT
) {
143 vir_writes_r3(const struct v3d_device_info
*devinfo
, struct qinst
*inst
)
145 for (int i
= 0; i
< vir_get_nsrc(inst
); i
++) {
146 switch (inst
->src
[i
].file
) {
154 if (devinfo
->ver
< 41 && (inst
->qpu
.sig
.ldvary
||
155 inst
->qpu
.sig
.ldtlb
||
156 inst
->qpu
.sig
.ldtlbu
||
157 inst
->qpu
.sig
.ldvpm
)) {
165 vir_writes_r4(const struct v3d_device_info
*devinfo
, struct qinst
*inst
)
167 switch (inst
->dst
.file
) {
169 switch (inst
->dst
.index
) {
170 case V3D_QPU_WADDR_RECIP
:
171 case V3D_QPU_WADDR_RSQRT
:
172 case V3D_QPU_WADDR_EXP
:
173 case V3D_QPU_WADDR_LOG
:
174 case V3D_QPU_WADDR_SIN
:
182 if (devinfo
->ver
< 41 && inst
->qpu
.sig
.ldtmu
)
189 vir_set_unpack(struct qinst
*inst
, int src
,
190 enum v3d_qpu_input_unpack unpack
)
192 assert(src
== 0 || src
== 1);
194 if (vir_is_add(inst
)) {
196 inst
->qpu
.alu
.add
.a_unpack
= unpack
;
198 inst
->qpu
.alu
.add
.b_unpack
= unpack
;
200 assert(vir_is_mul(inst
));
202 inst
->qpu
.alu
.mul
.a_unpack
= unpack
;
204 inst
->qpu
.alu
.mul
.b_unpack
= unpack
;
209 vir_set_cond(struct qinst
*inst
, enum v3d_qpu_cond cond
)
211 if (vir_is_add(inst
)) {
212 inst
->qpu
.flags
.ac
= cond
;
214 assert(vir_is_mul(inst
));
215 inst
->qpu
.flags
.mc
= cond
;
220 vir_set_pf(struct qinst
*inst
, enum v3d_qpu_pf pf
)
222 if (vir_is_add(inst
)) {
223 inst
->qpu
.flags
.apf
= pf
;
225 assert(vir_is_mul(inst
));
226 inst
->qpu
.flags
.mpf
= pf
;
231 vir_set_uf(struct qinst
*inst
, enum v3d_qpu_uf uf
)
233 if (vir_is_add(inst
)) {
234 inst
->qpu
.flags
.auf
= uf
;
236 assert(vir_is_mul(inst
));
237 inst
->qpu
.flags
.muf
= uf
;
243 vir_channels_written(struct qinst
*inst
)
245 if (vir_is_mul(inst
)) {
246 switch (inst
->dst
.pack
) {
247 case QPU_PACK_MUL_NOP
:
248 case QPU_PACK_MUL_8888
:
250 case QPU_PACK_MUL_8A
:
252 case QPU_PACK_MUL_8B
:
254 case QPU_PACK_MUL_8C
:
256 case QPU_PACK_MUL_8D
:
260 switch (inst
->dst
.pack
) {
262 case QPU_PACK_A_8888
:
263 case QPU_PACK_A_8888_SAT
:
264 case QPU_PACK_A_32_SAT
:
267 case QPU_PACK_A_8A_SAT
:
270 case QPU_PACK_A_8B_SAT
:
273 case QPU_PACK_A_8C_SAT
:
276 case QPU_PACK_A_8D_SAT
:
279 case QPU_PACK_A_16A_SAT
:
282 case QPU_PACK_A_16B_SAT
:
286 unreachable("Bad pack field");
291 vir_get_temp(struct v3d_compile
*c
)
295 reg
.file
= QFILE_TEMP
;
296 reg
.index
= c
->num_temps
++;
298 if (c
->num_temps
> c
->defs_array_size
) {
299 uint32_t old_size
= c
->defs_array_size
;
300 c
->defs_array_size
= MAX2(old_size
* 2, 16);
302 c
->defs
= reralloc(c
, c
->defs
, struct qinst
*,
304 memset(&c
->defs
[old_size
], 0,
305 sizeof(c
->defs
[0]) * (c
->defs_array_size
- old_size
));
307 c
->spillable
= reralloc(c
, c
->spillable
,
309 BITSET_WORDS(c
->defs_array_size
));
310 for (int i
= old_size
; i
< c
->defs_array_size
; i
++)
311 BITSET_SET(c
->spillable
, i
);
318 vir_add_inst(enum v3d_qpu_add_op op
, struct qreg dst
, struct qreg src0
, struct qreg src1
)
320 struct qinst
*inst
= calloc(1, sizeof(*inst
));
322 inst
->qpu
= v3d_qpu_nop();
323 inst
->qpu
.alu
.add
.op
= op
;
334 vir_mul_inst(enum v3d_qpu_mul_op op
, struct qreg dst
, struct qreg src0
, struct qreg src1
)
336 struct qinst
*inst
= calloc(1, sizeof(*inst
));
338 inst
->qpu
= v3d_qpu_nop();
339 inst
->qpu
.alu
.mul
.op
= op
;
350 vir_branch_inst(struct v3d_compile
*c
, enum v3d_qpu_branch_cond cond
)
352 struct qinst
*inst
= calloc(1, sizeof(*inst
));
354 inst
->qpu
= v3d_qpu_nop();
355 inst
->qpu
.type
= V3D_QPU_INSTR_TYPE_BRANCH
;
356 inst
->qpu
.branch
.cond
= cond
;
357 inst
->qpu
.branch
.msfign
= V3D_QPU_MSFIGN_NONE
;
358 inst
->qpu
.branch
.bdi
= V3D_QPU_BRANCH_DEST_REL
;
359 inst
->qpu
.branch
.ub
= true;
360 inst
->qpu
.branch
.bdu
= V3D_QPU_BRANCH_DEST_REL
;
362 inst
->dst
= vir_nop_reg();
363 inst
->uniform
= vir_get_uniform_index(c
, QUNIFORM_CONSTANT
, 0);
369 vir_emit(struct v3d_compile
*c
, struct qinst
*inst
)
371 switch (c
->cursor
.mode
) {
373 list_add(&inst
->link
, c
->cursor
.link
);
375 case vir_cursor_addtail
:
376 list_addtail(&inst
->link
, c
->cursor
.link
);
380 c
->cursor
= vir_after_inst(inst
);
381 c
->live_intervals_valid
= false;
384 /* Updates inst to write to a new temporary, emits it, and notes the def. */
386 vir_emit_def(struct v3d_compile
*c
, struct qinst
*inst
)
388 assert(inst
->dst
.file
== QFILE_NULL
);
390 /* If we're emitting an instruction that's a def, it had better be
391 * writing a register.
393 if (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_ALU
) {
394 assert(inst
->qpu
.alu
.add
.op
== V3D_QPU_A_NOP
||
395 v3d_qpu_add_op_has_dst(inst
->qpu
.alu
.add
.op
));
396 assert(inst
->qpu
.alu
.mul
.op
== V3D_QPU_M_NOP
||
397 v3d_qpu_mul_op_has_dst(inst
->qpu
.alu
.mul
.op
));
400 inst
->dst
= vir_get_temp(c
);
402 if (inst
->dst
.file
== QFILE_TEMP
)
403 c
->defs
[inst
->dst
.index
] = inst
;
411 vir_emit_nondef(struct v3d_compile
*c
, struct qinst
*inst
)
413 if (inst
->dst
.file
== QFILE_TEMP
)
414 c
->defs
[inst
->dst
.index
] = NULL
;
422 vir_new_block(struct v3d_compile
*c
)
424 struct qblock
*block
= rzalloc(c
, struct qblock
);
426 list_inithead(&block
->instructions
);
428 block
->predecessors
= _mesa_set_create(block
,
430 _mesa_key_pointer_equal
);
432 block
->index
= c
->next_block_index
++;
438 vir_set_emit_block(struct v3d_compile
*c
, struct qblock
*block
)
440 c
->cur_block
= block
;
441 c
->cursor
= vir_after_block(block
);
442 list_addtail(&block
->link
, &c
->blocks
);
446 vir_entry_block(struct v3d_compile
*c
)
448 return list_first_entry(&c
->blocks
, struct qblock
, link
);
452 vir_exit_block(struct v3d_compile
*c
)
454 return list_last_entry(&c
->blocks
, struct qblock
, link
);
458 vir_link_blocks(struct qblock
*predecessor
, struct qblock
*successor
)
460 _mesa_set_add(successor
->predecessors
, predecessor
);
461 if (predecessor
->successors
[0]) {
462 assert(!predecessor
->successors
[1]);
463 predecessor
->successors
[1] = successor
;
465 predecessor
->successors
[0] = successor
;
469 const struct v3d_compiler
*
470 v3d_compiler_init(const struct v3d_device_info
*devinfo
)
472 struct v3d_compiler
*compiler
= rzalloc(NULL
, struct v3d_compiler
);
476 compiler
->devinfo
= devinfo
;
478 if (!vir_init_reg_sets(compiler
)) {
479 ralloc_free(compiler
);
487 v3d_compiler_free(const struct v3d_compiler
*compiler
)
489 ralloc_free((void *)compiler
);
492 static struct v3d_compile
*
493 vir_compile_init(const struct v3d_compiler
*compiler
,
496 void (*debug_output
)(const char *msg
,
497 void *debug_output_data
),
498 void *debug_output_data
,
499 int program_id
, int variant_id
)
501 struct v3d_compile
*c
= rzalloc(NULL
, struct v3d_compile
);
503 c
->compiler
= compiler
;
504 c
->devinfo
= compiler
->devinfo
;
506 c
->program_id
= program_id
;
507 c
->variant_id
= variant_id
;
509 c
->debug_output
= debug_output
;
510 c
->debug_output_data
= debug_output_data
;
512 s
= nir_shader_clone(c
, s
);
515 list_inithead(&c
->blocks
);
516 vir_set_emit_block(c
, vir_new_block(c
));
518 c
->output_position_index
= -1;
519 c
->output_sample_mask_index
= -1;
521 c
->def_ht
= _mesa_hash_table_create(c
, _mesa_hash_pointer
,
522 _mesa_key_pointer_equal
);
528 type_size_vec4(const struct glsl_type
*type
, bool bindless
)
530 return glsl_count_attribute_slots(type
, false);
534 v3d_lower_nir(struct v3d_compile
*c
)
536 struct nir_lower_tex_options tex_options
= {
538 .lower_tg4_broadcom_swizzle
= true,
540 .lower_rect
= false, /* XXX: Use this on V3D 3.x */
542 /* Apply swizzles to all samplers. */
543 .swizzle_result
= ~0,
546 /* Lower the format swizzle and (for 32-bit returns)
547 * ARB_texture_swizzle-style swizzle.
549 for (int i
= 0; i
< ARRAY_SIZE(c
->key
->tex
); i
++) {
550 for (int j
= 0; j
< 4; j
++)
551 tex_options
.swizzles
[i
][j
] = c
->key
->tex
[i
].swizzle
[j
];
553 if (c
->key
->tex
[i
].clamp_s
)
554 tex_options
.saturate_s
|= 1 << i
;
555 if (c
->key
->tex
[i
].clamp_t
)
556 tex_options
.saturate_t
|= 1 << i
;
557 if (c
->key
->tex
[i
].clamp_r
)
558 tex_options
.saturate_r
|= 1 << i
;
559 if (c
->key
->tex
[i
].return_size
== 16) {
560 tex_options
.lower_tex_packing
[i
] =
561 nir_lower_tex_packing_16
;
565 NIR_PASS_V(c
->s
, nir_lower_tex
, &tex_options
);
566 NIR_PASS_V(c
->s
, nir_lower_system_values
);
570 v3d_set_prog_data_uniforms(struct v3d_compile
*c
,
571 struct v3d_prog_data
*prog_data
)
573 int count
= c
->num_uniforms
;
574 struct v3d_uniform_list
*ulist
= &prog_data
->uniforms
;
576 ulist
->count
= count
;
577 ulist
->data
= ralloc_array(prog_data
, uint32_t, count
);
578 memcpy(ulist
->data
, c
->uniform_data
,
579 count
* sizeof(*ulist
->data
));
580 ulist
->contents
= ralloc_array(prog_data
, enum quniform_contents
, count
);
581 memcpy(ulist
->contents
, c
->uniform_contents
,
582 count
* sizeof(*ulist
->contents
));
586 v3d_vs_set_prog_data(struct v3d_compile
*c
,
587 struct v3d_vs_prog_data
*prog_data
)
589 /* The vertex data gets format converted by the VPM so that
590 * each attribute channel takes up a VPM column. Precompute
591 * the sizes for the shader record.
593 for (int i
= 0; i
< ARRAY_SIZE(prog_data
->vattr_sizes
); i
++) {
594 prog_data
->vattr_sizes
[i
] = c
->vattr_sizes
[i
];
595 prog_data
->vpm_input_size
+= c
->vattr_sizes
[i
];
598 prog_data
->uses_vid
= (c
->s
->info
.system_values_read
&
599 (1ull << SYSTEM_VALUE_VERTEX_ID
));
600 prog_data
->uses_iid
= (c
->s
->info
.system_values_read
&
601 (1ull << SYSTEM_VALUE_INSTANCE_ID
));
603 if (prog_data
->uses_vid
)
604 prog_data
->vpm_input_size
++;
605 if (prog_data
->uses_iid
)
606 prog_data
->vpm_input_size
++;
608 /* Input/output segment size are in sectors (8 rows of 32 bits per
611 prog_data
->vpm_input_size
= align(prog_data
->vpm_input_size
, 8) / 8;
612 prog_data
->vpm_output_size
= align(c
->vpm_output_size
, 8) / 8;
614 /* Set us up for shared input/output segments. This is apparently
615 * necessary for our VCM setup to avoid varying corruption.
617 prog_data
->separate_segments
= false;
618 prog_data
->vpm_output_size
= MAX2(prog_data
->vpm_output_size
,
619 prog_data
->vpm_input_size
);
620 prog_data
->vpm_input_size
= 0;
622 /* Compute VCM cache size. We set up our program to take up less than
623 * half of the VPM, so that any set of bin and render programs won't
624 * run out of space. We need space for at least one input segment,
625 * and then allocate the rest to output segments (one for the current
626 * program, the rest to VCM). The valid range of the VCM cache size
627 * field is 1-4 16-vertex batches, but GFXH-1744 limits us to 2-4
630 assert(c
->devinfo
->vpm_size
);
631 int sector_size
= V3D_CHANNELS
* sizeof(uint32_t) * 8;
632 int vpm_size_in_sectors
= c
->devinfo
->vpm_size
/ sector_size
;
633 int half_vpm
= vpm_size_in_sectors
/ 2;
634 int vpm_output_sectors
= half_vpm
- prog_data
->vpm_input_size
;
635 int vpm_output_batches
= vpm_output_sectors
/ prog_data
->vpm_output_size
;
636 assert(vpm_output_batches
>= 2);
637 prog_data
->vcm_cache_size
= CLAMP(vpm_output_batches
- 1, 2, 4);
641 v3d_set_fs_prog_data_inputs(struct v3d_compile
*c
,
642 struct v3d_fs_prog_data
*prog_data
)
644 prog_data
->num_inputs
= c
->num_inputs
;
645 memcpy(prog_data
->input_slots
, c
->input_slots
,
646 c
->num_inputs
* sizeof(*c
->input_slots
));
648 STATIC_ASSERT(ARRAY_SIZE(prog_data
->flat_shade_flags
) >
649 (V3D_MAX_FS_INPUTS
- 1) / 24);
650 for (int i
= 0; i
< V3D_MAX_FS_INPUTS
; i
++) {
651 if (BITSET_TEST(c
->flat_shade_flags
, i
))
652 prog_data
->flat_shade_flags
[i
/ 24] |= 1 << (i
% 24);
654 if (BITSET_TEST(c
->noperspective_flags
, i
))
655 prog_data
->noperspective_flags
[i
/ 24] |= 1 << (i
% 24);
657 if (BITSET_TEST(c
->centroid_flags
, i
))
658 prog_data
->centroid_flags
[i
/ 24] |= 1 << (i
% 24);
663 v3d_fs_set_prog_data(struct v3d_compile
*c
,
664 struct v3d_fs_prog_data
*prog_data
)
666 v3d_set_fs_prog_data_inputs(c
, prog_data
);
667 prog_data
->writes_z
= c
->writes_z
;
668 prog_data
->disable_ez
= !c
->s
->info
.fs
.early_fragment_tests
;
669 prog_data
->uses_center_w
= c
->uses_center_w
;
673 v3d_set_prog_data(struct v3d_compile
*c
,
674 struct v3d_prog_data
*prog_data
)
676 prog_data
->threads
= c
->threads
;
677 prog_data
->single_seg
= !c
->last_thrsw
;
678 prog_data
->spill_size
= c
->spill_size
;
680 v3d_set_prog_data_uniforms(c
, prog_data
);
682 if (c
->s
->info
.stage
== MESA_SHADER_VERTEX
) {
683 v3d_vs_set_prog_data(c
, (struct v3d_vs_prog_data
*)prog_data
);
685 assert(c
->s
->info
.stage
== MESA_SHADER_FRAGMENT
);
686 v3d_fs_set_prog_data(c
, (struct v3d_fs_prog_data
*)prog_data
);
691 v3d_return_qpu_insts(struct v3d_compile
*c
, uint32_t *final_assembly_size
)
693 *final_assembly_size
= c
->qpu_inst_count
* sizeof(uint64_t);
695 uint64_t *qpu_insts
= malloc(*final_assembly_size
);
699 memcpy(qpu_insts
, c
->qpu_insts
, *final_assembly_size
);
701 vir_compile_destroy(c
);
707 v3d_nir_lower_vs_early(struct v3d_compile
*c
)
709 /* Split our I/O vars and dead code eliminate the unused
712 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar_early
,
713 nir_var_shader_in
| nir_var_shader_out
);
714 uint64_t used_outputs
[4] = {0};
715 for (int i
= 0; i
< c
->vs_key
->num_fs_inputs
; i
++) {
716 int slot
= v3d_slot_get_slot(c
->vs_key
->fs_inputs
[i
]);
717 int comp
= v3d_slot_get_component(c
->vs_key
->fs_inputs
[i
]);
718 used_outputs
[comp
] |= 1ull << slot
;
720 NIR_PASS_V(c
->s
, nir_remove_unused_io_vars
,
721 &c
->s
->outputs
, used_outputs
, NULL
); /* demotes to globals */
722 NIR_PASS_V(c
->s
, nir_lower_global_vars_to_local
);
723 v3d_optimize_nir(c
->s
);
724 NIR_PASS_V(c
->s
, nir_remove_dead_variables
, nir_var_shader_in
);
725 NIR_PASS_V(c
->s
, nir_lower_io
, nir_var_shader_in
| nir_var_shader_out
,
727 (nir_lower_io_options
)0);
731 v3d_fixup_fs_output_types(struct v3d_compile
*c
)
733 nir_foreach_variable(var
, &c
->s
->outputs
) {
736 switch (var
->data
.location
) {
737 case FRAG_RESULT_COLOR
:
740 case FRAG_RESULT_DATA0
:
741 case FRAG_RESULT_DATA1
:
742 case FRAG_RESULT_DATA2
:
743 case FRAG_RESULT_DATA3
:
744 mask
= 1 << (var
->data
.location
- FRAG_RESULT_DATA0
);
748 if (c
->fs_key
->int_color_rb
& mask
) {
750 glsl_vector_type(GLSL_TYPE_INT
,
751 glsl_get_components(var
->type
));
752 } else if (c
->fs_key
->uint_color_rb
& mask
) {
754 glsl_vector_type(GLSL_TYPE_UINT
,
755 glsl_get_components(var
->type
));
761 v3d_nir_lower_fs_early(struct v3d_compile
*c
)
763 if (c
->fs_key
->int_color_rb
|| c
->fs_key
->uint_color_rb
)
764 v3d_fixup_fs_output_types(c
);
766 /* If the shader has no non-TLB side effects, we can promote it to
767 * enabling early_fragment_tests even if the user didn't.
769 if (!(c
->s
->info
.num_images
||
770 c
->s
->info
.num_ssbos
||
771 c
->s
->info
.num_abos
)) {
772 c
->s
->info
.fs
.early_fragment_tests
= true;
777 v3d_nir_lower_vs_late(struct v3d_compile
*c
)
779 if (c
->vs_key
->clamp_color
)
780 NIR_PASS_V(c
->s
, nir_lower_clamp_color_outputs
);
782 if (c
->key
->ucp_enables
) {
783 NIR_PASS_V(c
->s
, nir_lower_clip_vs
, c
->key
->ucp_enables
,
785 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar
,
789 /* Note: VS output scalarizing must happen after nir_lower_clip_vs. */
790 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar
, nir_var_shader_out
);
794 v3d_nir_lower_fs_late(struct v3d_compile
*c
)
796 if (c
->fs_key
->light_twoside
)
797 NIR_PASS_V(c
->s
, nir_lower_two_sided_color
);
799 if (c
->fs_key
->clamp_color
)
800 NIR_PASS_V(c
->s
, nir_lower_clamp_color_outputs
);
802 if (c
->fs_key
->alpha_test
) {
803 NIR_PASS_V(c
->s
, nir_lower_alpha_test
,
804 c
->fs_key
->alpha_test_func
,
808 if (c
->key
->ucp_enables
)
809 NIR_PASS_V(c
->s
, nir_lower_clip_fs
, c
->key
->ucp_enables
);
811 /* Note: FS input scalarizing must happen after
812 * nir_lower_two_sided_color, which only handles a vec4 at a time.
814 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar
, nir_var_shader_in
);
818 vir_get_max_temps(struct v3d_compile
*c
)
821 vir_for_each_inst_inorder(inst
, c
)
824 uint32_t *pressure
= rzalloc_array(NULL
, uint32_t, max_ip
);
826 for (int t
= 0; t
< c
->num_temps
; t
++) {
827 for (int i
= c
->temp_start
[t
]; (i
< c
->temp_end
[t
] &&
835 uint32_t max_temps
= 0;
836 for (int i
= 0; i
< max_ip
; i
++)
837 max_temps
= MAX2(max_temps
, pressure
[i
]);
839 ralloc_free(pressure
);
844 uint64_t *v3d_compile(const struct v3d_compiler
*compiler
,
846 struct v3d_prog_data
**out_prog_data
,
848 void (*debug_output
)(const char *msg
,
849 void *debug_output_data
),
850 void *debug_output_data
,
851 int program_id
, int variant_id
,
852 uint32_t *final_assembly_size
)
854 struct v3d_prog_data
*prog_data
;
855 struct v3d_compile
*c
= vir_compile_init(compiler
, key
, s
,
856 debug_output
, debug_output_data
,
857 program_id
, variant_id
);
859 switch (c
->s
->info
.stage
) {
860 case MESA_SHADER_VERTEX
:
861 c
->vs_key
= (struct v3d_vs_key
*)key
;
862 prog_data
= rzalloc_size(NULL
, sizeof(struct v3d_vs_prog_data
));
864 case MESA_SHADER_FRAGMENT
:
865 c
->fs_key
= (struct v3d_fs_key
*)key
;
866 prog_data
= rzalloc_size(NULL
, sizeof(struct v3d_fs_prog_data
));
869 unreachable("unsupported shader stage");
872 if (c
->s
->info
.stage
== MESA_SHADER_VERTEX
) {
873 v3d_nir_lower_vs_early(c
);
875 assert(c
->s
->info
.stage
== MESA_SHADER_FRAGMENT
);
876 v3d_nir_lower_fs_early(c
);
881 if (c
->s
->info
.stage
== MESA_SHADER_VERTEX
) {
882 v3d_nir_lower_vs_late(c
);
884 assert(c
->s
->info
.stage
== MESA_SHADER_FRAGMENT
);
885 v3d_nir_lower_fs_late(c
);
888 NIR_PASS_V(c
->s
, v3d_nir_lower_io
, c
);
889 NIR_PASS_V(c
->s
, v3d_nir_lower_txf_ms
, c
);
890 NIR_PASS_V(c
->s
, v3d_nir_lower_image_load_store
);
891 NIR_PASS_V(c
->s
, nir_lower_idiv
);
893 v3d_optimize_nir(c
->s
);
894 NIR_PASS_V(c
->s
, nir_lower_bool_to_int32
);
895 NIR_PASS_V(c
->s
, nir_convert_from_ssa
, true);
899 v3d_set_prog_data(c
, prog_data
);
901 *out_prog_data
= prog_data
;
904 int ret
= asprintf(&shaderdb
,
905 "%s shader: %d inst, %d threads, %d loops, "
906 "%d uniforms, %d max-temps, %d:%d spills:fills",
907 vir_get_stage_name(c
),
912 vir_get_max_temps(c
),
916 c
->debug_output(shaderdb
, c
->debug_output_data
);
920 return v3d_return_qpu_insts(c
, final_assembly_size
);
924 vir_remove_instruction(struct v3d_compile
*c
, struct qinst
*qinst
)
926 if (qinst
->dst
.file
== QFILE_TEMP
)
927 c
->defs
[qinst
->dst
.index
] = NULL
;
929 assert(&qinst
->link
!= c
->cursor
.link
);
931 list_del(&qinst
->link
);
934 c
->live_intervals_valid
= false;
938 vir_follow_movs(struct v3d_compile
*c
, struct qreg reg
)
943 while (reg.file == QFILE_TEMP &&
944 c->defs[reg.index] &&
945 (c->defs[reg.index]->op == QOP_MOV ||
946 c->defs[reg.index]->op == QOP_FMOV) &&
947 !c->defs[reg.index]->dst.pack &&
948 !c->defs[reg.index]->src[0].pack) {
949 reg = c->defs[reg.index]->src[0];
958 vir_compile_destroy(struct v3d_compile
*c
)
960 /* Defuse the assert that we aren't removing the cursor's instruction.
962 c
->cursor
.link
= NULL
;
964 vir_for_each_block(block
, c
) {
965 while (!list_empty(&block
->instructions
)) {
966 struct qinst
*qinst
=
967 list_first_entry(&block
->instructions
,
969 vir_remove_instruction(c
, qinst
);
977 vir_get_uniform_index(struct v3d_compile
*c
,
978 enum quniform_contents contents
,
981 for (int i
= 0; i
< c
->num_uniforms
; i
++) {
982 if (c
->uniform_contents
[i
] == contents
&&
983 c
->uniform_data
[i
] == data
) {
988 uint32_t uniform
= c
->num_uniforms
++;
990 if (uniform
>= c
->uniform_array_size
) {
991 c
->uniform_array_size
= MAX2(MAX2(16, uniform
+ 1),
992 c
->uniform_array_size
* 2);
994 c
->uniform_data
= reralloc(c
, c
->uniform_data
,
996 c
->uniform_array_size
);
997 c
->uniform_contents
= reralloc(c
, c
->uniform_contents
,
998 enum quniform_contents
,
999 c
->uniform_array_size
);
1002 c
->uniform_contents
[uniform
] = contents
;
1003 c
->uniform_data
[uniform
] = data
;
1009 vir_uniform(struct v3d_compile
*c
,
1010 enum quniform_contents contents
,
1013 struct qinst
*inst
= vir_NOP(c
);
1014 inst
->qpu
.sig
.ldunif
= true;
1015 inst
->uniform
= vir_get_uniform_index(c
, contents
, data
);
1016 inst
->dst
= vir_get_temp(c
);
1017 c
->defs
[inst
->dst
.index
] = inst
;
1021 #define OPTPASS(func) \
1023 bool stage_progress = func(c); \
1024 if (stage_progress) { \
1026 if (print_opt_debug) { \
1028 "VIR opt pass %2d: %s progress\n", \
1031 /*XXX vir_validate(c);*/ \
1036 vir_optimize(struct v3d_compile
*c
)
1038 bool print_opt_debug
= false;
1042 bool progress
= false;
1044 OPTPASS(vir_opt_copy_propagate
);
1045 OPTPASS(vir_opt_redundant_flags
);
1046 OPTPASS(vir_opt_dead_code
);
1047 OPTPASS(vir_opt_small_immediates
);
1057 vir_get_stage_name(struct v3d_compile
*c
)
1059 if (c
->vs_key
&& c
->vs_key
->is_coord
)
1060 return "MESA_SHADER_COORD";
1062 return gl_shader_stage_name(c
->s
->info
.stage
);