1 /* 2 * Copyright 2009 Corbin Simpson <MostAwesomeDude (at) gmail.com> 3 * Copyright 2009 Marek Olk <maraeo (at) 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 #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(PIPE_SHADER_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 } 290