1 /*
2 * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
3 * Copyright 2009 Marek Olšák <maraeo@gmail.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23
24 #include "r300_vs.h"
25
26 #include "r300_context.h"
27 #include "r300_screen.h"
28 #include "r300_tgsi_to_rc.h"
29 #include "r300_reg.h"
30
31 #include "tgsi/tgsi_dump.h"
32
33 #include "compiler/radeon_compiler.h"
34
35 /* Convert info about VS output semantics into r300_shader_semantics. */
r300_shader_read_vs_outputs(struct r300_context * r300,struct tgsi_shader_info * info,struct r300_shader_semantics * vs_outputs)36 static void r300_shader_read_vs_outputs(
37 struct r300_context *r300,
38 struct tgsi_shader_info* info,
39 struct r300_shader_semantics* vs_outputs)
40 {
41 int i;
42 unsigned index;
43
44 r300_shader_semantics_reset(vs_outputs);
45
46 for (i = 0; i < info->num_outputs; i++) {
47 index = info->output_semantic_index[i];
48
49 switch (info->output_semantic_name[i]) {
50 case TGSI_SEMANTIC_POSITION:
51 assert(index == 0);
52 vs_outputs->pos = i;
53 break;
54
55 case TGSI_SEMANTIC_PSIZE:
56 assert(index == 0);
57 vs_outputs->psize = i;
58 break;
59
60 case TGSI_SEMANTIC_COLOR:
61 assert(index < ATTR_COLOR_COUNT);
62 vs_outputs->color[index] = i;
63 break;
64
65 case TGSI_SEMANTIC_BCOLOR:
66 assert(index < ATTR_COLOR_COUNT);
67 vs_outputs->bcolor[index] = i;
68 break;
69
70 case TGSI_SEMANTIC_TEXCOORD:
71 assert(index < ATTR_TEXCOORD_COUNT);
72 vs_outputs->texcoord[index] = i;
73 vs_outputs->num_texcoord++;
74 break;
75
76 case TGSI_SEMANTIC_GENERIC:
77 assert(index < ATTR_GENERIC_COUNT);
78 vs_outputs->generic[index] = i;
79 vs_outputs->num_generic++;
80 break;
81
82 case TGSI_SEMANTIC_FOG:
83 assert(index == 0);
84 vs_outputs->fog = i;
85 break;
86
87 case TGSI_SEMANTIC_EDGEFLAG:
88 assert(index == 0);
89 fprintf(stderr, "r300 VP: cannot handle edgeflag output.\n");
90 break;
91
92 case TGSI_SEMANTIC_CLIPVERTEX:
93 assert(index == 0);
94 /* Draw does clip vertex for us. */
95 if (r300->screen->caps.has_tcl) {
96 fprintf(stderr, "r300 VP: cannot handle clip vertex output.\n");
97 }
98 break;
99
100 default:
101 fprintf(stderr, "r300 VP: unknown vertex output semantic: %i.\n",
102 info->output_semantic_name[i]);
103 }
104 }
105
106 /* WPOS is a straight copy of POSITION */
107 vs_outputs->wpos = i;
108 }
109
set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)110 static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
111 {
112 struct r300_vertex_shader_code * vs = c->UserData;
113 struct r300_shader_semantics* outputs = &vs->outputs;
114 struct tgsi_shader_info* info = &vs->info;
115 int i, reg = 0;
116 bool any_bcolor_used = outputs->bcolor[0] != ATTR_UNUSED ||
117 outputs->bcolor[1] != ATTR_UNUSED;
118
119 /* Fill in the input mapping */
120 for (i = 0; i < info->num_inputs; i++)
121 c->code->inputs[i] = i;
122
123 /* Position. */
124 if (outputs->pos != ATTR_UNUSED) {
125 c->code->outputs[outputs->pos] = reg++;
126 } else {
127 assert(0);
128 }
129
130 /* Point size. */
131 if (outputs->psize != ATTR_UNUSED) {
132 c->code->outputs[outputs->psize] = reg++;
133 }
134
135 /* If we're writing back facing colors we need to send
136 * four colors to make front/back face colors selection work.
137 * If the vertex program doesn't write all 4 colors, lets
138 * pretend it does by skipping output index reg so the colors
139 * get written into appropriate output vectors.
140 */
141
142 /* Colors. */
143 for (i = 0; i < ATTR_COLOR_COUNT; i++) {
144 if (outputs->color[i] != ATTR_UNUSED) {
145 c->code->outputs[outputs->color[i]] = reg++;
146 } else if (any_bcolor_used ||
147 outputs->color[1] != ATTR_UNUSED) {
148 reg++;
149 }
150 }
151
152 /* Back-face colors. */
153 for (i = 0; i < ATTR_COLOR_COUNT; i++) {
154 if (outputs->bcolor[i] != ATTR_UNUSED) {
155 c->code->outputs[outputs->bcolor[i]] = reg++;
156 } else if (any_bcolor_used) {
157 reg++;
158 }
159 }
160
161 /* Generics. */
162 for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
163 if (outputs->generic[i] != ATTR_UNUSED) {
164 c->code->outputs[outputs->generic[i]] = reg++;
165 }
166 }
167
168 /* Texture coordinates. */
169 for (i = 0; i < ATTR_TEXCOORD_COUNT; i++) {
170 if (outputs->texcoord[i] != ATTR_UNUSED) {
171 c->code->outputs[outputs->texcoord[i]] = reg++;
172 }
173 }
174
175 /* Fog coordinates. */
176 if (outputs->fog != ATTR_UNUSED) {
177 c->code->outputs[outputs->fog] = reg++;
178 }
179
180 /* WPOS. */
181 if (vs->wpos)
182 c->code->outputs[outputs->wpos] = reg++;
183 }
184
r300_init_vs_outputs(struct r300_context * r300,struct r300_vertex_shader * vs)185 void r300_init_vs_outputs(struct r300_context *r300,
186 struct r300_vertex_shader *vs)
187 {
188 tgsi_scan_shader(vs->state.tokens, &vs->shader->info);
189 r300_shader_read_vs_outputs(r300, &vs->shader->info, &vs->shader->outputs);
190 }
191
r300_translate_vertex_shader(struct r300_context * r300,struct r300_vertex_shader * shader)192 void r300_translate_vertex_shader(struct r300_context *r300,
193 struct r300_vertex_shader *shader)
194 {
195 struct r300_vertex_program_compiler compiler;
196 struct tgsi_to_rc ttr;
197 unsigned i;
198 struct r300_vertex_shader_code *vs = shader->shader;
199
200 r300_init_vs_outputs(r300, shader);
201
202 /* Nothing to do if the shader does not write gl_Position. */
203 if (vs->outputs.pos == ATTR_UNUSED) {
204 vs->dummy = true;
205 return;
206 }
207
208 /* Setup the compiler */
209 memset(&compiler, 0, sizeof(compiler));
210 rc_init(&compiler.Base, &r300->vs_regalloc_state);
211
212 DBG_ON(r300, DBG_VP) ? compiler.Base.Debug |= RC_DBG_LOG : 0;
213 compiler.code = &vs->code;
214 compiler.UserData = vs;
215 compiler.Base.debug = &r300->context.debug;
216 compiler.Base.is_r500 = r300->screen->caps.is_r500;
217 compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT);
218 compiler.Base.has_half_swizzles = false;
219 compiler.Base.has_presub = false;
220 compiler.Base.has_omod = false;
221 compiler.Base.max_temp_regs = 32;
222 compiler.Base.max_constants = 256;
223 compiler.Base.max_alu_insts = r300->screen->caps.is_r500 ? 1024 : 256;
224
225 if (compiler.Base.Debug & RC_DBG_LOG) {
226 DBG(r300, DBG_VP, "r300: Initial vertex program\n");
227 tgsi_dump(shader->state.tokens, 0);
228 }
229
230 /* Translate TGSI to our internal representation */
231 ttr.compiler = &compiler.Base;
232 ttr.info = &vs->info;
233
234 r300_tgsi_to_rc(&ttr, shader->state.tokens);
235
236 if (ttr.error) {
237 fprintf(stderr, "r300 VP: Cannot translate a shader. "
238 "Corresponding draws will be skipped.\n");
239 vs->dummy = true;
240 return;
241 }
242
243 if (compiler.Base.Program.Constants.Count > 200) {
244 compiler.Base.remove_unused_constants = true;
245 }
246
247 compiler.RequiredOutputs = ~(~0U << (vs->info.num_outputs + (vs->wpos ? 1 : 0)));
248 compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
249
250 /* Insert the WPOS output. */
251 if (vs->wpos)
252 rc_copy_output(&compiler.Base, vs->outputs.pos, vs->outputs.wpos);
253
254 /* Invoke the compiler */
255 r3xx_compile_vertex_program(&compiler);
256 if (compiler.Base.Error) {
257 fprintf(stderr, "r300 VP: Compiler error:\n%sCorresponding draws will be"
258 " skipped.\n", compiler.Base.ErrorMsg);
259
260 rc_destroy(&compiler.Base);
261 vs->dummy = true;
262 return;
263 }
264
265 /* Initialize numbers of constants for each type. */
266 vs->externals_count = 0;
267 for (i = 0;
268 i < vs->code.constants.Count &&
269 vs->code.constants.Constants[i].Type == RC_CONSTANT_EXTERNAL; i++) {
270 vs->externals_count = i+1;
271 }
272 for (; i < vs->code.constants.Count; i++) {
273 assert(vs->code.constants.Constants[i].Type == RC_CONSTANT_IMMEDIATE);
274 }
275 vs->immediates_count = vs->code.constants.Count - vs->externals_count;
276
277 /* And, finally... */
278 rc_destroy(&compiler.Base);
279 }
280