• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
3  *
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  * on the rights to use, copy, modify, merge, publish, distribute, sub
8  * license, and/or sell copies of the Software, and to permit persons to whom
9  * the Software is furnished to do so, subject to the following conditions:
10  *
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
13  * Software.
14  *
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 NON-INFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22 
23 #include "radeon_compiler.h"
24 
25 #include <stdio.h>
26 
27 #include "radeon_compiler_util.h"
28 #include "radeon_dataflow.h"
29 #include "radeon_program_alu.h"
30 #include "radeon_program_tex.h"
31 #include "radeon_rename_regs.h"
32 #include "radeon_remove_constants.h"
33 #include "radeon_variable.h"
34 #include "radeon_list.h"
35 #include "r300_fragprog.h"
36 #include "r300_fragprog_swizzle.h"
37 #include "r500_fragprog.h"
38 
39 
rc_rewrite_depth_out(struct radeon_compiler * cc,void * user)40 static void rc_rewrite_depth_out(struct radeon_compiler *cc, void *user)
41 {
42 	struct r300_fragment_program_compiler *c = (struct r300_fragment_program_compiler*)cc;
43 	struct rc_instruction *rci;
44 
45 	for (rci = c->Base.Program.Instructions.Next; rci != &c->Base.Program.Instructions; rci = rci->Next) {
46 		struct rc_sub_instruction * inst = &rci->U.I;
47 		unsigned i;
48 		const struct rc_opcode_info *info = rc_get_opcode_info(inst->Opcode);
49 
50 		if (inst->DstReg.File != RC_FILE_OUTPUT || inst->DstReg.Index != c->OutputDepth)
51 			continue;
52 
53 		if (inst->DstReg.WriteMask & RC_MASK_Z) {
54 			inst->DstReg.WriteMask = RC_MASK_W;
55 		} else {
56 			inst->DstReg.WriteMask = 0;
57 			continue;
58 		}
59 
60 		if (!info->IsComponentwise) {
61 			continue;
62 		}
63 
64 		for (i = 0; i < info->NumSrcRegs; i++) {
65 			inst->SrcReg[i] = lmul_swizzle(RC_SWIZZLE_ZZZZ, inst->SrcReg[i]);
66 		}
67 	}
68 }
69 
70 /**
71  * This function will try to convert rgb instructions into alpha instructions
72  * and vice versa. While this is already attempted during the pair scheduling,
73  * it is much simpler to do it before pair conversion, so do it here at least for
74  * the simple cases.
75  *
76  * Currently only math opcodes writing to rgb (and with no friends) are
77  * converted to alpha.
78  *
79  * This function assumes all the instructions are still of type
80  * RC_INSTRUCTION_NORMAL, the conversion is much simpler.
81  *
82  * Beware that this needs to be also called before doing presubtract, because
83  * rc_get_variables can't get properly readers for normal instructions if presubtract
84  * is present (it works fine for pair instructions).
85  */
rc_convert_rgb_alpha(struct radeon_compiler * c,void * user)86 static void rc_convert_rgb_alpha(struct radeon_compiler *c, void *user)
87 {
88 	struct rc_list * variables;
89 	struct rc_list * var_ptr;
90 
91 	variables = rc_get_variables(c);
92 
93 	for (var_ptr = variables; var_ptr; var_ptr = var_ptr->Next) {
94 		struct rc_variable * var = var_ptr->Item;
95 
96 		if (var->Inst->U.I.DstReg.File != RC_FILE_TEMPORARY) {
97 			continue;
98 		}
99 
100 		/* Only rewrite scalar opcodes that are used separatelly for now. */
101 		if (var->Friend)
102 			continue;
103 
104 		const struct rc_opcode_info * opcode = rc_get_opcode_info(var->Inst->U.I.Opcode);
105 		if (opcode->IsStandardScalar && var->Dst.WriteMask != RC_MASK_W) {
106 			unsigned index = rc_find_free_temporary(c);
107 			rc_variable_change_dst(var, index, RC_MASK_W);
108 		}
109 	}
110 }
111 
r3xx_compile_fragment_program(struct r300_fragment_program_compiler * c)112 void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
113 {
114 	int is_r500 = c->Base.is_r500;
115 	int opt = !c->Base.disable_optimizations;
116 	int alpha2one = c->state.alpha_to_one;
117 
118 	/* Lists of instruction transformations. */
119 	struct radeon_program_transformation force_alpha_to_one[] = {
120 		{ &rc_force_output_alpha_to_one, c },
121 		{ NULL, NULL }
122 	};
123 
124 	struct radeon_program_transformation rewrite_tex[] = {
125 		{ &radeonTransformTEX, c },
126 		{ NULL, NULL }
127 	};
128 
129 	struct radeon_program_transformation native_rewrite_r500[] = {
130 		{ &radeonTransformALU, NULL },
131 		{ &radeonTransformDeriv, NULL },
132 		{ NULL, NULL }
133 	};
134 
135 	struct radeon_program_transformation native_rewrite_r300[] = {
136 		{ &radeonTransformALU, NULL },
137 		{ &radeonStubDeriv, NULL },
138 		{ NULL, NULL }
139 	};
140 
141 	/* List of compiler passes. */
142 	struct radeon_compiler_pass fs_list[] = {
143 		/* NAME				DUMP PREDICATE	FUNCTION			PARAM */
144 		{"rewrite depth out",		1, 1,		rc_rewrite_depth_out,		NULL},
145 		{"force alpha to one",		1, alpha2one,	rc_local_transform,		force_alpha_to_one},
146 		{"transform TEX",		1, 1,		rc_local_transform,		rewrite_tex},
147 		{"transform IF",		1, is_r500,	r500_transform_IF,		NULL},
148 		{"native rewrite",		1, is_r500,	rc_local_transform,		native_rewrite_r500},
149 		{"native rewrite",		1, !is_r500,	rc_local_transform,		native_rewrite_r300},
150 		{"deadcode",			1, opt,		rc_dataflow_deadcode,		NULL},
151 		{"convert rgb<->alpha",		1, opt,		rc_convert_rgb_alpha,		NULL},
152 		{"register rename",		1, !is_r500 || opt,		rc_rename_regs,			NULL},
153 		{"dataflow optimize",		1, opt,		rc_optimize,			NULL},
154 		{"inline literals",		1, is_r500 && opt,		rc_inline_literals,			NULL},
155 		{"dataflow swizzles",		1, 1,		rc_dataflow_swizzles,		NULL},
156 		{"dead constants",		1, 1,		rc_remove_unused_constants,	&c->code->constants_remap_table},
157 		{"pair translate",		1, 1,		rc_pair_translate,		NULL},
158 		{"pair scheduling",		1, 1,		rc_pair_schedule,		&opt},
159 		{"dead sources",		1, 1,		rc_pair_remove_dead_sources, NULL},
160 		{"register allocation",		1, 1,		rc_pair_regalloc,		&opt},
161 		{"final code validation",	0, 1,		rc_validate_final_shader,	NULL},
162 		{"machine code generation",	0, is_r500,	r500BuildFragmentProgramHwCode,	NULL},
163 		{"machine code generation",	0, !is_r500,	r300BuildFragmentProgramHwCode,	NULL},
164 		{"dump machine code",		0, is_r500  && (c->Base.Debug & RC_DBG_LOG), r500FragmentProgramDump, NULL},
165 		{"dump machine code",		0, !is_r500 && (c->Base.Debug & RC_DBG_LOG), r300FragmentProgramDump, NULL},
166 		{NULL, 0, 0, NULL, NULL}
167 	};
168 
169 	c->Base.type = RC_FRAGMENT_PROGRAM;
170 	c->Base.SwizzleCaps = c->Base.is_r500 ? &r500_swizzle_caps : &r300_swizzle_caps;
171 
172 	rc_run_compiler(&c->Base, fs_list);
173 
174 	rc_constants_copy(&c->code->constants, &c->Base.Program.Constants);
175 }
176