• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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