r300_vs.c revision cdc920a0
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#include "r300_fs.h" 26 27#include "r300_context.h" 28#include "r300_screen.h" 29#include "r300_tgsi_to_rc.h" 30#include "r300_reg.h" 31 32#include "tgsi/tgsi_dump.h" 33#include "tgsi/tgsi_parse.h" 34 35#include "radeon_compiler.h" 36 37#include "util/u_math.h" 38 39/* Convert info about VS output semantics into r300_shader_semantics. */ 40static void r300_shader_read_vs_outputs( 41 struct tgsi_shader_info* info, 42 struct r300_shader_semantics* vs_outputs) 43{ 44 int i; 45 unsigned index; 46 47 r300_shader_semantics_reset(vs_outputs); 48 49 for (i = 0; i < info->num_outputs; i++) { 50 index = info->output_semantic_index[i]; 51 52 switch (info->output_semantic_name[i]) { 53 case TGSI_SEMANTIC_POSITION: 54 assert(index == 0); 55 vs_outputs->pos = i; 56 break; 57 58 case TGSI_SEMANTIC_PSIZE: 59 assert(index == 0); 60 vs_outputs->psize = i; 61 break; 62 63 case TGSI_SEMANTIC_COLOR: 64 assert(index < ATTR_COLOR_COUNT); 65 vs_outputs->color[index] = i; 66 break; 67 68 case TGSI_SEMANTIC_BCOLOR: 69 assert(index < ATTR_COLOR_COUNT); 70 vs_outputs->bcolor[index] = i; 71 break; 72 73 case TGSI_SEMANTIC_GENERIC: 74 assert(index < ATTR_GENERIC_COUNT); 75 vs_outputs->generic[index] = i; 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 assert(0); 87 break; 88 default: 89 assert(0); 90 } 91 } 92} 93 94static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs) 95{ 96 struct r300_shader_semantics* vs_outputs = &vs->outputs; 97 uint32_t* hwfmt = vs->hwfmt; 98 int i, gen_count; 99 boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || 100 vs_outputs->bcolor[1] != ATTR_UNUSED; 101 102 /* Do the actual vertex_info setup. 103 * 104 * vertex_info has four uints of hardware-specific data in it. 105 * vinfo.hwfmt[0] is R300_VAP_VTX_STATE_CNTL 106 * vinfo.hwfmt[1] is R300_VAP_VSM_VTX_ASSM 107 * vinfo.hwfmt[2] is R300_VAP_OUTPUT_VTX_FMT_0 108 * vinfo.hwfmt[3] is R300_VAP_OUTPUT_VTX_FMT_1 */ 109 110 hwfmt[0] = 0x5555; /* XXX this is classic Mesa bonghits */ 111 112 /* Position. */ 113 if (vs_outputs->pos != ATTR_UNUSED) { 114 hwfmt[1] |= R300_INPUT_CNTL_POS; 115 hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; 116 } else { 117 assert(0); 118 } 119 120 /* Point size. */ 121 if (vs_outputs->psize != ATTR_UNUSED) { 122 hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; 123 } 124 125 /* Colors. */ 126 for (i = 0; i < ATTR_COLOR_COUNT; i++) { 127 if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || 128 vs_outputs->color[1] != ATTR_UNUSED) { 129 hwfmt[1] |= R300_INPUT_CNTL_COLOR; 130 hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i; 131 } 132 } 133 134 /* Back-face colors. */ 135 if (any_bcolor_used) { 136 for (i = 0; i < ATTR_COLOR_COUNT; i++) { 137 hwfmt[1] |= R300_INPUT_CNTL_COLOR; 138 hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i); 139 } 140 } 141 142 /* Texture coordinates. */ 143 gen_count = 0; 144 for (i = 0; i < ATTR_GENERIC_COUNT; i++) { 145 if (vs_outputs->generic[i] != ATTR_UNUSED) { 146 hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count); 147 hwfmt[3] |= (4 << (3 * gen_count)); 148 gen_count++; 149 } 150 } 151 152 /* Fog coordinates. */ 153 if (vs_outputs->fog != ATTR_UNUSED) { 154 hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count); 155 hwfmt[3] |= (4 << (3 * gen_count)); 156 gen_count++; 157 } 158 159 /* XXX magic */ 160 assert(gen_count <= 8); 161 162 /* WPOS. */ 163 vs->wpos_tex_output = gen_count; 164} 165 166/* Sets up stream mapping to equivalent VS outputs if TCL is bypassed 167 * or isn't present. */ 168static void r300_stream_locations_notcl( 169 struct r300_shader_semantics* vs_outputs, 170 int* stream_loc) 171{ 172 int i, tabi = 0, gen_count; 173 boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || 174 vs_outputs->bcolor[1] != ATTR_UNUSED; 175 176 /* Position. */ 177 stream_loc[tabi++] = 0; 178 179 /* Point size. */ 180 if (vs_outputs->psize != ATTR_UNUSED) { 181 stream_loc[tabi++] = 1; 182 } 183 184 /* Colors. */ 185 for (i = 0; i < ATTR_COLOR_COUNT; i++) { 186 if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || 187 vs_outputs->color[1] != ATTR_UNUSED) { 188 stream_loc[tabi++] = 2 + i; 189 } 190 } 191 192 /* Back-face colors. */ 193 if (any_bcolor_used) { 194 for (i = 0; i < ATTR_COLOR_COUNT; i++) { 195 stream_loc[tabi++] = 4 + i; 196 } 197 } 198 199 /* Texture coordinates. */ 200 gen_count = 0; 201 for (i = 0; i < ATTR_GENERIC_COUNT; i++) { 202 if (vs_outputs->generic[i] != ATTR_UNUSED) { 203 assert(tabi < 16); 204 stream_loc[tabi++] = 6 + gen_count; 205 gen_count++; 206 } 207 } 208 209 /* Fog coordinates. */ 210 if (vs_outputs->fog != ATTR_UNUSED) { 211 assert(tabi < 16); 212 stream_loc[tabi++] = 6 + gen_count; 213 gen_count++; 214 } 215 216 /* WPOS. */ 217 if (vs_outputs->wpos != ATTR_UNUSED) { 218 assert(tabi < 16); 219 stream_loc[tabi++] = 6 + gen_count; 220 gen_count++; 221 } 222 223 for (; tabi < 16;) { 224 stream_loc[tabi++] = -1; 225 } 226} 227 228static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) 229{ 230 struct r300_vertex_shader * vs = c->UserData; 231 struct r300_shader_semantics* outputs = &vs->outputs; 232 struct tgsi_shader_info* info = &vs->info; 233 int i, reg = 0; 234 boolean any_bcolor_used = outputs->bcolor[0] != ATTR_UNUSED || 235 outputs->bcolor[1] != ATTR_UNUSED; 236 237 /* Fill in the input mapping */ 238 for (i = 0; i < info->num_inputs; i++) 239 c->code->inputs[i] = i; 240 241 /* Position. */ 242 if (outputs->pos != ATTR_UNUSED) { 243 c->code->outputs[outputs->pos] = reg++; 244 } else { 245 assert(0); 246 } 247 248 /* Point size. */ 249 if (outputs->psize != ATTR_UNUSED) { 250 c->code->outputs[outputs->psize] = reg++; 251 } 252 253 /* If we're writing back facing colors we need to send 254 * four colors to make front/back face colors selection work. 255 * If the vertex program doesn't write all 4 colors, lets 256 * pretend it does by skipping output index reg so the colors 257 * get written into appropriate output vectors. 258 */ 259 260 /* Colors. */ 261 for (i = 0; i < ATTR_COLOR_COUNT; i++) { 262 if (outputs->color[i] != ATTR_UNUSED) { 263 c->code->outputs[outputs->color[i]] = reg++; 264 } else if (any_bcolor_used || 265 outputs->color[1] != ATTR_UNUSED) { 266 reg++; 267 } 268 } 269 270 /* Back-face colors. */ 271 for (i = 0; i < ATTR_COLOR_COUNT; i++) { 272 if (outputs->bcolor[i] != ATTR_UNUSED) { 273 c->code->outputs[outputs->bcolor[i]] = reg++; 274 } else if (any_bcolor_used) { 275 reg++; 276 } 277 } 278 279 /* Texture coordinates. */ 280 for (i = 0; i < ATTR_GENERIC_COUNT; i++) { 281 if (outputs->generic[i] != ATTR_UNUSED) { 282 c->code->outputs[outputs->generic[i]] = reg++; 283 } 284 } 285 286 /* Fog coordinates. */ 287 if (outputs->fog != ATTR_UNUSED) { 288 c->code->outputs[outputs->fog] = reg++; 289 } 290 291 /* WPOS. */ 292 if (outputs->wpos != ATTR_UNUSED) { 293 c->code->outputs[outputs->wpos] = reg++; 294 } 295} 296 297static void r300_insert_wpos(struct r300_vertex_program_compiler* c, 298 struct r300_shader_semantics* outputs) 299{ 300 int i, lastOutput = 0; 301 302 /* Find the max output index. */ 303 lastOutput = MAX2(lastOutput, outputs->psize); 304 for (i = 0; i < ATTR_COLOR_COUNT; i++) { 305 lastOutput = MAX2(lastOutput, outputs->color[i]); 306 lastOutput = MAX2(lastOutput, outputs->bcolor[i]); 307 } 308 for (i = 0; i < ATTR_GENERIC_COUNT; i++) { 309 lastOutput = MAX2(lastOutput, outputs->generic[i]); 310 } 311 lastOutput = MAX2(lastOutput, outputs->fog); 312 313 /* Set WPOS after the last output. */ 314 lastOutput++; 315 rc_copy_output(&c->Base, 0, lastOutput); /* out[lastOutput] = out[0]; */ 316 outputs->wpos = lastOutput; 317} 318 319void r300_translate_vertex_shader(struct r300_context* r300, 320 struct r300_vertex_shader* vs) 321{ 322 struct r300_vertex_program_compiler compiler; 323 struct tgsi_to_rc ttr; 324 325 /* Initialize. */ 326 r300_shader_read_vs_outputs(&vs->info, &vs->outputs); 327 328 /* Setup the compiler */ 329 rc_init(&compiler.Base); 330 331 compiler.Base.Debug = DBG_ON(r300, DBG_VP); 332 compiler.code = &vs->code; 333 compiler.UserData = vs; 334 335 if (compiler.Base.Debug) { 336 debug_printf("r300: Initial vertex program\n"); 337 tgsi_dump(vs->state.tokens, 0); 338 } 339 340 /* Translate TGSI to our internal representation */ 341 ttr.compiler = &compiler.Base; 342 ttr.info = &vs->info; 343 ttr.use_half_swizzles = FALSE; 344 345 r300_tgsi_to_rc(&ttr, vs->state.tokens); 346 347 compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+1)); 348 compiler.SetHwInputOutput = &set_vertex_inputs_outputs; 349 350 /* Insert the WPOS output. */ 351 r300_insert_wpos(&compiler, &vs->outputs); 352 353 r300_shader_vap_output_fmt(vs); 354 r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl); 355 356 /* Invoke the compiler */ 357 r3xx_compile_vertex_program(&compiler); 358 if (compiler.Base.Error) { 359 /* XXX We should fallback using Draw. */ 360 fprintf(stderr, "r300 VP: Compiler error\n"); 361 abort(); 362 } 363 364 /* And, finally... */ 365 rc_destroy(&compiler.Base); 366 vs->translated = TRUE; 367} 368 369boolean r300_vertex_shader_setup_wpos(struct r300_context* r300) 370{ 371 struct r300_vertex_shader* vs = r300->vs_state.state; 372 int tex_output = vs->wpos_tex_output; 373 uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output; 374 uint32_t* hwfmt = vs->hwfmt; 375 376 if (r300->fs->inputs.wpos != ATTR_UNUSED) { 377 /* Enable WPOS in VAP. */ 378 if (!(hwfmt[1] & tex_fmt)) { 379 hwfmt[1] |= tex_fmt; 380 hwfmt[3] |= (4 << (3 * tex_output)); 381 382 assert(tex_output < 8); 383 return TRUE; 384 } 385 } else { 386 /* Disable WPOS in VAP. */ 387 if (hwfmt[1] & tex_fmt) { 388 hwfmt[1] &= ~tex_fmt; 389 hwfmt[3] &= ~(4 << (3 * tex_output)); 390 return TRUE; 391 } 392 } 393 return FALSE; 394} 395