Changeset 28475 in vbox for trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/shader.c
- Timestamp:
- Apr 19, 2010 3:27:01 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/shader.c
r25949 r28475 33 33 34 34 #include "config.h" 35 #include "wine/port.h" 35 36 36 37 #include <math.h> 37 38 #include <stdio.h> 39 #include <string.h> 38 40 39 41 #include "wined3d_private.h" 40 42 41 43 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); 44 WINE_DECLARE_DEBUG_CHANNEL(d3d); 45 46 static const char *shader_opcode_names[] = 47 { 48 /* WINED3DSIH_ABS */ "abs", 49 /* WINED3DSIH_ADD */ "add", 50 /* WINED3DSIH_BEM */ "bem", 51 /* WINED3DSIH_BREAK */ "break", 52 /* WINED3DSIH_BREAKC */ "breakc", 53 /* WINED3DSIH_BREAKP */ "breakp", 54 /* WINED3DSIH_CALL */ "call", 55 /* WINED3DSIH_CALLNZ */ "callnz", 56 /* WINED3DSIH_CMP */ "cmp", 57 /* WINED3DSIH_CND */ "cnd", 58 /* WINED3DSIH_CRS */ "crs", 59 /* WINED3DSIH_CUT */ "cut", 60 /* WINED3DSIH_DCL */ "dcl", 61 /* WINED3DSIH_DEF */ "def", 62 /* WINED3DSIH_DEFB */ "defb", 63 /* WINED3DSIH_DEFI */ "defi", 64 /* WINED3DSIH_DP2ADD */ "dp2add", 65 /* WINED3DSIH_DP3 */ "dp3", 66 /* WINED3DSIH_DP4 */ "dp4", 67 /* WINED3DSIH_DST */ "dst", 68 /* WINED3DSIH_DSX */ "dsx", 69 /* WINED3DSIH_DSY */ "dsy", 70 /* WINED3DSIH_ELSE */ "else", 71 /* WINED3DSIH_EMIT */ "emit", 72 /* WINED3DSIH_ENDIF */ "endif", 73 /* WINED3DSIH_ENDLOOP */ "endloop", 74 /* WINED3DSIH_ENDREP */ "endrep", 75 /* WINED3DSIH_EXP */ "exp", 76 /* WINED3DSIH_EXPP */ "expp", 77 /* WINED3DSIH_FRC */ "frc", 78 /* WINED3DSIH_IADD */ "iadd", 79 /* WINED3DSIH_IF */ "if", 80 /* WINED3DSIH_IFC */ "ifc", 81 /* WINED3DSIH_IGE */ "ige", 82 /* WINED3DSIH_LABEL */ "label", 83 /* WINED3DSIH_LIT */ "lit", 84 /* WINED3DSIH_LOG */ "log", 85 /* WINED3DSIH_LOGP */ "logp", 86 /* WINED3DSIH_LOOP */ "loop", 87 /* WINED3DSIH_LRP */ "lrp", 88 /* WINED3DSIH_LT */ "lt", 89 /* WINED3DSIH_M3x2 */ "m3x2", 90 /* WINED3DSIH_M3x3 */ "m3x3", 91 /* WINED3DSIH_M3x4 */ "m3x4", 92 /* WINED3DSIH_M4x3 */ "m4x3", 93 /* WINED3DSIH_M4x4 */ "m4x4", 94 /* WINED3DSIH_MAD */ "mad", 95 /* WINED3DSIH_MAX */ "max", 96 /* WINED3DSIH_MIN */ "min", 97 /* WINED3DSIH_MOV */ "mov", 98 /* WINED3DSIH_MOVA */ "mova", 99 /* WINED3DSIH_MUL */ "mul", 100 /* WINED3DSIH_NOP */ "nop", 101 /* WINED3DSIH_NRM */ "nrm", 102 /* WINED3DSIH_PHASE */ "phase", 103 /* WINED3DSIH_POW */ "pow", 104 /* WINED3DSIH_RCP */ "rcp", 105 /* WINED3DSIH_REP */ "rep", 106 /* WINED3DSIH_RET */ "ret", 107 /* WINED3DSIH_RSQ */ "rsq", 108 /* WINED3DSIH_SETP */ "setp", 109 /* WINED3DSIH_SGE */ "sge", 110 /* WINED3DSIH_SGN */ "sgn", 111 /* WINED3DSIH_SINCOS */ "sincos", 112 /* WINED3DSIH_SLT */ "slt", 113 /* WINED3DSIH_SUB */ "sub", 114 /* WINED3DSIH_TEX */ "texld", 115 /* WINED3DSIH_TEXBEM */ "texbem", 116 /* WINED3DSIH_TEXBEML */ "texbeml", 117 /* WINED3DSIH_TEXCOORD */ "texcrd", 118 /* WINED3DSIH_TEXDEPTH */ "texdepth", 119 /* WINED3DSIH_TEXDP3 */ "texdp3", 120 /* WINED3DSIH_TEXDP3TEX */ "texdp3tex", 121 /* WINED3DSIH_TEXKILL */ "texkill", 122 /* WINED3DSIH_TEXLDD */ "texldd", 123 /* WINED3DSIH_TEXLDL */ "texldl", 124 /* WINED3DSIH_TEXM3x2DEPTH */ "texm3x2depth", 125 /* WINED3DSIH_TEXM3x2PAD */ "texm3x2pad", 126 /* WINED3DSIH_TEXM3x2TEX */ "texm3x2tex", 127 /* WINED3DSIH_TEXM3x3 */ "texm3x3", 128 /* WINED3DSIH_TEXM3x3DIFF */ "texm3x3diff", 129 /* WINED3DSIH_TEXM3x3PAD */ "texm3x3pad", 130 /* WINED3DSIH_TEXM3x3SPEC */ "texm3x3spec", 131 /* WINED3DSIH_TEXM3x3TEX */ "texm3x3tex", 132 /* WINED3DSIH_TEXM3x3VSPEC */ "texm3x3vspec", 133 /* WINED3DSIH_TEXREG2AR */ "texreg2ar", 134 /* WINED3DSIH_TEXREG2GB */ "texreg2gb", 135 /* WINED3DSIH_TEXREG2RGB */ "texreg2rgb", 136 }; 137 138 static const char *semantic_names[] = 139 { 140 /* WINED3DDECLUSAGE_POSITION */ "SV_POSITION", 141 /* WINED3DDECLUSAGE_BLENDWEIGHT */ "BLENDWEIGHT", 142 /* WINED3DDECLUSAGE_BLENDINDICES */ "BLENDINDICES", 143 /* WINED3DDECLUSAGE_NORMAL */ "NORMAL", 144 /* WINED3DDECLUSAGE_PSIZE */ "PSIZE", 145 /* WINED3DDECLUSAGE_TEXCOORD */ "TEXCOORD", 146 /* WINED3DDECLUSAGE_TANGENT */ "TANGENT", 147 /* WINED3DDECLUSAGE_BINORMAL */ "BINORMAL", 148 /* WINED3DDECLUSAGE_TESSFACTOR */ "TESSFACTOR", 149 /* WINED3DDECLUSAGE_POSITIONT */ "POSITIONT", 150 /* WINED3DDECLUSAGE_COLOR */ "COLOR", 151 /* WINED3DDECLUSAGE_FOG */ "FOG", 152 /* WINED3DDECLUSAGE_DEPTH */ "DEPTH", 153 /* WINED3DDECLUSAGE_SAMPLE */ "SAMPLE", 154 }; 155 156 static const char *shader_semantic_name_from_usage(WINED3DDECLUSAGE usage) 157 { 158 if (usage >= sizeof(semantic_names) / sizeof(*semantic_names)) 159 { 160 FIXME("Unrecognized usage %#x.\n", usage); 161 return "UNRECOGNIZED"; 162 } 163 164 return semantic_names[usage]; 165 } 166 167 static WINED3DDECLUSAGE shader_usage_from_semantic_name(const char *name) 168 { 169 unsigned int i; 170 171 for (i = 0; i < sizeof(semantic_names) / sizeof(*semantic_names); ++i) 172 { 173 if (!strcmp(name, semantic_names[i])) return i; 174 } 175 176 return ~0U; 177 } 178 179 BOOL shader_match_semantic(const char *semantic_name, WINED3DDECLUSAGE usage) 180 { 181 return !strcmp(semantic_name, shader_semantic_name_from_usage(usage)); 182 } 183 184 static void shader_signature_from_semantic(struct wined3d_shader_signature_element *e, 185 const struct wined3d_shader_semantic *s) 186 { 187 e->semantic_name = shader_semantic_name_from_usage(s->usage); 188 e->semantic_idx = s->usage_idx; 189 e->sysval_semantic = 0; 190 e->component_type = 0; 191 e->register_idx = s->reg.reg.idx; 192 e->mask = s->reg.write_mask; 193 } 194 195 static const struct wined3d_shader_frontend *shader_select_frontend(DWORD version_token) 196 { 197 switch (version_token >> 16) 198 { 199 case WINED3D_SM1_VS: 200 case WINED3D_SM1_PS: 201 return &sm1_shader_frontend; 202 203 case WINED3D_SM4_PS: 204 case WINED3D_SM4_VS: 205 case WINED3D_SM4_GS: 206 return &sm4_shader_frontend; 207 208 default: 209 FIXME("Unrecognised version token %#x\n", version_token); 210 return NULL; 211 } 212 } 213 214 void shader_buffer_clear(struct wined3d_shader_buffer *buffer) 215 { 216 buffer->buffer[0] = '\0'; 217 buffer->bsize = 0; 218 buffer->lineNo = 0; 219 buffer->newline = TRUE; 220 } 221 222 BOOL shader_buffer_init(struct wined3d_shader_buffer *buffer) 223 { 224 buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE); 225 if (!buffer->buffer) 226 { 227 ERR("Failed to allocate shader buffer memory.\n"); 228 return FALSE; 229 } 230 231 shader_buffer_clear(buffer); 232 return TRUE; 233 } 234 235 void shader_buffer_free(struct wined3d_shader_buffer *buffer) 236 { 237 HeapFree(GetProcessHeap(), 0, buffer->buffer); 238 } 239 240 int shader_vaddline(struct wined3d_shader_buffer *buffer, const char *format, va_list args) 241 { 242 char *base = buffer->buffer + buffer->bsize; 243 int rc; 244 245 rc = vsnprintf(base, SHADER_PGMSIZE - 1 - buffer->bsize, format, args); 246 247 if (rc < 0 /* C89 */ || (unsigned int)rc > SHADER_PGMSIZE - 1 - buffer->bsize /* C99 */) 248 { 249 ERR("The buffer allocated for the shader program string " 250 "is too small at %d bytes.\n", SHADER_PGMSIZE); 251 buffer->bsize = SHADER_PGMSIZE - 1; 252 return -1; 253 } 254 255 if (buffer->newline) 256 { 257 TRACE("GL HW (%u, %u) : %s", buffer->lineNo + 1, buffer->bsize, base); 258 buffer->newline = FALSE; 259 } 260 else 261 { 262 TRACE("%s", base); 263 } 264 265 buffer->bsize += rc; 266 if (buffer->buffer[buffer->bsize-1] == '\n') 267 { 268 ++buffer->lineNo; 269 buffer->newline = TRUE; 270 } 271 272 return 0; 273 } 274 275 int shader_addline(struct wined3d_shader_buffer *buffer, const char *format, ...) 276 { 277 va_list args; 278 int ret; 279 280 va_start(args, format); 281 ret = shader_vaddline(buffer, format, args); 282 va_end(args); 283 284 return ret; 285 } 286 287 static void shader_init(struct IWineD3DBaseShaderClass *shader, IWineD3DDeviceImpl *device, 288 IUnknown *parent, const struct wined3d_parent_ops *parent_ops) 289 { 290 shader->ref = 1; 291 shader->device = (IWineD3DDevice *)device; 292 shader->parent = parent; 293 shader->parent_ops = parent_ops; 294 list_init(&shader->linked_programs); 295 list_add_head(&device->shaders, &shader->shader_list_entry); 296 } 297 298 /* Convert floating point offset relative to a register file to an absolute 299 * offset for float constants. */ 300 static unsigned int shader_get_float_offset(WINED3DSHADER_PARAM_REGISTER_TYPE register_type, UINT register_idx) 301 { 302 switch (register_type) 303 { 304 case WINED3DSPR_CONST: return register_idx; 305 case WINED3DSPR_CONST2: return 2048 + register_idx; 306 case WINED3DSPR_CONST3: return 4096 + register_idx; 307 case WINED3DSPR_CONST4: return 6144 + register_idx; 308 default: 309 FIXME("Unsupported register type: %u.\n", register_type); 310 return register_idx; 311 } 312 } 313 314 static void shader_delete_constant_list(struct list *clist) 315 { 316 struct local_constant *constant; 317 struct list *ptr; 318 319 ptr = list_head(clist); 320 while (ptr) 321 { 322 constant = LIST_ENTRY(ptr, struct local_constant, entry); 323 ptr = list_next(clist, ptr); 324 HeapFree(GetProcessHeap(), 0, constant); 325 } 326 list_init(clist); 327 } 328 329 static inline void set_bitmap_bit(DWORD *bitmap, DWORD bit) 330 { 331 DWORD idx, shift; 332 idx = bit >> 5; 333 shift = bit & 0x1f; 334 bitmap[idx] |= (1 << shift); 335 } 336 337 static void shader_record_register_usage(IWineD3DBaseShaderImpl *shader, struct shader_reg_maps *reg_maps, 338 const struct wined3d_shader_register *reg, enum wined3d_shader_type shader_type) 339 { 340 switch (reg->type) 341 { 342 case WINED3DSPR_TEXTURE: /* WINED3DSPR_ADDR */ 343 if (shader_type == WINED3D_SHADER_TYPE_PIXEL) reg_maps->texcoord |= 1 << reg->idx; 344 else reg_maps->address |= 1 << reg->idx; 345 break; 346 347 case WINED3DSPR_TEMP: 348 reg_maps->temporary |= 1 << reg->idx; 349 break; 350 351 case WINED3DSPR_INPUT: 352 if (shader_type == WINED3D_SHADER_TYPE_PIXEL) 353 { 354 if (reg->rel_addr) 355 { 356 /* If relative addressing is used, we must assume that all registers 357 * are used. Even if it is a construct like v3[aL], we can't assume 358 * that v0, v1 and v2 aren't read because aL can be negative */ 359 unsigned int i; 360 for (i = 0; i < MAX_REG_INPUT; ++i) 361 { 362 ((IWineD3DPixelShaderImpl *)shader)->input_reg_used[i] = TRUE; 363 } 364 } 365 else 366 { 367 ((IWineD3DPixelShaderImpl *)shader)->input_reg_used[reg->idx] = TRUE; 368 } 369 } 370 else reg_maps->input_registers |= 1 << reg->idx; 371 break; 372 373 case WINED3DSPR_RASTOUT: 374 if (reg->idx == 1) reg_maps->fog = 1; 375 break; 376 377 case WINED3DSPR_MISCTYPE: 378 if (shader_type == WINED3D_SHADER_TYPE_PIXEL) 379 { 380 if (reg->idx == 0) reg_maps->vpos = 1; 381 else if (reg->idx == 1) reg_maps->usesfacing = 1; 382 } 383 break; 384 385 case WINED3DSPR_CONST: 386 if (reg->rel_addr) 387 { 388 if (shader_type != WINED3D_SHADER_TYPE_PIXEL) 389 { 390 if (reg->idx < ((IWineD3DVertexShaderImpl *)shader)->min_rel_offset) 391 { 392 ((IWineD3DVertexShaderImpl *)shader)->min_rel_offset = reg->idx; 393 } 394 if (reg->idx > ((IWineD3DVertexShaderImpl *)shader)->max_rel_offset) 395 { 396 ((IWineD3DVertexShaderImpl *)shader)->max_rel_offset = reg->idx; 397 } 398 } 399 reg_maps->usesrelconstF = TRUE; 400 } 401 else 402 { 403 set_bitmap_bit(reg_maps->constf, reg->idx); 404 } 405 break; 406 407 case WINED3DSPR_CONSTINT: 408 reg_maps->integer_constants |= (1 << reg->idx); 409 break; 410 411 case WINED3DSPR_CONSTBOOL: 412 reg_maps->boolean_constants |= (1 << reg->idx); 413 break; 414 415 case WINED3DSPR_COLOROUT: 416 reg_maps->highest_render_target = max(reg_maps->highest_render_target, reg->idx); 417 break; 418 419 default: 420 TRACE("Not recording register of type %#x and idx %u\n", reg->type, reg->idx); 421 break; 422 } 423 } 424 425 static unsigned int get_instr_extra_regcount(enum WINED3D_SHADER_INSTRUCTION_HANDLER instr, unsigned int param) 426 { 427 switch (instr) 428 { 429 case WINED3DSIH_M4x4: 430 case WINED3DSIH_M3x4: 431 return param == 1 ? 3 : 0; 432 433 case WINED3DSIH_M4x3: 434 case WINED3DSIH_M3x3: 435 return param == 1 ? 2 : 0; 436 437 case WINED3DSIH_M3x2: 438 return param == 1 ? 1 : 0; 439 440 default: 441 return 0; 442 } 443 } 444 445 /* Note that this does not count the loop register as an address register. */ 446 static HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3d_shader_frontend *fe, 447 struct shader_reg_maps *reg_maps, struct wined3d_shader_signature_element *input_signature, 448 struct wined3d_shader_signature_element *output_signature, const DWORD *byte_code, DWORD constf_size) 449 { 450 IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)iface; 451 unsigned int cur_loop_depth = 0, max_loop_depth = 0; 452 void *fe_data = shader->baseShader.frontend_data; 453 struct wined3d_shader_version shader_version; 454 const DWORD *ptr = byte_code; 455 456 memset(reg_maps, 0, sizeof(*reg_maps)); 457 458 /* get_registers_used() is called on every compile on some 1.x shaders, 459 * which can result in stacking up a collection of local constants. 460 * Delete the old constants if existing. */ 461 shader_delete_constant_list(&shader->baseShader.constantsF); 462 shader_delete_constant_list(&shader->baseShader.constantsB); 463 shader_delete_constant_list(&shader->baseShader.constantsI); 464 465 fe->shader_read_header(fe_data, &ptr, &shader_version); 466 reg_maps->shader_version = shader_version; 467 468 reg_maps->constf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 469 sizeof(*reg_maps->constf) * ((constf_size + 31) / 32)); 470 if (!reg_maps->constf) 471 { 472 ERR("Failed to allocate constant map memory.\n"); 473 return E_OUTOFMEMORY; 474 } 475 476 while (!fe->shader_is_end(fe_data, &ptr)) 477 { 478 struct wined3d_shader_instruction ins; 479 const char *comment; 480 UINT comment_size; 481 UINT param_size; 482 483 /* Skip comments. */ 484 fe->shader_read_comment(&ptr, &comment, &comment_size); 485 if (comment) continue; 486 487 /* Fetch opcode. */ 488 fe->shader_read_opcode(fe_data, &ptr, &ins, ¶m_size); 489 490 /* Unhandled opcode, and its parameters. */ 491 if (ins.handler_idx == WINED3DSIH_TABLE_SIZE) 492 { 493 TRACE("Skipping unrecognized instruction.\n"); 494 ptr += param_size; 495 continue; 496 } 497 498 /* Handle declarations. */ 499 if (ins.handler_idx == WINED3DSIH_DCL) 500 { 501 struct wined3d_shader_semantic semantic; 502 503 fe->shader_read_semantic(&ptr, &semantic); 504 505 switch (semantic.reg.reg.type) 506 { 507 /* Mark input registers used. */ 508 case WINED3DSPR_INPUT: 509 reg_maps->input_registers |= 1 << semantic.reg.reg.idx; 510 shader_signature_from_semantic(&input_signature[semantic.reg.reg.idx], &semantic); 511 break; 512 513 /* Vertex shader: mark 3.0 output registers used, save token. */ 514 case WINED3DSPR_OUTPUT: 515 reg_maps->output_registers |= 1 << semantic.reg.reg.idx; 516 shader_signature_from_semantic(&output_signature[semantic.reg.reg.idx], &semantic); 517 if (semantic.usage == WINED3DDECLUSAGE_FOG) reg_maps->fog = 1; 518 break; 519 520 /* Save sampler usage token. */ 521 case WINED3DSPR_SAMPLER: 522 reg_maps->sampler_type[semantic.reg.reg.idx] = semantic.sampler_type; 523 break; 524 525 default: 526 TRACE("Not recording DCL register type %#x.\n", semantic.reg.reg.type); 527 break; 528 } 529 } 530 else if (ins.handler_idx == WINED3DSIH_DEF) 531 { 532 struct wined3d_shader_src_param rel_addr; 533 struct wined3d_shader_dst_param dst; 534 535 local_constant *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant)); 536 if (!lconst) return E_OUTOFMEMORY; 537 538 fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr); 539 lconst->idx = dst.reg.idx; 540 541 memcpy(lconst->value, ptr, 4 * sizeof(DWORD)); 542 ptr += 4; 543 544 /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */ 545 if (shader_version.major == 1 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL) 546 { 547 float *value = (float *)lconst->value; 548 if (value[0] < -1.0f) value[0] = -1.0f; 549 else if (value[0] > 1.0f) value[0] = 1.0f; 550 if (value[1] < -1.0f) value[1] = -1.0f; 551 else if (value[1] > 1.0f) value[1] = 1.0f; 552 if (value[2] < -1.0f) value[2] = -1.0f; 553 else if (value[2] > 1.0f) value[2] = 1.0f; 554 if (value[3] < -1.0f) value[3] = -1.0f; 555 else if (value[3] > 1.0f) value[3] = 1.0f; 556 } 557 558 list_add_head(&shader->baseShader.constantsF, &lconst->entry); 559 } 560 else if (ins.handler_idx == WINED3DSIH_DEFI) 561 { 562 struct wined3d_shader_src_param rel_addr; 563 struct wined3d_shader_dst_param dst; 564 565 local_constant *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant)); 566 if (!lconst) return E_OUTOFMEMORY; 567 568 fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr); 569 lconst->idx = dst.reg.idx; 570 571 memcpy(lconst->value, ptr, 4 * sizeof(DWORD)); 572 ptr += 4; 573 574 list_add_head(&shader->baseShader.constantsI, &lconst->entry); 575 reg_maps->local_int_consts |= (1 << dst.reg.idx); 576 } 577 else if (ins.handler_idx == WINED3DSIH_DEFB) 578 { 579 struct wined3d_shader_src_param rel_addr; 580 struct wined3d_shader_dst_param dst; 581 582 local_constant *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant)); 583 if (!lconst) return E_OUTOFMEMORY; 584 585 fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr); 586 lconst->idx = dst.reg.idx; 587 588 memcpy(lconst->value, ptr, sizeof(DWORD)); 589 ++ptr; 590 591 list_add_head(&shader->baseShader.constantsB, &lconst->entry); 592 reg_maps->local_bool_consts |= (1 << dst.reg.idx); 593 } 594 /* If there's a loop in the shader. */ 595 else if (ins.handler_idx == WINED3DSIH_LOOP 596 || ins.handler_idx == WINED3DSIH_REP) 597 { 598 struct wined3d_shader_src_param src, rel_addr; 599 600 fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr); 601 602 /* Rep and Loop always use an integer constant for the control parameters. */ 603 if (ins.handler_idx == WINED3DSIH_REP) 604 { 605 reg_maps->integer_constants |= 1 << src.reg.idx; 606 } 607 else 608 { 609 fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr); 610 reg_maps->integer_constants |= 1 << src.reg.idx; 611 } 612 613 cur_loop_depth++; 614 if (cur_loop_depth > max_loop_depth) max_loop_depth = cur_loop_depth; 615 } 616 else if (ins.handler_idx == WINED3DSIH_ENDLOOP 617 || ins.handler_idx == WINED3DSIH_ENDREP) 618 { 619 cur_loop_depth--; 620 } 621 /* For subroutine prototypes. */ 622 else if (ins.handler_idx == WINED3DSIH_LABEL) 623 { 624 struct wined3d_shader_src_param src, rel_addr; 625 626 fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr); 627 reg_maps->labels |= 1 << src.reg.idx; 628 } 629 /* Set texture, address, temporary registers. */ 630 else 631 { 632 BOOL color0_mov = FALSE; 633 int i, limit; 634 635 /* This will loop over all the registers and try to 636 * make a bitmask of the ones we're interested in. 637 * 638 * Relative addressing tokens are ignored, but that's 639 * okay, since we'll catch any address registers when 640 * they are initialized (required by spec). */ 641 if (ins.dst_count) 642 { 643 struct wined3d_shader_src_param dst_rel_addr; 644 struct wined3d_shader_dst_param dst_param; 645 646 fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr); 647 648 shader_record_register_usage(shader, reg_maps, &dst_param.reg, shader_version.type); 649 650 /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and 651 * is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel 652 * shaders because TECRDOUT isn't used in them, but future register types might cause issues */ 653 if (shader_version.type == WINED3D_SHADER_TYPE_VERTEX && shader_version.major < 3 654 && dst_param.reg.type == WINED3DSPR_TEXCRDOUT) 655 { 656 reg_maps->texcoord_mask[dst_param.reg.idx] |= dst_param.write_mask; 657 } 658 659 if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL) 660 { 661 IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *)shader; 662 663 if (dst_param.reg.type == WINED3DSPR_COLOROUT && dst_param.reg.idx == 0) 664 { 665 /* Many 2.0 and 3.0 pixel shaders end with a MOV from a temp register to 666 * COLOROUT 0. If we know this in advance, the ARB shader backend can skip 667 * the mov and perform the sRGB write correction from the source register. 668 * 669 * However, if the mov is only partial, we can't do this, and if the write 670 * comes from an instruction other than MOV it is hard to do as well. If 671 * COLOROUT 0 is overwritten partially later, the marker is dropped again. */ 672 673 ps->color0_mov = FALSE; 674 if (ins.handler_idx == WINED3DSIH_MOV) 675 { 676 /* Used later when the source register is read. */ 677 color0_mov = TRUE; 678 } 679 } 680 /* Also drop the MOV marker if the source register is overwritten prior to the shader 681 * end 682 */ 683 else if (dst_param.reg.type == WINED3DSPR_TEMP && dst_param.reg.idx == ps->color0_reg) 684 { 685 ps->color0_mov = FALSE; 686 } 687 } 688 689 /* Declare 1.x samplers implicitly, based on the destination reg. number. */ 690 if (shader_version.major == 1 691 && (ins.handler_idx == WINED3DSIH_TEX 692 || ins.handler_idx == WINED3DSIH_TEXBEM 693 || ins.handler_idx == WINED3DSIH_TEXBEML 694 || ins.handler_idx == WINED3DSIH_TEXDP3TEX 695 || ins.handler_idx == WINED3DSIH_TEXM3x2TEX 696 || ins.handler_idx == WINED3DSIH_TEXM3x3SPEC 697 || ins.handler_idx == WINED3DSIH_TEXM3x3TEX 698 || ins.handler_idx == WINED3DSIH_TEXM3x3VSPEC 699 || ins.handler_idx == WINED3DSIH_TEXREG2AR 700 || ins.handler_idx == WINED3DSIH_TEXREG2GB 701 || ins.handler_idx == WINED3DSIH_TEXREG2RGB)) 702 { 703 /* Fake sampler usage, only set reserved bit and type. */ 704 DWORD sampler_code = dst_param.reg.idx; 705 706 TRACE("Setting fake 2D sampler for 1.x pixelshader.\n"); 707 reg_maps->sampler_type[sampler_code] = WINED3DSTT_2D; 708 709 /* texbem is only valid with < 1.4 pixel shaders */ 710 if (ins.handler_idx == WINED3DSIH_TEXBEM 711 || ins.handler_idx == WINED3DSIH_TEXBEML) 712 { 713 reg_maps->bumpmat |= 1 << dst_param.reg.idx; 714 if (ins.handler_idx == WINED3DSIH_TEXBEML) 715 { 716 reg_maps->luminanceparams |= 1 << dst_param.reg.idx; 717 } 718 } 719 } 720 else if (ins.handler_idx == WINED3DSIH_BEM) 721 { 722 reg_maps->bumpmat |= 1 << dst_param.reg.idx; 723 } 724 } 725 726 if (ins.handler_idx == WINED3DSIH_NRM) reg_maps->usesnrm = 1; 727 else if (ins.handler_idx == WINED3DSIH_DSY) reg_maps->usesdsy = 1; 728 else if (ins.handler_idx == WINED3DSIH_DSX) reg_maps->usesdsx = 1; 729 else if (ins.handler_idx == WINED3DSIH_TEXLDD) reg_maps->usestexldd = 1; 730 else if (ins.handler_idx == WINED3DSIH_TEXLDL) reg_maps->usestexldl = 1; 731 else if (ins.handler_idx == WINED3DSIH_MOVA) reg_maps->usesmova = 1; 732 else if (ins.handler_idx == WINED3DSIH_IFC) reg_maps->usesifc = 1; 733 else if (ins.handler_idx == WINED3DSIH_CALL) reg_maps->usescall = 1; 734 735 limit = ins.src_count + (ins.predicate ? 1 : 0); 736 for (i = 0; i < limit; ++i) 737 { 738 struct wined3d_shader_src_param src_param, src_rel_addr; 739 unsigned int count; 740 741 fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr); 742 count = get_instr_extra_regcount(ins.handler_idx, i); 743 744 shader_record_register_usage(shader, reg_maps, &src_param.reg, shader_version.type); 745 while (count) 746 { 747 ++src_param.reg.idx; 748 shader_record_register_usage(shader, reg_maps, &src_param.reg, shader_version.type); 749 --count; 750 } 751 752 if (color0_mov) 753 { 754 IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *)shader; 755 if (src_param.reg.type == WINED3DSPR_TEMP 756 && src_param.swizzle == WINED3DSP_NOSWIZZLE) 757 { 758 ps->color0_mov = TRUE; 759 ps->color0_reg = src_param.reg.idx; 760 } 761 } 762 } 763 } 764 } 765 reg_maps->loop_depth = max_loop_depth; 766 767 shader->baseShader.functionLength = ((const char *)ptr - (const char *)byte_code); 768 769 return WINED3D_OK; 770 } 771 772 unsigned int shader_find_free_input_register(const struct shader_reg_maps *reg_maps, unsigned int max) 773 { 774 DWORD map = 1 << max; 775 map |= map - 1; 776 map &= reg_maps->shader_version.major < 3 ? ~reg_maps->texcoord : ~reg_maps->input_registers; 777 778 return wined3d_log2i(map); 779 } 780 781 static void shader_dump_decl_usage(const struct wined3d_shader_semantic *semantic, 782 const struct wined3d_shader_version *shader_version) 783 { 784 TRACE("dcl"); 785 786 if (semantic->reg.reg.type == WINED3DSPR_SAMPLER) 787 { 788 switch (semantic->sampler_type) 789 { 790 case WINED3DSTT_2D: TRACE("_2d"); break; 791 case WINED3DSTT_CUBE: TRACE("_cube"); break; 792 case WINED3DSTT_VOLUME: TRACE("_volume"); break; 793 default: TRACE("_unknown_ttype(0x%08x)", semantic->sampler_type); 794 } 795 } 796 else 797 { 798 /* Pixel shaders 3.0 don't have usage semantics. */ 799 if (shader_version->major < 3 && shader_version->type == WINED3D_SHADER_TYPE_PIXEL) return; 800 else TRACE("_"); 801 802 switch (semantic->usage) 803 { 804 case WINED3DDECLUSAGE_POSITION: 805 TRACE("position%u", semantic->usage_idx); 806 break; 807 808 case WINED3DDECLUSAGE_BLENDINDICES: 809 TRACE("blend"); 810 break; 811 812 case WINED3DDECLUSAGE_BLENDWEIGHT: 813 TRACE("weight"); 814 break; 815 816 case WINED3DDECLUSAGE_NORMAL: 817 TRACE("normal%u", semantic->usage_idx); 818 break; 819 820 case WINED3DDECLUSAGE_PSIZE: 821 TRACE("psize"); 822 break; 823 824 case WINED3DDECLUSAGE_COLOR: 825 if (semantic->usage_idx == 0) TRACE("color"); 826 else TRACE("specular%u", (semantic->usage_idx - 1)); 827 break; 828 829 case WINED3DDECLUSAGE_TEXCOORD: 830 TRACE("texture%u", semantic->usage_idx); 831 break; 832 833 case WINED3DDECLUSAGE_TANGENT: 834 TRACE("tangent"); 835 break; 836 837 case WINED3DDECLUSAGE_BINORMAL: 838 TRACE("binormal"); 839 break; 840 841 case WINED3DDECLUSAGE_TESSFACTOR: 842 TRACE("tessfactor"); 843 break; 844 845 case WINED3DDECLUSAGE_POSITIONT: 846 TRACE("positionT%u", semantic->usage_idx); 847 break; 848 849 case WINED3DDECLUSAGE_FOG: 850 TRACE("fog"); 851 break; 852 853 case WINED3DDECLUSAGE_DEPTH: 854 TRACE("depth"); 855 break; 856 857 case WINED3DDECLUSAGE_SAMPLE: 858 TRACE("sample"); 859 break; 860 861 default: 862 FIXME("unknown_semantics(0x%08x)", semantic->usage); 863 } 864 } 865 } 866 867 static void shader_dump_register(const struct wined3d_shader_register *reg, 868 const struct wined3d_shader_version *shader_version) 869 { 870 static const char * const rastout_reg_names[] = {"oPos", "oFog", "oPts"}; 871 static const char * const misctype_reg_names[] = {"vPos", "vFace"}; 872 UINT offset = reg->idx; 873 874 switch (reg->type) 875 { 876 case WINED3DSPR_TEMP: 877 TRACE("r"); 878 break; 879 880 case WINED3DSPR_INPUT: 881 TRACE("v"); 882 break; 883 884 case WINED3DSPR_CONST: 885 case WINED3DSPR_CONST2: 886 case WINED3DSPR_CONST3: 887 case WINED3DSPR_CONST4: 888 TRACE("c"); 889 offset = shader_get_float_offset(reg->type, reg->idx); 890 break; 891 892 case WINED3DSPR_TEXTURE: /* vs: case WINED3DSPR_ADDR */ 893 TRACE("%c", shader_version->type == WINED3D_SHADER_TYPE_PIXEL ? 't' : 'a'); 894 break; 895 896 case WINED3DSPR_RASTOUT: 897 TRACE("%s", rastout_reg_names[reg->idx]); 898 break; 899 900 case WINED3DSPR_COLOROUT: 901 TRACE("oC"); 902 break; 903 904 case WINED3DSPR_DEPTHOUT: 905 TRACE("oDepth"); 906 break; 907 908 case WINED3DSPR_ATTROUT: 909 TRACE("oD"); 910 break; 911 912 case WINED3DSPR_TEXCRDOUT: 913 /* Vertex shaders >= 3.0 use general purpose output registers 914 * (WINED3DSPR_OUTPUT), which can include an address token. */ 915 if (shader_version->major >= 3) TRACE("o"); 916 else TRACE("oT"); 917 break; 918 919 case WINED3DSPR_CONSTINT: 920 TRACE("i"); 921 break; 922 923 case WINED3DSPR_CONSTBOOL: 924 TRACE("b"); 925 break; 926 927 case WINED3DSPR_LABEL: 928 TRACE("l"); 929 break; 930 931 case WINED3DSPR_LOOP: 932 TRACE("aL"); 933 break; 934 935 case WINED3DSPR_SAMPLER: 936 TRACE("s"); 937 break; 938 939 case WINED3DSPR_MISCTYPE: 940 if (reg->idx > 1) FIXME("Unhandled misctype register %u.\n", reg->idx); 941 else TRACE("%s", misctype_reg_names[reg->idx]); 942 break; 943 944 case WINED3DSPR_PREDICATE: 945 TRACE("p"); 946 break; 947 948 case WINED3DSPR_IMMCONST: 949 TRACE("l"); 950 break; 951 952 case WINED3DSPR_CONSTBUFFER: 953 TRACE("cb"); 954 break; 955 956 default: 957 TRACE("unhandled_rtype(%#x)", reg->type); 958 break; 959 } 960 961 if (reg->type == WINED3DSPR_IMMCONST) 962 { 963 TRACE("("); 964 switch (reg->immconst_type) 965 { 966 case WINED3D_IMMCONST_FLOAT: 967 TRACE("%.8e", *(const float *)reg->immconst_data); 968 break; 969 970 case WINED3D_IMMCONST_FLOAT4: 971 TRACE("%.8e, %.8e, %.8e, %.8e", 972 *(const float *)®->immconst_data[0], *(const float *)®->immconst_data[1], 973 *(const float *)®->immconst_data[2], *(const float *)®->immconst_data[3]); 974 break; 975 976 default: 977 TRACE("<unhandled immconst_type %#x>", reg->immconst_type); 978 break; 979 } 980 TRACE(")"); 981 } 982 else if (reg->type != WINED3DSPR_RASTOUT && reg->type != WINED3DSPR_MISCTYPE) 983 { 984 if (reg->array_idx != ~0U) 985 { 986 TRACE("%u[%u", offset, reg->array_idx); 987 if (reg->rel_addr) 988 { 989 TRACE(" + "); 990 shader_dump_src_param(reg->rel_addr, shader_version); 991 } 992 TRACE("]"); 993 } 994 else 995 { 996 if (reg->rel_addr) 997 { 998 TRACE("["); 999 shader_dump_src_param(reg->rel_addr, shader_version); 1000 TRACE(" + "); 1001 } 1002 TRACE("%u", offset); 1003 if (reg->rel_addr) TRACE("]"); 1004 } 1005 } 1006 } 1007 1008 void shader_dump_dst_param(const struct wined3d_shader_dst_param *param, 1009 const struct wined3d_shader_version *shader_version) 1010 { 1011 DWORD write_mask = param->write_mask; 1012 1013 shader_dump_register(¶m->reg, shader_version); 1014 1015 if (write_mask != WINED3DSP_WRITEMASK_ALL) 1016 { 1017 static const char *write_mask_chars = "xyzw"; 1018 1019 TRACE("."); 1020 if (write_mask & WINED3DSP_WRITEMASK_0) TRACE("%c", write_mask_chars[0]); 1021 if (write_mask & WINED3DSP_WRITEMASK_1) TRACE("%c", write_mask_chars[1]); 1022 if (write_mask & WINED3DSP_WRITEMASK_2) TRACE("%c", write_mask_chars[2]); 1023 if (write_mask & WINED3DSP_WRITEMASK_3) TRACE("%c", write_mask_chars[3]); 1024 } 1025 } 1026 1027 void shader_dump_src_param(const struct wined3d_shader_src_param *param, 1028 const struct wined3d_shader_version *shader_version) 1029 { 1030 DWORD src_modifier = param->modifiers; 1031 DWORD swizzle = param->swizzle; 1032 1033 if (src_modifier == WINED3DSPSM_NEG 1034 || src_modifier == WINED3DSPSM_BIASNEG 1035 || src_modifier == WINED3DSPSM_SIGNNEG 1036 || src_modifier == WINED3DSPSM_X2NEG 1037 || src_modifier == WINED3DSPSM_ABSNEG) 1038 TRACE("-"); 1039 else if (src_modifier == WINED3DSPSM_COMP) 1040 TRACE("1-"); 1041 else if (src_modifier == WINED3DSPSM_NOT) 1042 TRACE("!"); 1043 1044 if (src_modifier == WINED3DSPSM_ABS || src_modifier == WINED3DSPSM_ABSNEG) 1045 TRACE("abs("); 1046 1047 shader_dump_register(¶m->reg, shader_version); 1048 1049 if (src_modifier) 1050 { 1051 switch (src_modifier) 1052 { 1053 case WINED3DSPSM_NONE: break; 1054 case WINED3DSPSM_NEG: break; 1055 case WINED3DSPSM_NOT: break; 1056 case WINED3DSPSM_BIAS: TRACE("_bias"); break; 1057 case WINED3DSPSM_BIASNEG: TRACE("_bias"); break; 1058 case WINED3DSPSM_SIGN: TRACE("_bx2"); break; 1059 case WINED3DSPSM_SIGNNEG: TRACE("_bx2"); break; 1060 case WINED3DSPSM_COMP: break; 1061 case WINED3DSPSM_X2: TRACE("_x2"); break; 1062 case WINED3DSPSM_X2NEG: TRACE("_x2"); break; 1063 case WINED3DSPSM_DZ: TRACE("_dz"); break; 1064 case WINED3DSPSM_DW: TRACE("_dw"); break; 1065 case WINED3DSPSM_ABSNEG: TRACE(")"); break; 1066 case WINED3DSPSM_ABS: TRACE(")"); break; 1067 default: TRACE("_unknown_modifier(%#x)", src_modifier); 1068 } 1069 } 1070 1071 if (swizzle != WINED3DSP_NOSWIZZLE) 1072 { 1073 static const char *swizzle_chars = "xyzw"; 1074 DWORD swizzle_x = swizzle & 0x03; 1075 DWORD swizzle_y = (swizzle >> 2) & 0x03; 1076 DWORD swizzle_z = (swizzle >> 4) & 0x03; 1077 DWORD swizzle_w = (swizzle >> 6) & 0x03; 1078 1079 if (swizzle_x == swizzle_y 1080 && swizzle_x == swizzle_z 1081 && swizzle_x == swizzle_w) 1082 { 1083 TRACE(".%c", swizzle_chars[swizzle_x]); 1084 } 1085 else 1086 { 1087 TRACE(".%c%c%c%c", swizzle_chars[swizzle_x], swizzle_chars[swizzle_y], 1088 swizzle_chars[swizzle_z], swizzle_chars[swizzle_w]); 1089 } 1090 } 1091 } 1092 1093 /* Shared code in order to generate the bulk of the shader string. 1094 * NOTE: A description of how to parse tokens can be found on MSDN. */ 1095 void shader_generate_main(IWineD3DBaseShader *iface, struct wined3d_shader_buffer *buffer, 1096 const shader_reg_maps *reg_maps, const DWORD *byte_code, void *backend_ctx) 1097 { 1098 IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)iface; 1099 IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)shader->baseShader.device; 1100 const struct wined3d_shader_frontend *fe = shader->baseShader.frontend; 1101 void *fe_data = shader->baseShader.frontend_data; 1102 struct wined3d_shader_src_param src_rel_addr[4]; 1103 struct wined3d_shader_src_param src_param[4]; 1104 struct wined3d_shader_version shader_version; 1105 struct wined3d_shader_src_param dst_rel_addr; 1106 struct wined3d_shader_dst_param dst_param; 1107 struct wined3d_shader_instruction ins; 1108 struct wined3d_shader_context ctx; 1109 const DWORD *ptr = byte_code; 1110 DWORD i; 1111 1112 /* Initialize current parsing state. */ 1113 ctx.shader = iface; 1114 ctx.gl_info = &device->adapter->gl_info; 1115 ctx.reg_maps = reg_maps; 1116 ctx.buffer = buffer; 1117 ctx.backend_data = backend_ctx; 1118 1119 ins.ctx = &ctx; 1120 ins.dst = &dst_param; 1121 ins.src = src_param; 1122 shader->baseShader.parse_state.current_row = 0; 1123 1124 fe->shader_read_header(fe_data, &ptr, &shader_version); 1125 1126 while (!fe->shader_is_end(fe_data, &ptr)) 1127 { 1128 const char *comment; 1129 UINT comment_size; 1130 UINT param_size; 1131 1132 /* Skip comment tokens. */ 1133 fe->shader_read_comment(&ptr, &comment, &comment_size); 1134 if (comment) continue; 1135 1136 /* Read opcode. */ 1137 fe->shader_read_opcode(fe_data, &ptr, &ins, ¶m_size); 1138 1139 /* Unknown opcode and its parameters. */ 1140 if (ins.handler_idx == WINED3DSIH_TABLE_SIZE) 1141 { 1142 TRACE("Skipping unrecognized instruction.\n"); 1143 ptr += param_size; 1144 continue; 1145 } 1146 1147 /* Nothing to do. */ 1148 if (ins.handler_idx == WINED3DSIH_DCL 1149 || ins.handler_idx == WINED3DSIH_NOP 1150 || ins.handler_idx == WINED3DSIH_DEF 1151 || ins.handler_idx == WINED3DSIH_DEFI 1152 || ins.handler_idx == WINED3DSIH_DEFB 1153 || ins.handler_idx == WINED3DSIH_PHASE) 1154 { 1155 ptr += param_size; 1156 continue; 1157 } 1158 1159 /* Destination token */ 1160 if (ins.dst_count) fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr); 1161 1162 /* Predication token */ 1163 if (ins.predicate) 1164 { 1165 FIXME("Predicates not implemented.\n"); 1166 ins.predicate = *ptr++; 1167 } 1168 1169 /* Other source tokens */ 1170 for (i = 0; i < ins.src_count; ++i) 1171 { 1172 fe->shader_read_src_param(fe_data, &ptr, &src_param[i], &src_rel_addr[i]); 1173 } 1174 1175 /* Call appropriate function for output target */ 1176 device->shader_backend->shader_handle_instruction(&ins); 1177 } 1178 } 1179 1180 static void shader_dump_ins_modifiers(const struct wined3d_shader_dst_param *dst) 1181 { 1182 DWORD mmask = dst->modifiers; 1183 1184 switch (dst->shift) 1185 { 1186 case 0: break; 1187 case 13: TRACE("_d8"); break; 1188 case 14: TRACE("_d4"); break; 1189 case 15: TRACE("_d2"); break; 1190 case 1: TRACE("_x2"); break; 1191 case 2: TRACE("_x4"); break; 1192 case 3: TRACE("_x8"); break; 1193 default: TRACE("_unhandled_shift(%d)", dst->shift); break; 1194 } 1195 1196 if (mmask & WINED3DSPDM_SATURATE) TRACE("_sat"); 1197 if (mmask & WINED3DSPDM_PARTIALPRECISION) TRACE("_pp"); 1198 if (mmask & WINED3DSPDM_MSAMPCENTROID) TRACE("_centroid"); 1199 1200 mmask &= ~(WINED3DSPDM_SATURATE | WINED3DSPDM_PARTIALPRECISION | WINED3DSPDM_MSAMPCENTROID); 1201 if (mmask) FIXME("_unrecognized_modifier(%#x)", mmask); 1202 } 1203 1204 static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe_data, const DWORD *byte_code) 1205 { 1206 struct wined3d_shader_version shader_version; 1207 const DWORD *ptr = byte_code; 1208 const char *type_prefix; 1209 DWORD i; 1210 1211 TRACE("Parsing %p.\n", byte_code); 1212 1213 fe->shader_read_header(fe_data, &ptr, &shader_version); 1214 1215 switch (shader_version.type) 1216 { 1217 case WINED3D_SHADER_TYPE_VERTEX: 1218 type_prefix = "vs"; 1219 break; 1220 1221 case WINED3D_SHADER_TYPE_GEOMETRY: 1222 type_prefix = "gs"; 1223 break; 1224 1225 case WINED3D_SHADER_TYPE_PIXEL: 1226 type_prefix = "ps"; 1227 break; 1228 1229 default: 1230 FIXME("Unhandled shader type %#x.\n", shader_version.type); 1231 type_prefix = "unknown"; 1232 break; 1233 } 1234 1235 TRACE("%s_%u_%u\n", type_prefix, shader_version.major, shader_version.minor); 1236 1237 while (!fe->shader_is_end(fe_data, &ptr)) 1238 { 1239 struct wined3d_shader_instruction ins; 1240 const char *comment; 1241 UINT comment_size; 1242 UINT param_size; 1243 1244 /* comment */ 1245 fe->shader_read_comment(&ptr, &comment, &comment_size); 1246 if (comment) 1247 { 1248 if (comment_size > 4 && *(const DWORD *)comment == WINEMAKEFOURCC('T', 'E', 'X', 'T')) 1249 { 1250 const char *end = comment + comment_size; 1251 const char *ptr = comment + 4; 1252 const char *line = ptr; 1253 1254 TRACE("// TEXT\n"); 1255 while (ptr != end) 1256 { 1257 if (*ptr == '\n') 1258 { 1259 UINT len = ptr - line; 1260 if (len && *(ptr - 1) == '\r') --len; 1261 TRACE("// %s\n", debugstr_an(line, len)); 1262 line = ++ptr; 1263 } 1264 else ++ptr; 1265 } 1266 if (line != ptr) TRACE("// %s\n", debugstr_an(line, ptr - line)); 1267 } 1268 else TRACE("// %s\n", debugstr_an(comment, comment_size)); 1269 continue; 1270 } 1271 1272 fe->shader_read_opcode(fe_data, &ptr, &ins, ¶m_size); 1273 if (ins.handler_idx == WINED3DSIH_TABLE_SIZE) 1274 { 1275 TRACE("Skipping unrecognized instruction.\n"); 1276 ptr += param_size; 1277 continue; 1278 } 1279 1280 if (ins.handler_idx == WINED3DSIH_DCL) 1281 { 1282 struct wined3d_shader_semantic semantic; 1283 1284 fe->shader_read_semantic(&ptr, &semantic); 1285 1286 shader_dump_decl_usage(&semantic, &shader_version); 1287 shader_dump_ins_modifiers(&semantic.reg); 1288 TRACE(" "); 1289 shader_dump_dst_param(&semantic.reg, &shader_version); 1290 } 1291 else if (ins.handler_idx == WINED3DSIH_DEF) 1292 { 1293 struct wined3d_shader_src_param rel_addr; 1294 struct wined3d_shader_dst_param dst; 1295 1296 fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr); 1297 1298 TRACE("def c%u = %f, %f, %f, %f", shader_get_float_offset(dst.reg.type, dst.reg.idx), 1299 *(const float *)(ptr), 1300 *(const float *)(ptr + 1), 1301 *(const float *)(ptr + 2), 1302 *(const float *)(ptr + 3)); 1303 ptr += 4; 1304 } 1305 else if (ins.handler_idx == WINED3DSIH_DEFI) 1306 { 1307 struct wined3d_shader_src_param rel_addr; 1308 struct wined3d_shader_dst_param dst; 1309 1310 fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr); 1311 1312 TRACE("defi i%u = %d, %d, %d, %d", dst.reg.idx, 1313 *(ptr), 1314 *(ptr + 1), 1315 *(ptr + 2), 1316 *(ptr + 3)); 1317 ptr += 4; 1318 } 1319 else if (ins.handler_idx == WINED3DSIH_DEFB) 1320 { 1321 struct wined3d_shader_src_param rel_addr; 1322 struct wined3d_shader_dst_param dst; 1323 1324 fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr); 1325 1326 TRACE("defb b%u = %s", dst.reg.idx, *ptr ? "true" : "false"); 1327 ++ptr; 1328 } 1329 else 1330 { 1331 struct wined3d_shader_src_param dst_rel_addr, src_rel_addr; 1332 struct wined3d_shader_dst_param dst_param; 1333 struct wined3d_shader_src_param src_param; 1334 1335 if (ins.dst_count) 1336 { 1337 fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr); 1338 } 1339 1340 /* Print out predication source token first - it follows 1341 * the destination token. */ 1342 if (ins.predicate) 1343 { 1344 fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr); 1345 TRACE("("); 1346 shader_dump_src_param(&src_param, &shader_version); 1347 TRACE(") "); 1348 } 1349 1350 /* PixWin marks instructions with the coissue flag with a '+' */ 1351 if (ins.coissue) TRACE("+"); 1352 1353 TRACE("%s", shader_opcode_names[ins.handler_idx]); 1354 1355 if (ins.handler_idx == WINED3DSIH_IFC 1356 || ins.handler_idx == WINED3DSIH_BREAKC) 1357 { 1358 switch (ins.flags) 1359 { 1360 case COMPARISON_GT: TRACE("_gt"); break; 1361 case COMPARISON_EQ: TRACE("_eq"); break; 1362 case COMPARISON_GE: TRACE("_ge"); break; 1363 case COMPARISON_LT: TRACE("_lt"); break; 1364 case COMPARISON_NE: TRACE("_ne"); break; 1365 case COMPARISON_LE: TRACE("_le"); break; 1366 default: TRACE("_(%u)", ins.flags); 1367 } 1368 } 1369 else if (ins.handler_idx == WINED3DSIH_TEX 1370 && shader_version.major >= 2 1371 && (ins.flags & WINED3DSI_TEXLD_PROJECT)) 1372 { 1373 TRACE("p"); 1374 } 1375 1376 /* We already read the destination token, print it. */ 1377 if (ins.dst_count) 1378 { 1379 shader_dump_ins_modifiers(&dst_param); 1380 TRACE(" "); 1381 shader_dump_dst_param(&dst_param, &shader_version); 1382 } 1383 1384 /* Other source tokens */ 1385 for (i = ins.dst_count; i < (ins.dst_count + ins.src_count); ++i) 1386 { 1387 fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr); 1388 TRACE(!i ? " " : ", "); 1389 shader_dump_src_param(&src_param, &shader_version); 1390 } 1391 } 1392 TRACE("\n"); 1393 } 1394 } 1395 1396 static void shader_cleanup(IWineD3DBaseShader *iface) 1397 { 1398 IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)iface; 1399 1400 ((IWineD3DDeviceImpl *)shader->baseShader.device)->shader_backend->shader_destroy(iface); 1401 HeapFree(GetProcessHeap(), 0, shader->baseShader.reg_maps.constf); 1402 HeapFree(GetProcessHeap(), 0, shader->baseShader.function); 1403 shader_delete_constant_list(&shader->baseShader.constantsF); 1404 shader_delete_constant_list(&shader->baseShader.constantsB); 1405 shader_delete_constant_list(&shader->baseShader.constantsI); 1406 list_remove(&shader->baseShader.shader_list_entry); 1407 1408 if (shader->baseShader.frontend && shader->baseShader.frontend_data) 1409 { 1410 shader->baseShader.frontend->shader_free(shader->baseShader.frontend_data); 1411 } 1412 } 1413 1414 static void shader_none_handle_instruction(const struct wined3d_shader_instruction *ins) {} 1415 static void shader_none_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) {} 1416 static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {} 1417 static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {} 1418 static void shader_none_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) {} 1419 static void shader_none_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) {} 1420 static void shader_none_load_constants(const struct wined3d_context *context, char usePS, char useVS) {} 1421 static void shader_none_load_np2fixup_constants(IWineD3DDevice *iface, char usePS, char useVS) {} 1422 static void shader_none_destroy(IWineD3DBaseShader *iface) {} 1423 static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;} 1424 static void shader_none_free(IWineD3DDevice *iface) {} 1425 static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;} 1426 1427 static void shader_none_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps) 1428 { 1429 /* Set the shader caps to 0 for the none shader backend */ 1430 caps->VertexShaderVersion = 0; 1431 caps->PixelShaderVersion = 0; 1432 caps->PixelShader1xMaxValue = 0.0f; 1433 } 1434 1435 static BOOL shader_none_color_fixup_supported(struct color_fixup_desc fixup) 1436 { 1437 if (TRACE_ON(d3d_shader) && TRACE_ON(d3d)) 1438 { 1439 TRACE("Checking support for fixup:\n"); 1440 dump_color_fixup_desc(fixup); 1441 } 1442 1443 /* Faked to make some apps happy. */ 1444 if (!is_complex_fixup(fixup)) 1445 { 1446 TRACE("[OK]\n"); 1447 return TRUE; 1448 } 1449 1450 TRACE("[FAILED]\n"); 1451 return FALSE; 1452 } 1453 1454 const shader_backend_t none_shader_backend = { 1455 shader_none_handle_instruction, 1456 shader_none_select, 1457 shader_none_select_depth_blt, 1458 shader_none_deselect_depth_blt, 1459 shader_none_update_float_vertex_constants, 1460 shader_none_update_float_pixel_constants, 1461 shader_none_load_constants, 1462 shader_none_load_np2fixup_constants, 1463 shader_none_destroy, 1464 shader_none_alloc, 1465 shader_none_free, 1466 shader_none_dirty_const, 1467 shader_none_get_caps, 1468 shader_none_color_fixup_supported, 1469 }; 42 1470 43 1471 static void shader_get_parent(IWineD3DBaseShaderImpl *shader, IUnknown **parent)
Note:
See TracChangeset
for help on using the changeset viewer.