1 /* 2 * Copyright 2011-2019 Branimir Karadzic. All rights reserved. 3 * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause 4 */ 5 6 #include "bgfx_p.h" 7 #include "shader_dx9bc.h" 8 9 BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-parameter"); 10 BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG("-Wunneeded-internal-declaration"); 11 12 namespace bgfx 13 { 14 struct Dx9bcOpcodeInfo 15 { 16 uint8_t numOperands; 17 uint8_t numValues; 18 }; 19 20 static const Dx9bcOpcodeInfo s_dx9bcOpcodeInfo[] = 21 { 22 { 0, 0 }, // NOP 23 { 2, 0 }, // MOV 24 { 3, 0 }, // ADD 25 { 1, 0 }, // SUB 26 { 4, 0 }, // MAD 27 { 3, 0 }, // MUL 28 { 2, 0 }, // RCP 29 { 2, 0 }, // RSQ 30 { 3, 0 }, // DP3 31 { 3, 0 }, // DP4 32 { 3, 0 }, // MIN 33 { 3, 0 }, // MAX 34 { 3, 0 }, // SLT 35 { 3, 0 }, // SGE 36 { 2, 0 }, // EXP 37 { 2, 0 }, // LOG 38 { 1, 0 }, // LIT 39 { 1, 0 }, // DST 40 { 4, 0 }, // LRP 41 { 2, 0 }, // FRC 42 { 1, 0 }, // M4X4 43 { 1, 0 }, // M4X3 44 { 1, 0 }, // M3X4 45 { 1, 0 }, // M3X3 46 { 1, 0 }, // M3X2 47 { 0, 0 }, // CALL 48 { 0, 0 }, // CALLNZ 49 { 0, 0 }, // LOOP 50 { 0, 0 }, // RET 51 { 0, 0 }, // ENDLOOP 52 { 0, 0 }, // LABEL 53 { 1, 1 }, // DCL 54 { 3, 0 }, // POW 55 { 1, 0 }, // CRS 56 { 1, 0 }, // SGN 57 { 1, 0 }, // ABS 58 { 2, 0 }, // NRM 59 { 4, 0 }, // SINCOS 60 { 1, 0 }, // REP 61 { 0, 0 }, // ENDREP 62 { 1, 0 }, // IF 63 { 2, 0 }, // IFC 64 { 0, 0 }, // ELSE 65 { 0, 0 }, // ENDIF 66 { 0, 0 }, // BREAK 67 { 2, 0 }, // BREAKC 68 { 2, 0 }, // MOVA 69 { 1, 4 }, // DEFB 70 { 1, 4 }, // DEFI 71 { 0, 0 }, // 0 72 { 0, 0 }, // 1 73 { 0, 0 }, // 2 74 { 0, 0 }, // 3 75 { 0, 0 }, // 4 76 { 0, 0 }, // 5 77 { 0, 0 }, // 6 78 { 0, 0 }, // 7 79 { 0, 0 }, // 8 80 { 0, 0 }, // 9 81 { 0, 0 }, // 10 82 { 0, 0 }, // 11 83 { 0, 0 }, // 12 84 { 0, 0 }, // 13 85 { 0, 0 }, // 14 86 { 1, 0 }, // TEXCOORD 87 { 1, 0 }, // TEXKILL 88 { 3, 0 }, // TEX 89 { 1, 0 }, // TEXBEM 90 { 1, 0 }, // TEXBEM1 91 { 1, 0 }, // TEXREG2AR 92 { 1, 0 }, // TEXREG2GB 93 { 1, 0 }, // TEXM3X2PAD 94 { 1, 0 }, // TEXM3X2TEX 95 { 1, 0 }, // TEXM3X3PAD 96 { 1, 0 }, // TEXM3X3TEX 97 { 1, 0 }, // TEXM3X3DIFF 98 { 1, 0 }, // TEXM3X3SPEC 99 { 1, 0 }, // TEXM3X3VSPEC 100 { 2, 0 }, // EXPP 101 { 2, 0 }, // LOGP 102 { 4, 0 }, // CND 103 { 1, 4 }, // DEF 104 { 1, 0 }, // TEXREG2RGB 105 { 1, 0 }, // TEXDP3TEX 106 { 1, 0 }, // TEXM3X2DEPTH 107 { 1, 0 }, // TEXDP3 108 { 1, 0 }, // TEXM3X3 109 { 1, 0 }, // TEXDEPTH 110 { 4, 0 }, // CMP 111 { 1, 0 }, // BEM 112 { 4, 0 }, // DP2ADD 113 { 2, 0 }, // DSX 114 { 2, 0 }, // DSY 115 { 5, 0 }, // TEXLDD 116 { 1, 0 }, // SETP 117 { 3, 0 }, // TEXLDL 118 { 0, 0 }, // BREAKP 119 }; 120 BX_STATIC_ASSERT(BX_COUNTOF(s_dx9bcOpcodeInfo) == Dx9bcOpcode::Count); 121 122 static const char* s_dx9bcOpcode[] = 123 { 124 "nop", 125 "mov", 126 "add", 127 "sub", 128 "mad", 129 "mul", 130 "rcp", 131 "rsq", 132 "dp3", 133 "dp4", 134 "min", 135 "max", 136 "slt", 137 "sge", 138 "exp", 139 "log", 140 "lit", 141 "dst", 142 "lrp", 143 "frc", 144 "m4x4", 145 "m4x3", 146 "m3x4", 147 "m3x3", 148 "m3x2", 149 "call", 150 "callnz", 151 "loop", 152 "ret", 153 "endloop", 154 "label", 155 "dcl", 156 "pow", 157 "crs", 158 "sgn", 159 "abs", 160 "nrm", 161 "sincos", 162 "rep", 163 "endrep", 164 "if", 165 "ifc", 166 "else", 167 "endif", 168 "break", 169 "breakc", 170 "mova", 171 "defb", 172 "defi", 173 174 NULL, 175 NULL, 176 NULL, 177 NULL, 178 NULL, 179 NULL, 180 NULL, 181 NULL, 182 NULL, 183 NULL, 184 NULL, 185 NULL, 186 NULL, 187 NULL, 188 NULL, 189 190 "texcoord", 191 "texkill", 192 "tex", 193 "texbem", 194 "texbem1", 195 "texreg2ar", 196 "texreg2gb", 197 "texm3x2pad", 198 "texm3x2tex", 199 "texm3x3pad", 200 "texm3x3tex", 201 "texm3x3diff", 202 "texm3x3spec", 203 "texm3x3vspec", 204 "expp", 205 "logp", 206 "cnd", 207 "def", 208 "texreg2rgb", 209 "texdp3tex", 210 "texm3x2depth", 211 "texdp3", 212 "texm3x3", 213 "texdepth", 214 "cmp", 215 "bem", 216 "dp2add", 217 "dsx", 218 "dsy", 219 "texldd", 220 "setp", 221 "texldl", 222 "breakp", 223 }; 224 BX_STATIC_ASSERT(BX_COUNTOF(s_dx9bcOpcode) == Dx9bcOpcode::Count); 225 getName(Dx9bcOpcode::Enum _opcode)226 const char* getName(Dx9bcOpcode::Enum _opcode) 227 { 228 BX_CHECK(_opcode < Dx9bcOpcode::Count, "Unknown opcode id %d (%x).", _opcode, _opcode); 229 return s_dx9bcOpcode[_opcode]; 230 } 231 232 static const char* s_dx9bcOperandType[] = 233 { 234 "r", // Temporary Register File 235 "v", // Input Register File 236 "c", // Constant Register File 237 "t", // Texture Register File (PS) 238 "oPos", // Rasterizer Register File 239 "oD", // Attribute Output Register File 240 "oT", // Texture Coordinate Output Register File 241 "output", // Output register file for VS3.0+ 242 "i", // Constant Integer Vector Register File 243 "oColor", // Color Output Register File 244 "oDepth", // Depth Output Register File 245 "s", // Sampler State Register File 246 "c", // Constant Register File 2048 - 4095 247 "c", // Constant Register File 4096 - 6143 248 "c", // Constant Register File 6144 - 8191 249 "b", // Constant Boolean register file 250 "aL", // Loop counter register file 251 "tempfloat16", // 16-bit float temp register file 252 "misctype", // Miscellaneous (single) registers. 253 "label", // Label 254 "p", // Predicate register 255 }; 256 BX_STATIC_ASSERT(BX_COUNTOF(s_dx9bcOperandType) == Dx9bcOperandType::Count); 257 258 static const char* s_dx9bcDeclUsage[] = 259 { 260 "position", 261 "blendweight", 262 "blendindices", 263 "normal", 264 "psize", 265 "texcoord", 266 "tangent", 267 "binormal", 268 "tessfactor", 269 "positiont", 270 "color", 271 "fog", 272 "depth", 273 "sample", 274 }; 275 BX_STATIC_ASSERT(BX_COUNTOF(s_dx9bcDeclUsage) == Dx9bcDeclUsage::Count); 276 read(bx::ReaderI * _reader,Dx9bcSubOperand & _subOperand,bx::Error * _err)277 int32_t read(bx::ReaderI* _reader, Dx9bcSubOperand& _subOperand, bx::Error* _err) 278 { 279 int32_t size = 0; 280 281 uint32_t token; 282 size += bx::read(_reader, token, _err); 283 284 _subOperand.type = Dx9bcOperandType::Enum( ( (token & UINT32_C(0x70000000) ) >> 28) 285 | ( (token & UINT32_C(0x00001800) ) >> 8) ); 286 _subOperand.regIndex = (token & UINT32_C(0x000007ff) ); 287 _subOperand.swizzleBits = uint8_t( (token & UINT32_C(0x00ff0000) ) >> 16); 288 289 return size; 290 } 291 write(bx::WriterI * _writer,const Dx9bcSubOperand & _subOperand,bx::Error * _err)292 int32_t write(bx::WriterI* _writer, const Dx9bcSubOperand& _subOperand, bx::Error* _err) 293 { 294 int32_t size = 0; 295 296 uint32_t token = 0; 297 token |= (_subOperand.type << 28) & UINT32_C(0x70000000); 298 token |= (_subOperand.type << 8) & UINT32_C(0x00001800); 299 token |= _subOperand.regIndex & UINT32_C(0x000007ff); 300 token |= (_subOperand.swizzleBits << 16) & UINT32_C(0x00ff0000); 301 size += bx::write(_writer, token, _err); 302 303 return size; 304 } 305 read(bx::ReaderI * _reader,Dx9bcOperand & _operand,bx::Error * _err)306 int32_t read(bx::ReaderI* _reader, Dx9bcOperand& _operand, bx::Error* _err) 307 { 308 int32_t size = 0; 309 310 uint32_t token; 311 size += bx::read(_reader, token, _err); 312 313 _operand.type = Dx9bcOperandType::Enum( ( (token & UINT32_C(0x70000000) ) >> 28) 314 | ( (token & UINT32_C(0x00001800) ) >> 8) ); 315 _operand.regIndex = (token & UINT32_C(0x000007ff) ); 316 _operand.addrMode = Dx9bcOperandAddrMode::Enum( (token & UINT32_C(0x00002000) ) >> 13); 317 318 if (_operand.destination) 319 { 320 // Destination Parameter Token 321 // https://msdn.microsoft.com/en-us/library/ff552738.aspx 322 323 _operand.writeMask = uint8_t( (token & UINT32_C(0x000f0000) ) >> 16); 324 _operand.saturate = 0 != (token & UINT32_C(0x00100000) ); 325 _operand.partialPrecision = 0 != (token & UINT32_C(0x00200000) ); 326 _operand.centroid = 0 != (token & UINT32_C(0x00400000) ); 327 } 328 else 329 { 330 // Source Parameter Token 331 // https://msdn.microsoft.com/en-us/library/ff569716%28v=vs.85%29.aspx 332 333 _operand.writeMask = 0; 334 _operand.saturate = false; 335 _operand.partialPrecision = false; 336 _operand.centroid = false; 337 _operand.swizzleBits = uint8_t( (token & UINT32_C(0x00ff0000) ) >> 16); 338 } 339 340 if (Dx9bcOperandAddrMode::Relative == _operand.addrMode) 341 { 342 size += read(_reader, _operand.subOperand, _err); 343 } 344 345 return size; 346 } 347 write(bx::WriterI * _writer,const Dx9bcOperand & _operand,bx::Error * _err)348 int32_t write(bx::WriterI* _writer, const Dx9bcOperand& _operand, bx::Error* _err) 349 { 350 int32_t size = 0; 351 352 uint32_t token = 0; 353 token |= (_operand.type << 28) & UINT32_C(0x70000000); 354 token |= (_operand.type << 8) & UINT32_C(0x00001800); 355 token |= _operand.regIndex & UINT32_C(0x000007ff); 356 token |= (_operand.addrMode << 13) & UINT32_C(0x00002000); 357 size += bx::write(_writer, token, _err); 358 359 if (Dx9bcOperandAddrMode::Relative == _operand.addrMode) 360 { 361 size += write(_writer, _operand.subOperand, _err); 362 } 363 364 return size; 365 } 366 read(bx::ReaderI * _reader,Dx9bcInstruction & _instruction,bx::Error * _err)367 int32_t read(bx::ReaderI* _reader, Dx9bcInstruction& _instruction, bx::Error* _err) 368 { 369 int32_t size = 0; 370 371 uint32_t token; 372 size += bx::read(_reader, token, _err); 373 374 _instruction.opcode = Dx9bcOpcode::Enum( (token & UINT32_C(0x0000ffff) ) ); 375 376 if (Dx9bcOpcode::Comment == _instruction.opcode) 377 { 378 _instruction.specific = 0; 379 _instruction.length = uint16_t( (token & UINT32_C(0x7fff0000) ) >> 16) + 1; 380 _instruction.predicated = false; 381 _instruction.coissue = false; 382 } 383 else 384 { 385 _instruction.specific = uint8_t( (token & UINT32_C(0x00ff0000) ) >> 16); 386 _instruction.length = uint8_t( (token & UINT32_C(0x0f000000) ) >> 24) + 1; 387 _instruction.predicated = 0 != (token & UINT32_C(0x10000000) ); 388 _instruction.coissue = 0 != (token & UINT32_C(0x40000000) ); 389 } 390 391 if (Dx9bcOpcode::Count <= _instruction.opcode) 392 { 393 if (Dx9bcOpcode::Comment == _instruction.opcode) 394 { 395 for (int32_t ii = 0, num = _instruction.length-1; ii < num; ++ii) 396 { 397 uint32_t tmp; 398 size += bx::read(_reader, tmp, _err); 399 } 400 } 401 402 return size; 403 } 404 405 uint32_t currOp = 0; 406 407 const Dx9bcOpcodeInfo& info = s_dx9bcOpcodeInfo[bx::uint32_min(_instruction.opcode, Dx9bcOpcode::Count)]; 408 _instruction.numOperands = info.numOperands; 409 _instruction.numValues = info.numValues; 410 411 switch (_instruction.opcode) 412 { 413 case Dx9bcOpcode::SINCOS: 414 if (5 > _instruction.length) 415 { 416 _instruction.numOperands = 2; 417 } 418 break; 419 420 default: 421 break; 422 }; 423 424 //BX_TRACE("%d (%d), %d, %d, 0x%08x" 425 // , _instruction.opcode 426 // , bx::uint32_min(_instruction.opcode, Dx9bcOpcode::Count) 427 // , _instruction.length 428 // , _instruction.numOperands 429 // , token 430 // ); 431 432 const bool valuesBeforeOpcode = false 433 || Dx9bcOpcode::DCL == _instruction.opcode 434 ; 435 436 if (valuesBeforeOpcode 437 && 0 < info.numValues) 438 { 439 size += read(_reader, _instruction.value, info.numValues*sizeof(uint32_t), _err); 440 } 441 442 _instruction.operand[0].destination = true; 443 444 switch (_instruction.numOperands) 445 { 446 case 6: size += read(_reader, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 447 case 5: size += read(_reader, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 448 case 4: size += read(_reader, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 449 case 3: size += read(_reader, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 450 case 2: size += read(_reader, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 451 case 1: size += read(_reader, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 452 case 0: 453 if (!valuesBeforeOpcode 454 && 0 < info.numValues) 455 { 456 size += read(_reader, _instruction.value, info.numValues*sizeof(uint32_t), _err); 457 } 458 break; 459 460 default: 461 BX_CHECK(false, "Instruction %s with invalid number of operands %d (numValues %d)." 462 , getName(_instruction.opcode) 463 , _instruction.numOperands 464 , info.numValues 465 ); 466 break; 467 } 468 469 return size; 470 } 471 write(bx::WriterI * _writer,const Dx9bcInstruction & _instruction,bx::Error * _err)472 int32_t write(bx::WriterI* _writer, const Dx9bcInstruction& _instruction, bx::Error* _err) 473 { 474 int32_t size = 0; 475 476 uint32_t token = 0; 477 token |= _instruction.opcode & UINT32_C(0x0000ffff); 478 token |= (_instruction.specific << 16) & UINT32_C(0x00ff0000); 479 token |= ( (_instruction.length - 1) << 24) & UINT32_C(0x0f000000); 480 size += bx::write(_writer, token, _err); 481 482 uint32_t currOp = 0; 483 switch (_instruction.numOperands) 484 { 485 case 6: size += write(_writer, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 486 case 5: size += write(_writer, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 487 case 4: size += write(_writer, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 488 case 3: size += write(_writer, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 489 case 2: size += write(_writer, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 490 case 1: size += write(_writer, _instruction.operand[currOp++], _err); BX_FALLTHROUGH; 491 case 0: 492 break; 493 } 494 495 return 0; 496 } 497 toString(char * _out,int32_t _size,const Dx9bcInstruction & _instruction)498 int32_t toString(char* _out, int32_t _size, const Dx9bcInstruction& _instruction) 499 { 500 int32_t size = 0; 501 502 if (Dx9bcOpcode::Comment == _instruction.opcode 503 || Dx9bcOpcode::Phase == _instruction.opcode) 504 { 505 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 506 , "// %x" 507 , _instruction.opcode 508 ); 509 return size; 510 } 511 512 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 513 , "%2d %s" 514 , _instruction.opcode 515 , getName(_instruction.opcode) 516 ); 517 518 switch (_instruction.opcode) 519 { 520 case Dx9bcOpcode::DCL: 521 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 522 , "_%s%d (%d, %d, %d, %d)" 523 , s_dx9bcDeclUsage[_instruction.value[0] & UINT32_C(0x0000000f)] 524 , (_instruction.value[0] & UINT32_C(0x000f0000) )>>16 525 , (_instruction.value[0] & UINT32_C(0x08000000) )>>27 // ? 526 , (_instruction.value[0] & UINT32_C(0x10000000) )>>28 // texture2d 527 , (_instruction.value[0] & UINT32_C(0x20000000) )>>29 // textureCube 528 , (_instruction.value[0] & UINT32_C(0x40000000) )>>30 // texture3d 529 ); 530 break; 531 532 default: 533 break; 534 } 535 536 for (uint32_t ii = 0; ii < _instruction.numOperands; ++ii) 537 { 538 const Dx9bcOperand& operand = _instruction.operand[ii]; 539 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 540 , "%s%s%d" 541 , 0 == ii ? " " : ", " 542 , s_dx9bcOperandType[operand.type] 543 , operand.regIndex 544 ); 545 546 if (operand.destination) 547 { 548 if (0xf > operand.writeMask 549 && 0 < operand.writeMask) 550 { 551 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 552 , ".%s%s%s%s" 553 , 0 == (operand.writeMask & 1) ? "" : "x" 554 , 0 == (operand.writeMask & 2) ? "" : "y" 555 , 0 == (operand.writeMask & 4) ? "" : "z" 556 , 0 == (operand.writeMask & 8) ? "" : "w" 557 ); 558 } 559 } 560 else 561 { 562 if (Dx9bcOperandAddrMode::Relative == operand.addrMode) 563 { 564 const bool array = true; 565 566 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 567 , "[" 568 ); 569 570 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 571 , "%s%d" 572 , s_dx9bcOperandType[operand.subOperand.type] 573 , operand.subOperand.regIndex 574 ); 575 576 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 577 , "%s" 578 , array ? "]" : "" 579 ); 580 } 581 582 if (0xe4 != operand.swizzleBits) 583 { 584 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 585 , ".%c%c%c%c" 586 , "xyzw"[(operand.swizzleBits )&0x3] 587 , "xyzw"[(operand.swizzleBits>>2)&0x3] 588 , "xyzw"[(operand.swizzleBits>>4)&0x3] 589 , "xyzw"[(operand.swizzleBits>>6)&0x3] 590 ); 591 } 592 } 593 } 594 595 switch (_instruction.opcode) 596 { 597 case Dx9bcOpcode::DEF: 598 for (uint32_t jj = 0; jj < _instruction.numValues; ++jj) 599 { 600 union { int32_t i; float f; } cast = { _instruction.value[jj] }; 601 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 602 , "%s%f%s" 603 , 0 == jj ? " (" : ", " 604 , cast.f 605 , uint32_t(_instruction.numValues-1) == jj ? ")" : "" 606 ); 607 } 608 break; 609 610 case Dx9bcOpcode::DEFI: 611 for (uint32_t jj = 0; jj < _instruction.numValues; ++jj) 612 { 613 size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size) 614 , "%s%d%s" 615 , 0 == jj ? " (" : ", " 616 , _instruction.value[jj] 617 , uint32_t(_instruction.numValues-1) == jj ? ")" : "" 618 ); 619 } 620 break; 621 622 default: 623 break; 624 } 625 626 return size; 627 } 628 read(bx::ReaderSeekerI * _reader,Dx9bcShader & _shader,bx::Error * _err)629 int32_t read(bx::ReaderSeekerI* _reader, Dx9bcShader& _shader, bx::Error* _err) 630 { 631 int32_t size = 0; 632 int64_t offset = bx::seek(_reader); 633 634 for (;;) 635 { 636 Dx9bcInstruction instruction; 637 int32_t length = read(_reader, instruction, _err); 638 size += length; 639 640 if (Dx9bcOpcode::Count > instruction.opcode) 641 { 642 char temp[512]; 643 toString(temp, 512, instruction); 644 645 BX_CHECK(length/4 == instruction.length 646 , "%s\nread %d, expected %d" 647 , temp 648 , length/4 649 , instruction.length 650 ); 651 } 652 else 653 { 654 if (Dx9bcOpcode::End == instruction.opcode) 655 { 656 size -= length; 657 break; 658 } 659 } 660 } 661 662 bx::seek(_reader, offset, bx::Whence::Begin); 663 664 _shader.byteCode.resize(size); 665 bx::read(_reader, _shader.byteCode.data(), size, _err); 666 667 return size; 668 } 669 write(bx::WriterI * _writer,const Dx9bcShader & _shader,bx::Error * _err)670 int32_t write(bx::WriterI* _writer, const Dx9bcShader& _shader, bx::Error* _err) 671 { 672 BX_UNUSED(_writer, _shader, _err); 673 return 0; 674 } 675 read(bx::ReaderSeekerI * _reader,Dx9bc & _bc,bx::Error * _err)676 int32_t read(bx::ReaderSeekerI* _reader, Dx9bc& _bc, bx::Error* _err) 677 { 678 int32_t size = 0; 679 680 size += bx::read(_reader, _bc.version, _err); 681 682 bool pixelShader = (0xffff0000 == (_bc.version & 0xffff0000) ); 683 uint32_t versionMajor = (_bc.version>>8)&0xff; 684 uint32_t versionMinor = _bc.version&0xff; 685 BX_UNUSED(pixelShader, versionMajor, versionMinor); 686 BX_TRACE("%s shader %d.%d" 687 , pixelShader ? "pixel" : "vertex" 688 , versionMajor 689 , versionMinor 690 ); 691 692 size += read(_reader, _bc.shader, _err); 693 694 return size; 695 } 696 write(bx::WriterSeekerI * _writer,const Dx9bc & _dxbc,bx::Error * _err)697 int32_t write(bx::WriterSeekerI* _writer, const Dx9bc& _dxbc, bx::Error* _err) 698 { 699 BX_UNUSED(_writer, _dxbc, _err); 700 return 0; 701 } 702 parse(const Dx9bcShader & _src,Dx9bcParseFn _fn,void * _userData,bx::Error * _err)703 void parse(const Dx9bcShader& _src, Dx9bcParseFn _fn, void* _userData, bx::Error* _err) 704 { 705 BX_ERROR_SCOPE(_err); 706 707 bx::MemoryReader reader(_src.byteCode.data(), uint32_t(_src.byteCode.size() ) ); 708 709 bx::Error err; 710 711 for (uint32_t token = 0, numTokens = uint32_t(_src.byteCode.size() / sizeof(uint32_t) ); token < numTokens;) 712 { 713 Dx9bcInstruction instruction; 714 uint32_t size = read(&reader, instruction, _err); 715 BX_CHECK(size/4 == instruction.length, "read %d, expected %d", size/4, instruction.length); BX_UNUSED(size); 716 717 bool cont = _fn(token * sizeof(uint32_t), instruction, _userData); 718 if (!cont) 719 { 720 return; 721 } 722 723 token += instruction.length; 724 } 725 } 726 filter(Dx9bcShader & _dst,const Dx9bcShader & _src,Dx9bcFilterFn _fn,void * _userData,bx::Error * _err)727 void filter(Dx9bcShader& _dst, const Dx9bcShader& _src, Dx9bcFilterFn _fn, void* _userData, bx::Error* _err) 728 { 729 BX_ERROR_SCOPE(_err); 730 731 bx::MemoryReader reader(_src.byteCode.data(), uint32_t(_src.byteCode.size() ) ); 732 733 bx::MemoryBlock mb(g_allocator); 734 bx::MemoryWriter writer(&mb); 735 736 for (uint32_t token = 0, numTokens = uint32_t(_src.byteCode.size() / sizeof(uint32_t) ); token < numTokens;) 737 { 738 Dx9bcInstruction instruction; 739 uint32_t size = read(&reader, instruction, _err); 740 BX_CHECK(size/4 == instruction.length, "read %d, expected %d", size/4, instruction.length); BX_UNUSED(size); 741 742 _fn(instruction, _userData); 743 744 write(&writer, instruction, _err); 745 746 token += instruction.length; 747 } 748 749 uint8_t* data = (uint8_t*)mb.more(); 750 uint32_t size = uint32_t(bx::getSize(&writer) ); 751 _dst.byteCode.reserve(size); 752 bx::memCopy(_dst.byteCode.data(), data, size); 753 } 754 755 } // namespace bgfx 756