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 switch (inst
->dst
.index
) {
66 case V3D_QPU_WADDR_TLBU
:
67 case V3D_QPU_WADDR_TMUAU
:
68 case V3D_QPU_WADDR_SYNCU
:
75 return inst
->has_implicit_uniform
;
81 /* The sideband uniform for textures gets stored after the normal ALU
85 vir_get_implicit_uniform_src(struct qinst
*inst
)
87 if (!vir_has_implicit_uniform(inst
))
89 return vir_get_nsrc(inst
) - 1;
93 * Returns whether the instruction has any side effects that must be
97 vir_has_side_effects(struct v3d_compile
*c
, struct qinst
*inst
)
99 switch (inst
->qpu
.type
) {
100 case V3D_QPU_INSTR_TYPE_BRANCH
:
102 case V3D_QPU_INSTR_TYPE_ALU
:
103 switch (inst
->qpu
.alu
.add
.op
) {
104 case V3D_QPU_A_SETREVF
:
105 case V3D_QPU_A_SETMSF
:
106 case V3D_QPU_A_VPMSETUP
:
107 case V3D_QPU_A_STVPMV
:
108 case V3D_QPU_A_STVPMD
:
109 case V3D_QPU_A_STVPMP
:
110 case V3D_QPU_A_VPMWT
:
111 case V3D_QPU_A_TMUWT
:
117 switch (inst
->qpu
.alu
.mul
.op
) {
118 case V3D_QPU_M_MULTOP
:
125 if (inst
->qpu
.sig
.ldtmu
||
126 inst
->qpu
.sig
.ldvary
||
127 inst
->qpu
.sig
.wrtmuc
||
128 inst
->qpu
.sig
.thrsw
) {
136 vir_is_float_input(struct qinst
*inst
)
138 /* XXX: More instrs */
139 switch (inst
->qpu
.type
) {
140 case V3D_QPU_INSTR_TYPE_BRANCH
:
142 case V3D_QPU_INSTR_TYPE_ALU
:
143 switch (inst
->qpu
.alu
.add
.op
) {
148 case V3D_QPU_A_FTOIN
:
154 switch (inst
->qpu
.alu
.mul
.op
) {
156 case V3D_QPU_M_VFMUL
:
168 vir_is_raw_mov(struct qinst
*inst
)
170 if (inst
->qpu
.type
!= V3D_QPU_INSTR_TYPE_ALU
||
171 (inst
->qpu
.alu
.mul
.op
!= V3D_QPU_M_FMOV
&&
172 inst
->qpu
.alu
.mul
.op
!= V3D_QPU_M_MOV
)) {
176 if (inst
->qpu
.alu
.add
.output_pack
!= V3D_QPU_PACK_NONE
||
177 inst
->qpu
.alu
.mul
.output_pack
!= V3D_QPU_PACK_NONE
) {
181 if (inst
->qpu
.flags
.ac
!= V3D_QPU_COND_NONE
||
182 inst
->qpu
.flags
.mc
!= V3D_QPU_COND_NONE
)
189 vir_is_add(struct qinst
*inst
)
191 return (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_ALU
&&
192 inst
->qpu
.alu
.add
.op
!= V3D_QPU_A_NOP
);
196 vir_is_mul(struct qinst
*inst
)
198 return (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_ALU
&&
199 inst
->qpu
.alu
.mul
.op
!= V3D_QPU_M_NOP
);
203 vir_is_tex(struct qinst
*inst
)
205 if (inst
->dst
.file
== QFILE_MAGIC
)
206 return v3d_qpu_magic_waddr_is_tmu(inst
->dst
.index
);
208 if (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_ALU
&&
209 inst
->qpu
.alu
.add
.op
== V3D_QPU_A_TMUWT
) {
217 vir_writes_r3(const struct v3d_device_info
*devinfo
, struct qinst
*inst
)
219 for (int i
= 0; i
< vir_get_nsrc(inst
); i
++) {
220 switch (inst
->src
[i
].file
) {
228 if (devinfo
->ver
< 41 && (inst
->qpu
.sig
.ldvary
||
229 inst
->qpu
.sig
.ldtlb
||
230 inst
->qpu
.sig
.ldtlbu
||
231 inst
->qpu
.sig
.ldvpm
)) {
239 vir_writes_r4(const struct v3d_device_info
*devinfo
, struct qinst
*inst
)
241 switch (inst
->dst
.file
) {
243 switch (inst
->dst
.index
) {
244 case V3D_QPU_WADDR_RECIP
:
245 case V3D_QPU_WADDR_RSQRT
:
246 case V3D_QPU_WADDR_EXP
:
247 case V3D_QPU_WADDR_LOG
:
248 case V3D_QPU_WADDR_SIN
:
256 if (devinfo
->ver
< 41 && inst
->qpu
.sig
.ldtmu
)
263 vir_set_unpack(struct qinst
*inst
, int src
,
264 enum v3d_qpu_input_unpack unpack
)
266 assert(src
== 0 || src
== 1);
268 if (vir_is_add(inst
)) {
270 inst
->qpu
.alu
.add
.a_unpack
= unpack
;
272 inst
->qpu
.alu
.add
.b_unpack
= unpack
;
274 assert(vir_is_mul(inst
));
276 inst
->qpu
.alu
.mul
.a_unpack
= unpack
;
278 inst
->qpu
.alu
.mul
.b_unpack
= unpack
;
283 vir_set_cond(struct qinst
*inst
, enum v3d_qpu_cond cond
)
285 if (vir_is_add(inst
)) {
286 inst
->qpu
.flags
.ac
= cond
;
288 assert(vir_is_mul(inst
));
289 inst
->qpu
.flags
.mc
= cond
;
294 vir_set_pf(struct qinst
*inst
, enum v3d_qpu_pf pf
)
296 if (vir_is_add(inst
)) {
297 inst
->qpu
.flags
.apf
= pf
;
299 assert(vir_is_mul(inst
));
300 inst
->qpu
.flags
.mpf
= pf
;
305 vir_set_uf(struct qinst
*inst
, enum v3d_qpu_uf uf
)
307 if (vir_is_add(inst
)) {
308 inst
->qpu
.flags
.auf
= uf
;
310 assert(vir_is_mul(inst
));
311 inst
->qpu
.flags
.muf
= uf
;
317 vir_channels_written(struct qinst
*inst
)
319 if (vir_is_mul(inst
)) {
320 switch (inst
->dst
.pack
) {
321 case QPU_PACK_MUL_NOP
:
322 case QPU_PACK_MUL_8888
:
324 case QPU_PACK_MUL_8A
:
326 case QPU_PACK_MUL_8B
:
328 case QPU_PACK_MUL_8C
:
330 case QPU_PACK_MUL_8D
:
334 switch (inst
->dst
.pack
) {
336 case QPU_PACK_A_8888
:
337 case QPU_PACK_A_8888_SAT
:
338 case QPU_PACK_A_32_SAT
:
341 case QPU_PACK_A_8A_SAT
:
344 case QPU_PACK_A_8B_SAT
:
347 case QPU_PACK_A_8C_SAT
:
350 case QPU_PACK_A_8D_SAT
:
353 case QPU_PACK_A_16A_SAT
:
356 case QPU_PACK_A_16B_SAT
:
360 unreachable("Bad pack field");
365 vir_get_temp(struct v3d_compile
*c
)
369 reg
.file
= QFILE_TEMP
;
370 reg
.index
= c
->num_temps
++;
372 if (c
->num_temps
> c
->defs_array_size
) {
373 uint32_t old_size
= c
->defs_array_size
;
374 c
->defs_array_size
= MAX2(old_size
* 2, 16);
376 c
->defs
= reralloc(c
, c
->defs
, struct qinst
*,
378 memset(&c
->defs
[old_size
], 0,
379 sizeof(c
->defs
[0]) * (c
->defs_array_size
- old_size
));
381 c
->spillable
= reralloc(c
, c
->spillable
,
383 BITSET_WORDS(c
->defs_array_size
));
384 for (int i
= old_size
; i
< c
->defs_array_size
; i
++)
385 BITSET_SET(c
->spillable
, i
);
392 vir_add_inst(enum v3d_qpu_add_op op
, struct qreg dst
, struct qreg src0
, struct qreg src1
)
394 struct qinst
*inst
= calloc(1, sizeof(*inst
));
396 inst
->qpu
= v3d_qpu_nop();
397 inst
->qpu
.alu
.add
.op
= op
;
408 vir_mul_inst(enum v3d_qpu_mul_op op
, struct qreg dst
, struct qreg src0
, struct qreg src1
)
410 struct qinst
*inst
= calloc(1, sizeof(*inst
));
412 inst
->qpu
= v3d_qpu_nop();
413 inst
->qpu
.alu
.mul
.op
= op
;
424 vir_branch_inst(enum v3d_qpu_branch_cond cond
, struct qreg src
)
426 struct qinst
*inst
= calloc(1, sizeof(*inst
));
428 inst
->qpu
= v3d_qpu_nop();
429 inst
->qpu
.type
= V3D_QPU_INSTR_TYPE_BRANCH
;
430 inst
->qpu
.branch
.cond
= cond
;
431 inst
->qpu
.branch
.msfign
= V3D_QPU_MSFIGN_NONE
;
432 inst
->qpu
.branch
.bdi
= V3D_QPU_BRANCH_DEST_REL
;
433 inst
->qpu
.branch
.ub
= true;
434 inst
->qpu
.branch
.bdu
= V3D_QPU_BRANCH_DEST_REL
;
436 inst
->dst
= vir_reg(QFILE_NULL
, 0);
444 vir_emit(struct v3d_compile
*c
, struct qinst
*inst
)
446 switch (c
->cursor
.mode
) {
448 list_add(&inst
->link
, c
->cursor
.link
);
450 case vir_cursor_addtail
:
451 list_addtail(&inst
->link
, c
->cursor
.link
);
455 c
->cursor
= vir_after_inst(inst
);
456 c
->live_intervals_valid
= false;
459 /* Updates inst to write to a new temporary, emits it, and notes the def. */
461 vir_emit_def(struct v3d_compile
*c
, struct qinst
*inst
)
463 assert(inst
->dst
.file
== QFILE_NULL
);
465 /* If we're emitting an instruction that's a def, it had better be
466 * writing a register.
468 if (inst
->qpu
.type
== V3D_QPU_INSTR_TYPE_ALU
) {
469 assert(inst
->qpu
.alu
.add
.op
== V3D_QPU_A_NOP
||
470 v3d_qpu_add_op_has_dst(inst
->qpu
.alu
.add
.op
));
471 assert(inst
->qpu
.alu
.mul
.op
== V3D_QPU_M_NOP
||
472 v3d_qpu_mul_op_has_dst(inst
->qpu
.alu
.mul
.op
));
475 inst
->dst
= vir_get_temp(c
);
477 if (inst
->dst
.file
== QFILE_TEMP
)
478 c
->defs
[inst
->dst
.index
] = inst
;
486 vir_emit_nondef(struct v3d_compile
*c
, struct qinst
*inst
)
488 if (inst
->dst
.file
== QFILE_TEMP
)
489 c
->defs
[inst
->dst
.index
] = NULL
;
497 vir_new_block(struct v3d_compile
*c
)
499 struct qblock
*block
= rzalloc(c
, struct qblock
);
501 list_inithead(&block
->instructions
);
503 block
->predecessors
= _mesa_set_create(block
,
505 _mesa_key_pointer_equal
);
507 block
->index
= c
->next_block_index
++;
513 vir_set_emit_block(struct v3d_compile
*c
, struct qblock
*block
)
515 c
->cur_block
= block
;
516 c
->cursor
= vir_after_block(block
);
517 list_addtail(&block
->link
, &c
->blocks
);
521 vir_entry_block(struct v3d_compile
*c
)
523 return list_first_entry(&c
->blocks
, struct qblock
, link
);
527 vir_exit_block(struct v3d_compile
*c
)
529 return list_last_entry(&c
->blocks
, struct qblock
, link
);
533 vir_link_blocks(struct qblock
*predecessor
, struct qblock
*successor
)
535 _mesa_set_add(successor
->predecessors
, predecessor
);
536 if (predecessor
->successors
[0]) {
537 assert(!predecessor
->successors
[1]);
538 predecessor
->successors
[1] = successor
;
540 predecessor
->successors
[0] = successor
;
544 const struct v3d_compiler
*
545 v3d_compiler_init(const struct v3d_device_info
*devinfo
)
547 struct v3d_compiler
*compiler
= rzalloc(NULL
, struct v3d_compiler
);
551 compiler
->devinfo
= devinfo
;
553 if (!vir_init_reg_sets(compiler
)) {
554 ralloc_free(compiler
);
562 v3d_compiler_free(const struct v3d_compiler
*compiler
)
564 ralloc_free((void *)compiler
);
567 static struct v3d_compile
*
568 vir_compile_init(const struct v3d_compiler
*compiler
,
571 void (*debug_output
)(const char *msg
,
572 void *debug_output_data
),
573 void *debug_output_data
,
574 int program_id
, int variant_id
)
576 struct v3d_compile
*c
= rzalloc(NULL
, struct v3d_compile
);
578 c
->compiler
= compiler
;
579 c
->devinfo
= compiler
->devinfo
;
581 c
->program_id
= program_id
;
582 c
->variant_id
= variant_id
;
584 c
->debug_output
= debug_output
;
585 c
->debug_output_data
= debug_output_data
;
587 s
= nir_shader_clone(c
, s
);
590 list_inithead(&c
->blocks
);
591 vir_set_emit_block(c
, vir_new_block(c
));
593 c
->output_position_index
= -1;
594 c
->output_point_size_index
= -1;
595 c
->output_sample_mask_index
= -1;
597 c
->def_ht
= _mesa_hash_table_create(c
, _mesa_hash_pointer
,
598 _mesa_key_pointer_equal
);
604 type_size_vec4(const struct glsl_type
*type
)
606 return glsl_count_attribute_slots(type
, false);
610 v3d_lower_nir(struct v3d_compile
*c
)
612 struct nir_lower_tex_options tex_options
= {
614 .lower_tg4_broadcom_swizzle
= true,
616 .lower_rect
= false, /* XXX: Use this on V3D 3.x */
618 /* Apply swizzles to all samplers. */
619 .swizzle_result
= ~0,
622 /* Lower the format swizzle and (for 32-bit returns)
623 * ARB_texture_swizzle-style swizzle.
625 for (int i
= 0; i
< ARRAY_SIZE(c
->key
->tex
); i
++) {
626 for (int j
= 0; j
< 4; j
++)
627 tex_options
.swizzles
[i
][j
] = c
->key
->tex
[i
].swizzle
[j
];
629 if (c
->key
->tex
[i
].clamp_s
)
630 tex_options
.saturate_s
|= 1 << i
;
631 if (c
->key
->tex
[i
].clamp_t
)
632 tex_options
.saturate_t
|= 1 << i
;
633 if (c
->key
->tex
[i
].clamp_r
)
634 tex_options
.saturate_r
|= 1 << i
;
635 if (c
->key
->tex
[i
].return_size
== 16) {
636 tex_options
.lower_tex_packing
[i
] =
637 nir_lower_tex_packing_16
;
641 NIR_PASS_V(c
->s
, nir_lower_tex
, &tex_options
);
642 NIR_PASS_V(c
->s
, nir_lower_system_values
);
646 v3d_set_prog_data_uniforms(struct v3d_compile
*c
,
647 struct v3d_prog_data
*prog_data
)
649 int count
= c
->num_uniforms
;
650 struct v3d_uniform_list
*ulist
= &prog_data
->uniforms
;
652 ulist
->count
= count
;
653 ulist
->data
= ralloc_array(prog_data
, uint32_t, count
);
654 memcpy(ulist
->data
, c
->uniform_data
,
655 count
* sizeof(*ulist
->data
));
656 ulist
->contents
= ralloc_array(prog_data
, enum quniform_contents
, count
);
657 memcpy(ulist
->contents
, c
->uniform_contents
,
658 count
* sizeof(*ulist
->contents
));
661 /* Copy the compiler UBO range state to the compiled shader, dropping out
662 * arrays that were never referenced by an indirect load.
664 * (Note that QIR dead code elimination of an array access still leaves that
665 * array alive, though)
668 v3d_set_prog_data_ubo(struct v3d_compile
*c
,
669 struct v3d_prog_data
*prog_data
)
671 if (!c
->num_ubo_ranges
)
674 prog_data
->num_ubo_ranges
= 0;
675 prog_data
->ubo_ranges
= ralloc_array(prog_data
, struct v3d_ubo_range
,
677 for (int i
= 0; i
< c
->num_ubo_ranges
; i
++) {
678 if (!c
->ubo_range_used
[i
])
681 struct v3d_ubo_range
*range
= &c
->ubo_ranges
[i
];
682 prog_data
->ubo_ranges
[prog_data
->num_ubo_ranges
++] = *range
;
683 prog_data
->ubo_size
+= range
->size
;
686 if (prog_data
->ubo_size
) {
687 if (V3D_DEBUG
& V3D_DEBUG_SHADERDB
) {
688 fprintf(stderr
, "SHADER-DB: %s prog %d/%d: %d UBO uniforms\n",
689 vir_get_stage_name(c
),
690 c
->program_id
, c
->variant_id
,
691 prog_data
->ubo_size
/ 4);
697 v3d_vs_set_prog_data(struct v3d_compile
*c
,
698 struct v3d_vs_prog_data
*prog_data
)
700 prog_data
->base
.num_inputs
= c
->num_inputs
;
702 /* The vertex data gets format converted by the VPM so that
703 * each attribute channel takes up a VPM column. Precompute
704 * the sizes for the shader record.
706 for (int i
= 0; i
< ARRAY_SIZE(prog_data
->vattr_sizes
); i
++) {
707 prog_data
->vattr_sizes
[i
] = c
->vattr_sizes
[i
];
708 prog_data
->vpm_input_size
+= c
->vattr_sizes
[i
];
711 prog_data
->uses_vid
= (c
->s
->info
.system_values_read
&
712 (1ull << SYSTEM_VALUE_VERTEX_ID
));
713 prog_data
->uses_iid
= (c
->s
->info
.system_values_read
&
714 (1ull << SYSTEM_VALUE_INSTANCE_ID
));
716 if (prog_data
->uses_vid
)
717 prog_data
->vpm_input_size
++;
718 if (prog_data
->uses_iid
)
719 prog_data
->vpm_input_size
++;
721 /* Input/output segment size are in sectors (8 rows of 32 bits per
724 prog_data
->vpm_input_size
= align(prog_data
->vpm_input_size
, 8) / 8;
725 prog_data
->vpm_output_size
= align(c
->num_vpm_writes
, 8) / 8;
727 /* Set us up for shared input/output segments. This is apparently
728 * necessary for our VCM setup to avoid varying corruption.
730 prog_data
->separate_segments
= false;
731 prog_data
->vpm_output_size
= MAX2(prog_data
->vpm_output_size
,
732 prog_data
->vpm_input_size
);
733 prog_data
->vpm_input_size
= 0;
735 /* Compute VCM cache size. We set up our program to take up less than
736 * half of the VPM, so that any set of bin and render programs won't
737 * run out of space. We need space for at least one input segment,
738 * and then allocate the rest to output segments (one for the current
739 * program, the rest to VCM). The valid range of the VCM cache size
740 * field is 1-4 16-vertex batches, but GFXH-1744 limits us to 2-4
743 assert(c
->devinfo
->vpm_size
);
744 int sector_size
= 16 * sizeof(uint32_t) * 8;
745 int vpm_size_in_sectors
= c
->devinfo
->vpm_size
/ sector_size
;
746 int half_vpm
= vpm_size_in_sectors
/ 2;
747 int vpm_output_sectors
= half_vpm
- prog_data
->vpm_input_size
;
748 int vpm_output_batches
= vpm_output_sectors
/ prog_data
->vpm_output_size
;
749 assert(vpm_output_batches
>= 2);
750 prog_data
->vcm_cache_size
= CLAMP(vpm_output_batches
- 1, 2, 4);
754 v3d_set_fs_prog_data_inputs(struct v3d_compile
*c
,
755 struct v3d_fs_prog_data
*prog_data
)
757 prog_data
->base
.num_inputs
= c
->num_inputs
;
758 memcpy(prog_data
->input_slots
, c
->input_slots
,
759 c
->num_inputs
* sizeof(*c
->input_slots
));
761 STATIC_ASSERT(ARRAY_SIZE(prog_data
->flat_shade_flags
) >
762 (V3D_MAX_FS_INPUTS
- 1) / 24);
763 for (int i
= 0; i
< V3D_MAX_FS_INPUTS
; i
++) {
764 if (BITSET_TEST(c
->flat_shade_flags
, i
))
765 prog_data
->flat_shade_flags
[i
/ 24] |= 1 << (i
% 24);
767 if (BITSET_TEST(c
->noperspective_flags
, i
))
768 prog_data
->noperspective_flags
[i
/ 24] |= 1 << (i
% 24);
770 if (BITSET_TEST(c
->centroid_flags
, i
))
771 prog_data
->centroid_flags
[i
/ 24] |= 1 << (i
% 24);
776 v3d_fs_set_prog_data(struct v3d_compile
*c
,
777 struct v3d_fs_prog_data
*prog_data
)
779 v3d_set_fs_prog_data_inputs(c
, prog_data
);
780 prog_data
->writes_z
= (c
->s
->info
.outputs_written
&
781 (1 << FRAG_RESULT_DEPTH
));
782 prog_data
->discard
= (c
->s
->info
.fs
.uses_discard
||
783 c
->fs_key
->sample_alpha_to_coverage
);
784 prog_data
->uses_center_w
= c
->uses_center_w
;
786 /* If the shader has some side effects and hasn't allowed early
787 * fragment tests, disable them.
789 if (!c
->s
->info
.fs
.early_fragment_tests
&&
790 (c
->s
->info
.num_images
||
791 c
->s
->info
.num_ssbos
||
792 c
->s
->info
.num_abos
)) {
793 prog_data
->discard
= true;
798 v3d_set_prog_data(struct v3d_compile
*c
,
799 struct v3d_prog_data
*prog_data
)
801 prog_data
->threads
= c
->threads
;
802 prog_data
->single_seg
= !c
->last_thrsw
;
803 prog_data
->spill_size
= c
->spill_size
;
805 v3d_set_prog_data_uniforms(c
, prog_data
);
806 v3d_set_prog_data_ubo(c
, prog_data
);
808 if (c
->s
->info
.stage
== MESA_SHADER_VERTEX
) {
809 v3d_vs_set_prog_data(c
, (struct v3d_vs_prog_data
*)prog_data
);
811 assert(c
->s
->info
.stage
== MESA_SHADER_FRAGMENT
);
812 v3d_fs_set_prog_data(c
, (struct v3d_fs_prog_data
*)prog_data
);
817 v3d_return_qpu_insts(struct v3d_compile
*c
, uint32_t *final_assembly_size
)
819 *final_assembly_size
= c
->qpu_inst_count
* sizeof(uint64_t);
821 uint64_t *qpu_insts
= malloc(*final_assembly_size
);
825 memcpy(qpu_insts
, c
->qpu_insts
, *final_assembly_size
);
827 vir_compile_destroy(c
);
833 v3d_nir_lower_vs_early(struct v3d_compile
*c
)
835 /* Split our I/O vars and dead code eliminate the unused
838 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar_early
,
839 nir_var_shader_in
| nir_var_shader_out
);
840 uint64_t used_outputs
[4] = {0};
841 for (int i
= 0; i
< c
->vs_key
->num_fs_inputs
; i
++) {
842 int slot
= v3d_slot_get_slot(c
->vs_key
->fs_inputs
[i
]);
843 int comp
= v3d_slot_get_component(c
->vs_key
->fs_inputs
[i
]);
844 used_outputs
[comp
] |= 1ull << slot
;
846 NIR_PASS_V(c
->s
, nir_remove_unused_io_vars
,
847 &c
->s
->outputs
, used_outputs
, NULL
); /* demotes to globals */
848 NIR_PASS_V(c
->s
, nir_lower_global_vars_to_local
);
849 v3d_optimize_nir(c
->s
);
850 NIR_PASS_V(c
->s
, nir_remove_dead_variables
, nir_var_shader_in
);
851 NIR_PASS_V(c
->s
, nir_lower_io
, nir_var_shader_in
| nir_var_shader_out
,
853 (nir_lower_io_options
)0);
857 v3d_fixup_fs_output_types(struct v3d_compile
*c
)
859 nir_foreach_variable(var
, &c
->s
->outputs
) {
862 switch (var
->data
.location
) {
863 case FRAG_RESULT_COLOR
:
866 case FRAG_RESULT_DATA0
:
867 case FRAG_RESULT_DATA1
:
868 case FRAG_RESULT_DATA2
:
869 case FRAG_RESULT_DATA3
:
870 mask
= 1 << (var
->data
.location
- FRAG_RESULT_DATA0
);
874 if (c
->fs_key
->int_color_rb
& mask
) {
876 glsl_vector_type(GLSL_TYPE_INT
,
877 glsl_get_components(var
->type
));
878 } else if (c
->fs_key
->uint_color_rb
& mask
) {
880 glsl_vector_type(GLSL_TYPE_UINT
,
881 glsl_get_components(var
->type
));
887 v3d_nir_lower_fs_early(struct v3d_compile
*c
)
889 if (c
->fs_key
->int_color_rb
|| c
->fs_key
->uint_color_rb
)
890 v3d_fixup_fs_output_types(c
);
894 v3d_nir_lower_vs_late(struct v3d_compile
*c
)
896 if (c
->vs_key
->clamp_color
)
897 NIR_PASS_V(c
->s
, nir_lower_clamp_color_outputs
);
899 if (c
->key
->ucp_enables
) {
900 NIR_PASS_V(c
->s
, nir_lower_clip_vs
, c
->key
->ucp_enables
,
902 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar
,
906 /* Note: VS output scalarizing must happen after nir_lower_clip_vs. */
907 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar
, nir_var_shader_out
);
911 v3d_nir_lower_fs_late(struct v3d_compile
*c
)
913 if (c
->fs_key
->light_twoside
)
914 NIR_PASS_V(c
->s
, nir_lower_two_sided_color
);
916 if (c
->fs_key
->clamp_color
)
917 NIR_PASS_V(c
->s
, nir_lower_clamp_color_outputs
);
919 if (c
->fs_key
->alpha_test
) {
920 NIR_PASS_V(c
->s
, nir_lower_alpha_test
,
921 c
->fs_key
->alpha_test_func
,
925 if (c
->key
->ucp_enables
)
926 NIR_PASS_V(c
->s
, nir_lower_clip_fs
, c
->key
->ucp_enables
);
928 /* Note: FS input scalarizing must happen after
929 * nir_lower_two_sided_color, which only handles a vec4 at a time.
931 NIR_PASS_V(c
->s
, nir_lower_io_to_scalar
, nir_var_shader_in
);
934 uint64_t *v3d_compile(const struct v3d_compiler
*compiler
,
936 struct v3d_prog_data
**out_prog_data
,
938 void (*debug_output
)(const char *msg
,
939 void *debug_output_data
),
940 void *debug_output_data
,
941 int program_id
, int variant_id
,
942 uint32_t *final_assembly_size
)
944 struct v3d_prog_data
*prog_data
;
945 struct v3d_compile
*c
= vir_compile_init(compiler
, key
, s
,
946 debug_output
, debug_output_data
,
947 program_id
, variant_id
);
949 switch (c
->s
->info
.stage
) {
950 case MESA_SHADER_VERTEX
:
951 c
->vs_key
= (struct v3d_vs_key
*)key
;
952 prog_data
= rzalloc_size(NULL
, sizeof(struct v3d_vs_prog_data
));
954 case MESA_SHADER_FRAGMENT
:
955 c
->fs_key
= (struct v3d_fs_key
*)key
;
956 prog_data
= rzalloc_size(NULL
, sizeof(struct v3d_fs_prog_data
));
959 unreachable("unsupported shader stage");
962 if (c
->s
->info
.stage
== MESA_SHADER_VERTEX
) {
963 v3d_nir_lower_vs_early(c
);
965 assert(c
->s
->info
.stage
== MESA_SHADER_FRAGMENT
);
966 v3d_nir_lower_fs_early(c
);
971 if (c
->s
->info
.stage
== MESA_SHADER_VERTEX
) {
972 v3d_nir_lower_vs_late(c
);
974 assert(c
->s
->info
.stage
== MESA_SHADER_FRAGMENT
);
975 v3d_nir_lower_fs_late(c
);
978 NIR_PASS_V(c
->s
, v3d_nir_lower_io
, c
);
979 NIR_PASS_V(c
->s
, v3d_nir_lower_txf_ms
, c
);
980 NIR_PASS_V(c
->s
, v3d_nir_lower_image_load_store
);
981 NIR_PASS_V(c
->s
, nir_lower_idiv
);
983 v3d_optimize_nir(c
->s
);
984 NIR_PASS_V(c
->s
, nir_lower_bool_to_int32
);
985 NIR_PASS_V(c
->s
, nir_convert_from_ssa
, true);
989 v3d_set_prog_data(c
, prog_data
);
991 *out_prog_data
= prog_data
;
994 int ret
= asprintf(&shaderdb
,
995 "%s shader: %d inst, %d threads, %d loops, "
996 "%d uniforms, %d:%d spills:fills",
997 vir_get_stage_name(c
),
1005 c
->debug_output(shaderdb
, c
->debug_output_data
);
1009 return v3d_return_qpu_insts(c
, final_assembly_size
);
1013 vir_remove_instruction(struct v3d_compile
*c
, struct qinst
*qinst
)
1015 if (qinst
->dst
.file
== QFILE_TEMP
)
1016 c
->defs
[qinst
->dst
.index
] = NULL
;
1018 assert(&qinst
->link
!= c
->cursor
.link
);
1020 list_del(&qinst
->link
);
1023 c
->live_intervals_valid
= false;
1027 vir_follow_movs(struct v3d_compile
*c
, struct qreg reg
)
1030 int pack = reg.pack;
1032 while (reg.file == QFILE_TEMP &&
1033 c->defs[reg.index] &&
1034 (c->defs[reg.index]->op == QOP_MOV ||
1035 c->defs[reg.index]->op == QOP_FMOV) &&
1036 !c->defs[reg.index]->dst.pack &&
1037 !c->defs[reg.index]->src[0].pack) {
1038 reg = c->defs[reg.index]->src[0];
1047 vir_compile_destroy(struct v3d_compile
*c
)
1049 /* Defuse the assert that we aren't removing the cursor's instruction.
1051 c
->cursor
.link
= NULL
;
1053 vir_for_each_block(block
, c
) {
1054 while (!list_empty(&block
->instructions
)) {
1055 struct qinst
*qinst
=
1056 list_first_entry(&block
->instructions
,
1057 struct qinst
, link
);
1058 vir_remove_instruction(c
, qinst
);
1066 vir_uniform(struct v3d_compile
*c
,
1067 enum quniform_contents contents
,
1070 for (int i
= 0; i
< c
->num_uniforms
; i
++) {
1071 if (c
->uniform_contents
[i
] == contents
&&
1072 c
->uniform_data
[i
] == data
) {
1073 return vir_reg(QFILE_UNIF
, i
);
1077 uint32_t uniform
= c
->num_uniforms
++;
1079 if (uniform
>= c
->uniform_array_size
) {
1080 c
->uniform_array_size
= MAX2(MAX2(16, uniform
+ 1),
1081 c
->uniform_array_size
* 2);
1083 c
->uniform_data
= reralloc(c
, c
->uniform_data
,
1085 c
->uniform_array_size
);
1086 c
->uniform_contents
= reralloc(c
, c
->uniform_contents
,
1087 enum quniform_contents
,
1088 c
->uniform_array_size
);
1091 c
->uniform_contents
[uniform
] = contents
;
1092 c
->uniform_data
[uniform
] = data
;
1094 return vir_reg(QFILE_UNIF
, uniform
);
1098 vir_can_set_flags(struct v3d_compile
*c
, struct qinst
*inst
)
1100 if (c
->devinfo
->ver
>= 40 && (v3d_qpu_reads_vpm(&inst
->qpu
) ||
1101 v3d_qpu_uses_sfu(&inst
->qpu
))) {
1105 if (inst
->qpu
.type
!= V3D_QPU_INSTR_TYPE_ALU
||
1106 (inst
->qpu
.alu
.add
.op
== V3D_QPU_A_NOP
&&
1107 inst
->qpu
.alu
.mul
.op
== V3D_QPU_M_NOP
)) {
1115 vir_PF(struct v3d_compile
*c
, struct qreg src
, enum v3d_qpu_pf pf
)
1117 struct qinst
*last_inst
= NULL
;
1119 if (!list_empty(&c
->cur_block
->instructions
)) {
1120 last_inst
= (struct qinst
*)c
->cur_block
->instructions
.prev
;
1122 /* Can't stuff the PF into the last last inst if our cursor
1123 * isn't pointing after it.
1125 struct vir_cursor after_inst
= vir_after_inst(last_inst
);
1126 if (c
->cursor
.mode
!= after_inst
.mode
||
1127 c
->cursor
.link
!= after_inst
.link
)
1131 if (src
.file
!= QFILE_TEMP
||
1132 !c
->defs
[src
.index
] ||
1133 last_inst
!= c
->defs
[src
.index
] ||
1134 !vir_can_set_flags(c
, last_inst
)) {
1135 /* XXX: Make the MOV be the appropriate type */
1136 last_inst
= vir_MOV_dest(c
, vir_reg(QFILE_NULL
, 0), src
);
1139 vir_set_pf(last_inst
, pf
);
1142 #define OPTPASS(func) \
1144 bool stage_progress = func(c); \
1145 if (stage_progress) { \
1147 if (print_opt_debug) { \
1149 "VIR opt pass %2d: %s progress\n", \
1152 /*XXX vir_validate(c);*/ \
1157 vir_optimize(struct v3d_compile
*c
)
1159 bool print_opt_debug
= false;
1163 bool progress
= false;
1165 OPTPASS(vir_opt_copy_propagate
);
1166 OPTPASS(vir_opt_dead_code
);
1167 OPTPASS(vir_opt_small_immediates
);
1177 vir_get_stage_name(struct v3d_compile
*c
)
1179 if (c
->vs_key
&& c
->vs_key
->is_coord
)
1180 return "MESA_SHADER_COORD";
1182 return gl_shader_stage_name(c
->s
->info
.stage
);