Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5563 | serge | 1 | /* |
2 | * Copyright 2009 Corbin Simpson |
||
3 | * Copyright 2009 Marek Olšák |
||
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 | #include "tgsi/tgsi_parse.h" |
||
33 | #include "tgsi/tgsi_ureg.h" |
||
34 | |||
35 | #include "compiler/radeon_compiler.h" |
||
36 | |||
37 | /* Convert info about VS output semantics into r300_shader_semantics. */ |
||
38 | static void r300_shader_read_vs_outputs( |
||
39 | struct r300_context *r300, |
||
40 | struct tgsi_shader_info* info, |
||
41 | struct r300_shader_semantics* vs_outputs) |
||
42 | { |
||
43 | int i; |
||
44 | unsigned index; |
||
45 | |||
46 | r300_shader_semantics_reset(vs_outputs); |
||
47 | |||
48 | for (i = 0; i < info->num_outputs; i++) { |
||
49 | index = info->output_semantic_index[i]; |
||
50 | |||
51 | switch (info->output_semantic_name[i]) { |
||
52 | case TGSI_SEMANTIC_POSITION: |
||
53 | assert(index == 0); |
||
54 | vs_outputs->pos = i; |
||
55 | break; |
||
56 | |||
57 | case TGSI_SEMANTIC_PSIZE: |
||
58 | assert(index == 0); |
||
59 | vs_outputs->psize = i; |
||
60 | break; |
||
61 | |||
62 | case TGSI_SEMANTIC_COLOR: |
||
63 | assert(index < ATTR_COLOR_COUNT); |
||
64 | vs_outputs->color[index] = i; |
||
65 | break; |
||
66 | |||
67 | case TGSI_SEMANTIC_BCOLOR: |
||
68 | assert(index < ATTR_COLOR_COUNT); |
||
69 | vs_outputs->bcolor[index] = i; |
||
70 | break; |
||
71 | |||
72 | case TGSI_SEMANTIC_GENERIC: |
||
73 | assert(index < ATTR_GENERIC_COUNT); |
||
74 | vs_outputs->generic[index] = i; |
||
75 | vs_outputs->num_generic++; |
||
76 | break; |
||
77 | |||
78 | case TGSI_SEMANTIC_FOG: |
||
79 | assert(index == 0); |
||
80 | vs_outputs->fog = i; |
||
81 | break; |
||
82 | |||
83 | case TGSI_SEMANTIC_EDGEFLAG: |
||
84 | assert(index == 0); |
||
85 | fprintf(stderr, "r300 VP: cannot handle edgeflag output.\n"); |
||
86 | break; |
||
87 | |||
88 | case TGSI_SEMANTIC_CLIPVERTEX: |
||
89 | assert(index == 0); |
||
90 | /* Draw does clip vertex for us. */ |
||
91 | if (r300->screen->caps.has_tcl) { |
||
92 | fprintf(stderr, "r300 VP: cannot handle clip vertex output.\n"); |
||
93 | } |
||
94 | break; |
||
95 | |||
96 | default: |
||
97 | fprintf(stderr, "r300 VP: unknown vertex output semantic: %i.\n", |
||
98 | info->output_semantic_name[i]); |
||
99 | } |
||
100 | } |
||
101 | |||
102 | /* WPOS is a straight copy of POSITION and it's always emitted. */ |
||
103 | vs_outputs->wpos = i; |
||
104 | } |
||
105 | |||
106 | static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) |
||
107 | { |
||
108 | struct r300_vertex_shader * vs = c->UserData; |
||
109 | struct r300_shader_semantics* outputs = &vs->outputs; |
||
110 | struct tgsi_shader_info* info = &vs->info; |
||
111 | int i, reg = 0; |
||
112 | boolean any_bcolor_used = outputs->bcolor[0] != ATTR_UNUSED || |
||
113 | outputs->bcolor[1] != ATTR_UNUSED; |
||
114 | |||
115 | /* Fill in the input mapping */ |
||
116 | for (i = 0; i < info->num_inputs; i++) |
||
117 | c->code->inputs[i] = i; |
||
118 | |||
119 | /* Position. */ |
||
120 | if (outputs->pos != ATTR_UNUSED) { |
||
121 | c->code->outputs[outputs->pos] = reg++; |
||
122 | } else { |
||
123 | assert(0); |
||
124 | } |
||
125 | |||
126 | /* Point size. */ |
||
127 | if (outputs->psize != ATTR_UNUSED) { |
||
128 | c->code->outputs[outputs->psize] = reg++; |
||
129 | } |
||
130 | |||
131 | /* If we're writing back facing colors we need to send |
||
132 | * four colors to make front/back face colors selection work. |
||
133 | * If the vertex program doesn't write all 4 colors, lets |
||
134 | * pretend it does by skipping output index reg so the colors |
||
135 | * get written into appropriate output vectors. |
||
136 | */ |
||
137 | |||
138 | /* Colors. */ |
||
139 | for (i = 0; i < ATTR_COLOR_COUNT; i++) { |
||
140 | if (outputs->color[i] != ATTR_UNUSED) { |
||
141 | c->code->outputs[outputs->color[i]] = reg++; |
||
142 | } else if (any_bcolor_used || |
||
143 | outputs->color[1] != ATTR_UNUSED) { |
||
144 | reg++; |
||
145 | } |
||
146 | } |
||
147 | |||
148 | /* Back-face colors. */ |
||
149 | for (i = 0; i < ATTR_COLOR_COUNT; i++) { |
||
150 | if (outputs->bcolor[i] != ATTR_UNUSED) { |
||
151 | c->code->outputs[outputs->bcolor[i]] = reg++; |
||
152 | } else if (any_bcolor_used) { |
||
153 | reg++; |
||
154 | } |
||
155 | } |
||
156 | |||
157 | /* Texture coordinates. */ |
||
158 | for (i = 0; i < ATTR_GENERIC_COUNT; i++) { |
||
159 | if (outputs->generic[i] != ATTR_UNUSED) { |
||
160 | c->code->outputs[outputs->generic[i]] = reg++; |
||
161 | } |
||
162 | } |
||
163 | |||
164 | /* Fog coordinates. */ |
||
165 | if (outputs->fog != ATTR_UNUSED) { |
||
166 | c->code->outputs[outputs->fog] = reg++; |
||
167 | } |
||
168 | |||
169 | /* WPOS. */ |
||
170 | c->code->outputs[outputs->wpos] = reg++; |
||
171 | } |
||
172 | |||
173 | void r300_init_vs_outputs(struct r300_context *r300, |
||
174 | struct r300_vertex_shader *vs) |
||
175 | { |
||
176 | tgsi_scan_shader(vs->state.tokens, &vs->info); |
||
177 | r300_shader_read_vs_outputs(r300, &vs->info, &vs->outputs); |
||
178 | } |
||
179 | |||
180 | static void r300_dummy_vertex_shader( |
||
181 | struct r300_context* r300, |
||
182 | struct r300_vertex_shader* shader) |
||
183 | { |
||
184 | struct ureg_program *ureg; |
||
185 | struct ureg_dst dst; |
||
186 | struct ureg_src imm; |
||
187 | |||
188 | /* Make a simple vertex shader which outputs (0, 0, 0, 1), |
||
189 | * effectively rendering nothing. */ |
||
190 | ureg = ureg_create(TGSI_PROCESSOR_VERTEX); |
||
191 | dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); |
||
192 | imm = ureg_imm4f(ureg, 0, 0, 0, 1); |
||
193 | |||
194 | ureg_MOV(ureg, dst, imm); |
||
195 | ureg_END(ureg); |
||
196 | |||
197 | shader->state.tokens = tgsi_dup_tokens(ureg_finalize(ureg)); |
||
198 | ureg_destroy(ureg); |
||
199 | |||
200 | shader->dummy = TRUE; |
||
201 | r300_init_vs_outputs(r300, shader); |
||
202 | r300_translate_vertex_shader(r300, shader); |
||
203 | } |
||
204 | |||
205 | void r300_translate_vertex_shader(struct r300_context *r300, |
||
206 | struct r300_vertex_shader *vs) |
||
207 | { |
||
208 | struct r300_vertex_program_compiler compiler; |
||
209 | struct tgsi_to_rc ttr; |
||
210 | unsigned i; |
||
211 | |||
212 | /* Setup the compiler */ |
||
213 | memset(&compiler, 0, sizeof(compiler)); |
||
214 | rc_init(&compiler.Base, NULL); |
||
215 | |||
216 | DBG_ON(r300, DBG_VP) ? compiler.Base.Debug |= RC_DBG_LOG : 0; |
||
217 | DBG_ON(r300, DBG_P_STAT) ? compiler.Base.Debug |= RC_DBG_STATS : 0; |
||
218 | compiler.code = &vs->code; |
||
219 | compiler.UserData = vs; |
||
220 | compiler.Base.is_r500 = r300->screen->caps.is_r500; |
||
221 | compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT); |
||
222 | compiler.Base.has_half_swizzles = FALSE; |
||
223 | compiler.Base.has_presub = FALSE; |
||
224 | compiler.Base.has_omod = FALSE; |
||
225 | compiler.Base.max_temp_regs = 32; |
||
226 | compiler.Base.max_constants = 256; |
||
227 | compiler.Base.max_alu_insts = r300->screen->caps.is_r500 ? 1024 : 256; |
||
228 | |||
229 | if (compiler.Base.Debug & RC_DBG_LOG) { |
||
230 | DBG(r300, DBG_VP, "r300: Initial vertex program\n"); |
||
231 | tgsi_dump(vs->state.tokens, 0); |
||
232 | } |
||
233 | |||
234 | /* Translate TGSI to our internal representation */ |
||
235 | ttr.compiler = &compiler.Base; |
||
236 | ttr.info = &vs->info; |
||
237 | ttr.use_half_swizzles = FALSE; |
||
238 | |||
239 | r300_tgsi_to_rc(&ttr, vs->state.tokens); |
||
240 | |||
241 | if (ttr.error) { |
||
242 | fprintf(stderr, "r300 VP: Cannot translate a shader. " |
||
243 | "Using a dummy shader instead.\n"); |
||
244 | r300_dummy_vertex_shader(r300, vs); |
||
245 | return; |
||
246 | } |
||
247 | |||
248 | if (compiler.Base.Program.Constants.Count > 200) { |
||
249 | compiler.Base.remove_unused_constants = TRUE; |
||
250 | } |
||
251 | |||
252 | compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs + 1)); |
||
253 | compiler.SetHwInputOutput = &set_vertex_inputs_outputs; |
||
254 | |||
255 | /* Insert the WPOS output. */ |
||
256 | rc_copy_output(&compiler.Base, 0, vs->outputs.wpos); |
||
257 | |||
258 | /* Invoke the compiler */ |
||
259 | r3xx_compile_vertex_program(&compiler); |
||
260 | if (compiler.Base.Error) { |
||
261 | fprintf(stderr, "r300 VP: Compiler error:\n%sUsing a dummy shader" |
||
262 | " instead.\n", compiler.Base.ErrorMsg); |
||
263 | |||
264 | if (vs->dummy) { |
||
265 | fprintf(stderr, "r300 VP: Cannot compile the dummy shader! " |
||
266 | "Giving up...\n"); |
||
267 | abort(); |
||
268 | } |
||
269 | |||
270 | rc_destroy(&compiler.Base); |
||
271 | r300_dummy_vertex_shader(r300, vs); |
||
272 | return; |
||
273 | } |
||
274 | |||
275 | /* Initialize numbers of constants for each type. */ |
||
276 | vs->externals_count = 0; |
||
277 | for (i = 0; |
||
278 | i < vs->code.constants.Count && |
||
279 | vs->code.constants.Constants[i].Type == RC_CONSTANT_EXTERNAL; i++) { |
||
280 | vs->externals_count = i+1; |
||
281 | } |
||
282 | for (; i < vs->code.constants.Count; i++) { |
||
283 | assert(vs->code.constants.Constants[i].Type == RC_CONSTANT_IMMEDIATE); |
||
284 | } |
||
285 | vs->immediates_count = vs->code.constants.Count - vs->externals_count; |
||
286 | |||
287 | /* And, finally... */ |
||
288 | rc_destroy(&compiler.Base); |
||
289 | }>>><>>>>>>>>> |