xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r300/compiler/r3xx_fragprog.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2009 Nicolai Hähnle <[email protected]>
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "radeon_compiler.h"
7 
8 #include <stdio.h>
9 
10 #include "radeon_compiler_util.h"
11 #include "radeon_dataflow.h"
12 #include "radeon_program_alu.h"
13 #include "radeon_program_tex.h"
14 #include "radeon_rename_regs.h"
15 #include "radeon_remove_constants.h"
16 #include "radeon_variable.h"
17 #include "radeon_list.h"
18 #include "r300_fragprog.h"
19 #include "r300_fragprog_swizzle.h"
20 #include "r500_fragprog.h"
21 
22 
rc_rewrite_depth_out(struct radeon_compiler * cc,void * user)23 static void rc_rewrite_depth_out(struct radeon_compiler *cc, void *user)
24 {
25 	struct r300_fragment_program_compiler *c = (struct r300_fragment_program_compiler*)cc;
26 	struct rc_instruction *rci;
27 
28 	for (rci = c->Base.Program.Instructions.Next; rci != &c->Base.Program.Instructions; rci = rci->Next) {
29 		struct rc_sub_instruction * inst = &rci->U.I;
30 		unsigned i;
31 		const struct rc_opcode_info *info = rc_get_opcode_info(inst->Opcode);
32 
33 		if (inst->DstReg.File != RC_FILE_OUTPUT || inst->DstReg.Index != c->OutputDepth)
34 			continue;
35 
36 		if (inst->DstReg.WriteMask & RC_MASK_Z) {
37 			inst->DstReg.WriteMask = RC_MASK_W;
38 		} else {
39 			inst->DstReg.WriteMask = 0;
40 			continue;
41 		}
42 
43 		if (!info->IsComponentwise) {
44 			continue;
45 		}
46 
47 		for (i = 0; i < info->NumSrcRegs; i++) {
48 			inst->SrcReg[i] = lmul_swizzle(RC_SWIZZLE_ZZZZ, inst->SrcReg[i]);
49 		}
50 	}
51 }
52 
53 /**
54  * This function will try to convert rgb instructions into alpha instructions
55  * and vice versa. While this is already attempted during the pair scheduling,
56  * it is much simpler to do it before pair conversion, so do it here at least for
57  * the simple cases.
58  *
59  * Currently only math opcodes writing to rgb (and with no friends) are
60  * converted to alpha.
61  *
62  * This function assumes all the instructions are still of type
63  * RC_INSTRUCTION_NORMAL, the conversion is much simpler.
64  *
65  * Beware that this needs to be also called before doing presubtract, because
66  * rc_get_variables can't get properly readers for normal instructions if presubtract
67  * is present (it works fine for pair instructions).
68  */
rc_convert_rgb_alpha(struct radeon_compiler * c,void * user)69 static void rc_convert_rgb_alpha(struct radeon_compiler *c, void *user)
70 {
71 	struct rc_list * variables;
72 	struct rc_list * var_ptr;
73 
74 	variables = rc_get_variables(c);
75 
76 	for (var_ptr = variables; var_ptr; var_ptr = var_ptr->Next) {
77 		struct rc_variable * var = var_ptr->Item;
78 
79 		if (var->Inst->U.I.DstReg.File != RC_FILE_TEMPORARY) {
80 			continue;
81 		}
82 
83 		/* Only rewrite scalar opcodes that are used separately for now. */
84 		if (var->Friend)
85 			continue;
86 
87 		const struct rc_opcode_info * opcode = rc_get_opcode_info(var->Inst->U.I.Opcode);
88 		if (opcode->IsStandardScalar && var->Dst.WriteMask != RC_MASK_W) {
89 			unsigned index = rc_find_free_temporary(c);
90 			rc_variable_change_dst(var, index, RC_MASK_W);
91 		}
92 	}
93 }
94 
r3xx_compile_fragment_program(struct r300_fragment_program_compiler * c)95 void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
96 {
97 	int is_r500 = c->Base.is_r500;
98 	int opt = !c->Base.disable_optimizations;
99 	int alpha2one = c->state.alpha_to_one;
100 
101 	/* Lists of instruction transformations. */
102 	struct radeon_program_transformation force_alpha_to_one[] = {
103 		{ &rc_force_output_alpha_to_one, c },
104 		{ NULL, NULL }
105 	};
106 
107 	struct radeon_program_transformation rewrite_tex[] = {
108 		{ &radeonTransformTEX, c },
109 		{ NULL, NULL }
110 	};
111 
112 	struct radeon_program_transformation native_rewrite_r500[] = {
113 		{ &radeonTransformALU, NULL },
114 		{ &radeonTransformDeriv, NULL },
115 		{ NULL, NULL }
116 	};
117 
118 	struct radeon_program_transformation native_rewrite_r300[] = {
119 		{ &radeonTransformALU, NULL },
120 		{ &radeonStubDeriv, NULL },
121 		{ NULL, NULL }
122 	};
123 
124 	struct radeon_program_transformation opt_presubtract[] = {
125                 { &rc_opt_presubtract, NULL },
126                 { NULL, NULL }
127         };
128 
129 
130 	/* List of compiler passes. */
131 	struct radeon_compiler_pass fs_list[] = {
132 		/* NAME				DUMP PREDICATE	FUNCTION			PARAM */
133 		{"rewrite depth out",		1, 1,		rc_rewrite_depth_out,		NULL},
134 		{"force alpha to one",		1, alpha2one,	rc_local_transform,		force_alpha_to_one},
135 		{"transform TEX",		1, 1,		rc_local_transform,		rewrite_tex},
136 		{"transform IF",		1, is_r500,	r500_transform_IF,		NULL},
137 		{"native rewrite",		1, is_r500,	rc_local_transform,		native_rewrite_r500},
138 		{"native rewrite",		1, !is_r500,	rc_local_transform,		native_rewrite_r300},
139 		{"deadcode",			1, opt,		rc_dataflow_deadcode,		NULL},
140 		{"convert rgb<->alpha",		1, opt,		rc_convert_rgb_alpha,		NULL},
141 		{"register rename",		1, !is_r500 || opt,		rc_rename_regs,			NULL},
142 		{"dataflow optimize",		1, opt,		rc_optimize,			NULL},
143 		{"inline literals",		1, is_r500 && opt,		rc_inline_literals,			NULL},
144 		{"dataflow swizzles",		1, 1,		rc_dataflow_swizzles,		NULL},
145 		{"dead constants",		1, 1,		rc_remove_unused_constants,	&c->code->constants_remap_table},
146 		{"dataflow presubtract",	1, opt,		rc_local_transform,		opt_presubtract},
147 		{"pair translate",		1, 1,		rc_pair_translate,		NULL},
148 		{"pair scheduling",		1, 1,		rc_pair_schedule,		&opt},
149 		{"dead sources",		1, 1,		rc_pair_remove_dead_sources, NULL},
150 		{"register allocation",		1, 1,		rc_pair_regalloc,		&opt},
151 		{"final code validation",	0, 1,		rc_validate_final_shader,	NULL},
152 		{"machine code generation",	0, is_r500,	r500BuildFragmentProgramHwCode,	NULL},
153 		{"machine code generation",	0, !is_r500,	r300BuildFragmentProgramHwCode,	NULL},
154 		{"dump machine code",		0, is_r500  && (c->Base.Debug & RC_DBG_LOG), r500FragmentProgramDump, NULL},
155 		{"dump machine code",		0, !is_r500 && (c->Base.Debug & RC_DBG_LOG), r300FragmentProgramDump, NULL},
156 		{NULL, 0, 0, NULL, NULL}
157 	};
158 
159 	c->Base.type = RC_FRAGMENT_PROGRAM;
160 	c->Base.SwizzleCaps = c->Base.is_r500 ? &r500_swizzle_caps : &r300_swizzle_caps;
161 
162 	rc_run_compiler(&c->Base, fs_list);
163 
164 	rc_constants_copy(&c->code->constants, &c->Base.Program.Constants);
165 }
166