Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2012 lines
63 KiB

  1. #if 0 // this whole thing is turned off...
  2. //------------------------------------------------------------------------------
  3. // DX9AsmToGL.cpp
  4. //------------------------------------------------------------------------------
  5. #include "dxabstract.h"
  6. #include "tier0/dbg.h"
  7. #include "tier1/strtools.h"
  8. #include "tier1/utlbuffer.h"
  9. #include "DX9AsmToGL.h"
  10. #ifdef POSIX
  11. #include "glmgr/glmgrbasics.h"
  12. #else
  13. // normally we would get this form glmgr.h. on a non-POSIX build of this code, we just sneak it in here
  14. #define kGLMUserClipPlaneParamBase 253
  15. #endif
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. #ifdef POSIX
  19. #define strcat_s( a, b, c) V_strcat( a, c, b )
  20. #endif
  21. #define DST_REGISTER 0
  22. #define SRC_REGISTER 1
  23. // Tracking and naming sampler dimensions
  24. #define SAMPLER_TYPE_2D 0
  25. #define SAMPLER_TYPE_CUBE 1
  26. #define SAMPLER_TYPE_3D 2
  27. // Code for which component of the "dummy" address register is needed by an instruction
  28. #define ARL_DEST_NONE -1
  29. #define ARL_DEST_X 0
  30. #define ARL_DEST_Y 1
  31. #define ARL_DEST_Z 2
  32. #define ARL_DEST_W 3
  33. #ifndef POSIX
  34. #define Debugger() Assert(0)
  35. #endif
  36. char g_pSamplerStrings[3][5] = { "2D", "CUBE", "3D" };
  37. float uint32ToFloat_ASM( uint32 dw )
  38. {
  39. return *((float*)&dw);
  40. }
  41. uint32 D3DToGL_ASM::GetNextToken( void )
  42. {
  43. uint32 dwToken = *m_pdwNextToken;
  44. m_pdwNextToken++;
  45. return dwToken;
  46. }
  47. void D3DToGL_ASM::SkipTokens( uint32 numToSkip )
  48. {
  49. m_pdwNextToken += numToSkip;
  50. }
  51. uint32 D3DToGL_ASM::Opcode( uint32 dwToken )
  52. {
  53. return ( dwToken & D3DSI_OPCODE_MASK );
  54. }
  55. uint32 D3DToGL_ASM::OpcodeSpecificData (uint32 dwToken)
  56. {
  57. return ( ( dwToken & D3DSP_OPCODESPECIFICCONTROL_MASK ) >> D3DSP_OPCODESPECIFICCONTROL_SHIFT );
  58. }
  59. uint32 D3DToGL_ASM::TextureType ( uint32 dwToken )
  60. {
  61. return ( dwToken & D3DSP_TEXTURETYPE_MASK ); // Note this one doesn't shift due to weird D3DSAMPLER_TEXTURE_TYPE enum
  62. }
  63. // Print GLSL intrinsic corresponding to particular instruction
  64. void D3DToGL_ASM::OpenIntrinsic( uint32 inst, char* buff, int nBufLen )
  65. {
  66. switch ( inst )
  67. {
  68. case D3DSIO_RSQ:
  69. V_snprintf( buff, nBufLen, "inversesqrt( " );
  70. break;
  71. case D3DSIO_DP3:
  72. case D3DSIO_DP4:
  73. V_snprintf( buff, nBufLen, "dot( " );
  74. break;
  75. case D3DSIO_MIN:
  76. V_snprintf( buff, nBufLen, "min( " );
  77. break;
  78. case D3DSIO_MAX:
  79. V_snprintf( buff, nBufLen, "max( " );
  80. break;
  81. case D3DSIO_SLT:
  82. V_snprintf( buff, nBufLen, "lessThan( " );
  83. break;
  84. case D3DSIO_SGE:
  85. V_snprintf( buff, nBufLen, "greaterThan( " );
  86. break;
  87. case D3DSIO_EXP:
  88. V_snprintf( buff, nBufLen, "exp( " ); // exp2 ?
  89. break;
  90. case D3DSIO_LOG:
  91. V_snprintf( buff, nBufLen, "log( " ); // log2 ?
  92. break;
  93. case D3DSIO_LIT:
  94. Assert(0);
  95. V_snprintf( buff, nBufLen, "lit( " ); // gonna have to write this one
  96. break;
  97. case D3DSIO_DST:
  98. Assert(0);
  99. V_snprintf( buff, nBufLen, "dst( " ); // gonna have to write this one
  100. break;
  101. case D3DSIO_LRP:
  102. Assert( !m_bVertexShader );
  103. V_snprintf( buff, nBufLen, "mix( " );
  104. break;
  105. case D3DSIO_FRC:
  106. V_snprintf( buff, nBufLen, "fract( " );
  107. break;
  108. case D3DSIO_M4x4:
  109. Assert(0);
  110. V_snprintf( buff, nBufLen, "m4x4" );
  111. break;
  112. case D3DSIO_M4x3:
  113. case D3DSIO_M3x4:
  114. case D3DSIO_M3x3:
  115. case D3DSIO_M3x2:
  116. case D3DSIO_CALL:
  117. case D3DSIO_CALLNZ:
  118. case D3DSIO_LOOP:
  119. case D3DSIO_RET:
  120. case D3DSIO_ENDLOOP:
  121. case D3DSIO_LABEL:
  122. case D3DSIO_DCL:
  123. Assert(0);
  124. break;
  125. case D3DSIO_POW:
  126. V_snprintf( buff, nBufLen, "pow( " );
  127. break;
  128. case D3DSIO_CRS:
  129. V_snprintf( buff, nBufLen, "cross( " );
  130. break;
  131. case D3DSIO_SGN:
  132. Assert(0);
  133. V_snprintf( buff, nBufLen, "sign( " );
  134. break;
  135. case D3DSIO_ABS:
  136. V_snprintf( buff, nBufLen, "abs( " );
  137. break;
  138. case D3DSIO_NRM:
  139. Assert( 0 );
  140. V_snprintf( buff, nBufLen, "normalize( " );
  141. break;
  142. case D3DSIO_SINCOS:
  143. Assert( 0 );
  144. V_snprintf( buff, nBufLen, "sincos( " ); // gonna have to write this one
  145. break;
  146. case D3DSIO_REP:
  147. case D3DSIO_ENDREP:
  148. case D3DSIO_IF:
  149. case D3DSIO_IFC:
  150. case D3DSIO_ELSE:
  151. case D3DSIO_ENDIF:
  152. case D3DSIO_BREAK:
  153. case D3DSIO_BREAKC: // TODO: these are the reason we even need GLSL...gotta make these work
  154. Assert(0);
  155. break;
  156. case D3DSIO_DEFB:
  157. case D3DSIO_DEFI:
  158. Assert(0);
  159. break;
  160. case D3DSIO_TEXCOORD:
  161. V_snprintf( buff, nBufLen, "texcoord" );
  162. break;
  163. case D3DSIO_TEXKILL:
  164. V_snprintf( buff, nBufLen, "kill( " ); // wrap the discard instruction?
  165. break;
  166. case D3DSIO_TEX:
  167. Assert(0);
  168. V_snprintf( buff, nBufLen, "TEX" ); // We shouldn'g get here
  169. break;
  170. case D3DSIO_TEXBEM:
  171. case D3DSIO_TEXBEML:
  172. case D3DSIO_TEXREG2AR:
  173. case D3DSIO_TEXREG2GB:
  174. case D3DSIO_TEXM3x2PAD:
  175. case D3DSIO_TEXM3x2TEX:
  176. case D3DSIO_TEXM3x3PAD:
  177. case D3DSIO_TEXM3x3TEX:
  178. case D3DSIO_TEXM3x3SPEC:
  179. case D3DSIO_TEXM3x3VSPEC:
  180. Assert(0);
  181. break;
  182. case D3DSIO_EXPP:
  183. V_snprintf( buff, nBufLen, "exp( " );
  184. break;
  185. case D3DSIO_LOGP:
  186. V_snprintf( buff, nBufLen, "log( " );
  187. break;
  188. case D3DSIO_CND:
  189. Assert(0);
  190. break;
  191. case D3DSIO_DEF:
  192. Assert(0);
  193. V_snprintf( buff, nBufLen, "DEF" );
  194. break;
  195. case D3DSIO_TEXREG2RGB:
  196. case D3DSIO_TEXDP3TEX:
  197. case D3DSIO_TEXM3x2DEPTH:
  198. case D3DSIO_TEXDP3:
  199. case D3DSIO_TEXM3x3:
  200. Assert(0);
  201. break;
  202. case D3DSIO_TEXDEPTH:
  203. V_snprintf( buff, nBufLen, "texdepth" );
  204. break;
  205. case D3DSIO_CMP:
  206. Assert(0);
  207. Assert( !m_bVertexShader );
  208. V_snprintf( buff, nBufLen, "CMP" );
  209. break;
  210. case D3DSIO_BEM:
  211. Assert(0);
  212. break;
  213. case D3DSIO_DP2ADD:
  214. Assert(0);
  215. break;
  216. case D3DSIO_DSX:
  217. case D3DSIO_DSY:
  218. Assert(0);
  219. break;
  220. case D3DSIO_TEXLDD:
  221. V_snprintf( buff, nBufLen, "texldd" );
  222. break;
  223. case D3DSIO_SETP:
  224. Assert(0);
  225. break;
  226. case D3DSIO_TEXLDL:
  227. V_snprintf( buff, nBufLen, "texldl" );
  228. break;
  229. case D3DSIO_BREAKP:
  230. case D3DSIO_PHASE:
  231. Assert(0);
  232. break;
  233. }
  234. }
  235. // Print ASM opcode
  236. void D3DToGL_ASM::PrintOpcode( uint32 inst, char* buff, int nBufLen )
  237. {
  238. switch ( inst )
  239. {
  240. case D3DSIO_NOP:
  241. V_snprintf( buff, nBufLen, "NOP" );
  242. Assert(0);
  243. break;
  244. case D3DSIO_MOV:
  245. V_snprintf( buff, nBufLen, "MOV" );
  246. break;
  247. case D3DSIO_ADD:
  248. V_snprintf( buff, nBufLen, "ADD" );
  249. break;
  250. case D3DSIO_SUB:
  251. V_snprintf( buff, nBufLen, "SUB" );
  252. break;
  253. case D3DSIO_MAD:
  254. V_snprintf( buff, nBufLen, "MAD" );
  255. break;
  256. case D3DSIO_MUL:
  257. V_snprintf( buff, nBufLen, "MUL" );
  258. break;
  259. case D3DSIO_RCP:
  260. V_snprintf( buff, nBufLen, "RCP" );
  261. break;
  262. case D3DSIO_RSQ:
  263. V_snprintf( buff, nBufLen, "RSQ" );
  264. break;
  265. case D3DSIO_DP3:
  266. V_snprintf( buff, nBufLen, "DP3" );
  267. break;
  268. case D3DSIO_DP4:
  269. V_snprintf( buff, nBufLen, "DP4" );
  270. break;
  271. case D3DSIO_MIN:
  272. V_snprintf( buff, nBufLen, "MIN" );
  273. break;
  274. case D3DSIO_MAX:
  275. V_snprintf( buff, nBufLen, "MAX" );
  276. break;
  277. case D3DSIO_SLT:
  278. V_snprintf( buff, nBufLen, "SLT" );
  279. break;
  280. case D3DSIO_SGE:
  281. V_snprintf( buff, nBufLen, "SGE" );
  282. break;
  283. case D3DSIO_EXP:
  284. V_snprintf( buff, nBufLen, "EX2" );
  285. break;
  286. case D3DSIO_LOG:
  287. V_snprintf( buff, nBufLen, "LG2" );
  288. break;
  289. case D3DSIO_LIT:
  290. V_snprintf( buff, nBufLen, "LIT" );
  291. break;
  292. case D3DSIO_DST:
  293. V_snprintf( buff, nBufLen, "DST" );
  294. break;
  295. case D3DSIO_LRP:
  296. Assert( !m_bVertexShader );
  297. V_snprintf( buff, nBufLen, "LRP" );
  298. break;
  299. case D3DSIO_FRC:
  300. V_snprintf( buff, nBufLen, "FRC" );
  301. break;
  302. case D3DSIO_M4x4:
  303. V_snprintf( buff, nBufLen, "m4x4" );
  304. break;
  305. case D3DSIO_M4x3:
  306. case D3DSIO_M3x4:
  307. case D3DSIO_M3x3:
  308. case D3DSIO_M3x2:
  309. case D3DSIO_CALL:
  310. case D3DSIO_CALLNZ:
  311. case D3DSIO_LOOP:
  312. case D3DSIO_RET:
  313. case D3DSIO_ENDLOOP:
  314. case D3DSIO_LABEL:
  315. Assert(0);
  316. break;
  317. case D3DSIO_DCL:
  318. V_snprintf( buff, nBufLen, "DCL" );
  319. break;
  320. case D3DSIO_POW:
  321. V_snprintf( buff, nBufLen, "POW" );
  322. break;
  323. case D3DSIO_CRS:
  324. V_snprintf( buff, nBufLen, "XPD" );
  325. break;
  326. case D3DSIO_SGN:
  327. Assert(0);
  328. V_snprintf( buff, nBufLen, "SGN" );
  329. break;
  330. case D3DSIO_ABS:
  331. V_snprintf( buff, nBufLen, "ABS" );
  332. break;
  333. case D3DSIO_NRM:
  334. Assert( 0 );
  335. V_snprintf( buff, nBufLen, "NRM" );
  336. break;
  337. case D3DSIO_SINCOS:
  338. Assert( !m_bVertexShader );
  339. V_snprintf( buff, nBufLen, "SCS" );
  340. break;
  341. case D3DSIO_REP:
  342. case D3DSIO_ENDREP:
  343. case D3DSIO_IF:
  344. case D3DSIO_IFC:
  345. case D3DSIO_ELSE:
  346. case D3DSIO_ENDIF:
  347. case D3DSIO_BREAK:
  348. case D3DSIO_BREAKC:
  349. Assert(0);
  350. break;
  351. case D3DSIO_MOVA:
  352. Assert( m_bVertexShader );
  353. V_snprintf( buff, nBufLen, "MOV" ); // We're always moving into a temp instead, so this is MOV instead of ARL
  354. break;
  355. case D3DSIO_DEFB:
  356. case D3DSIO_DEFI:
  357. Assert(0);
  358. break;
  359. case D3DSIO_TEXCOORD:
  360. V_snprintf( buff, nBufLen, "texcoord" );
  361. break;
  362. case D3DSIO_TEXKILL:
  363. V_snprintf( buff, nBufLen, "KIL" );
  364. break;
  365. case D3DSIO_TEX:
  366. V_snprintf( buff, nBufLen, "TEX" );
  367. break;
  368. case D3DSIO_TEXBEM:
  369. case D3DSIO_TEXBEML:
  370. case D3DSIO_TEXREG2AR:
  371. case D3DSIO_TEXREG2GB:
  372. case D3DSIO_TEXM3x2PAD:
  373. case D3DSIO_TEXM3x2TEX:
  374. case D3DSIO_TEXM3x3PAD:
  375. case D3DSIO_TEXM3x3TEX:
  376. case D3DSIO_TEXM3x3SPEC:
  377. case D3DSIO_TEXM3x3VSPEC:
  378. Assert(0);
  379. break;
  380. case D3DSIO_EXPP:
  381. V_snprintf( buff, nBufLen, "EXP" );
  382. break;
  383. case D3DSIO_LOGP:
  384. V_snprintf( buff, nBufLen, "LOG" );
  385. break;
  386. case D3DSIO_CND:
  387. Assert(0);
  388. break;
  389. case D3DSIO_DEF:
  390. V_snprintf( buff, nBufLen, "DEF" );
  391. break;
  392. case D3DSIO_TEXREG2RGB:
  393. case D3DSIO_TEXDP3TEX:
  394. case D3DSIO_TEXM3x2DEPTH:
  395. case D3DSIO_TEXDP3:
  396. case D3DSIO_TEXM3x3:
  397. Assert(0);
  398. break;
  399. case D3DSIO_TEXDEPTH:
  400. V_snprintf( buff, nBufLen, "texdepth" );
  401. break;
  402. case D3DSIO_CMP:
  403. Assert( !m_bVertexShader );
  404. V_snprintf( buff, nBufLen, "CMP" );
  405. break;
  406. case D3DSIO_BEM:
  407. Assert(0);
  408. break;
  409. case D3DSIO_DP2ADD:
  410. Assert(0);
  411. break;
  412. case D3DSIO_DSX:
  413. case D3DSIO_DSY:
  414. Assert(0);
  415. break;
  416. case D3DSIO_TEXLDD:
  417. V_snprintf( buff, nBufLen, "texldd" );
  418. break;
  419. case D3DSIO_SETP:
  420. Assert(0);
  421. break;
  422. case D3DSIO_TEXLDL:
  423. V_snprintf( buff, nBufLen, "texldl" );
  424. break;
  425. case D3DSIO_BREAKP:
  426. case D3DSIO_PHASE:
  427. Assert(0);
  428. break;
  429. }
  430. }
  431. //------------------------------------------------------------------------------
  432. // Helper function which prints ASCII representation of usage-usageindex pair to string
  433. //
  434. // Strictly used by vertex shaders
  435. // not used any more now that we have attribmap metadata
  436. //------------------------------------------------------------------------------
  437. void D3DToGL_ASM::PrintUsageAndIndexToString( uint32 dwToken, char* strUsageUsageIndexName, int nBufLen, bool bGLSL )
  438. {
  439. uint32 dwUsage = ( dwToken & D3DSP_DCL_USAGE_MASK );
  440. uint32 dwUsageIndex = ( dwToken & D3DSP_DCL_USAGEINDEX_MASK ) >> D3DSP_DCL_USAGEINDEX_SHIFT;
  441. switch ( dwUsage )
  442. {
  443. case D3DDECLUSAGE_POSITION:
  444. V_snprintf( strUsageUsageIndexName, nBufLen, "vertex.attrib[0]" ); //"vertex.position" ); // aka generic [0]
  445. break;
  446. case D3DDECLUSAGE_BLENDWEIGHT:
  447. V_snprintf( strUsageUsageIndexName, nBufLen, "vertex.attrib[1]" ); // "vertex.attrib[12]" ); // or [1]
  448. break;
  449. case D3DDECLUSAGE_BLENDINDICES:
  450. V_snprintf( strUsageUsageIndexName, nBufLen, "vertex.attrib[13]" ); // "vertex.attrib[13]" ); // or [ 7 ]
  451. break;
  452. case D3DDECLUSAGE_NORMAL:
  453. V_snprintf( strUsageUsageIndexName, nBufLen, "vertex.attrib[2]" ); // "vertex.normal" ); // aka [ 2 ]
  454. break;
  455. case D3DDECLUSAGE_PSIZE:
  456. Assert(0);
  457. V_snprintf( strUsageUsageIndexName, nBufLen, "_psize" ); // no analog
  458. break;
  459. case D3DDECLUSAGE_TEXCOORD:
  460. V_snprintf( strUsageUsageIndexName, nBufLen, "vertex.attrib[%d]", 8+dwUsageIndex ); // "vertex.texcoord[%d]", dwUsageIndex ); // aka [8] - [15] ?
  461. break;
  462. case D3DDECLUSAGE_TANGENT:
  463. V_snprintf( strUsageUsageIndexName, nBufLen, "vertex.attrib[15]" ); // aka texc[7]
  464. break;
  465. case D3DDECLUSAGE_BINORMAL:
  466. V_snprintf( strUsageUsageIndexName, nBufLen, "vertex.attrib[14]" ); // aka texc[6]
  467. break;
  468. // case D3DDECLUSAGE_TESSFACTOR:
  469. // Assert(0);
  470. // V_snprintf( strUsageUsageIndexName, nBufLen, "_position" ); // no analog
  471. // break;
  472. // case D3DDECLUSAGE_POSITIONT:
  473. // Assert(0);
  474. // V_snprintf( strUsageUsageIndexName, nBufLen, "_positiont" ); // no analog
  475. // break;
  476. case D3DDECLUSAGE_COLOR:
  477. V_snprintf( strUsageUsageIndexName, nBufLen, "vertex.attrib[%d]", 3+dwUsageIndex ); //dwUsageIndex ); // != 0 ? "vertex.color.secondary" : "vertex.color" ); // aka [3] / [4] (second)
  478. break;
  479. case D3DDECLUSAGE_FOG:
  480. V_snprintf( strUsageUsageIndexName, nBufLen, "vertex.attrib[5]" ); //"vertex.position" /* "_fog" */ ); //FIXME, evil // aka [5] / vertex.fogcoord
  481. break;
  482. case D3DDECLUSAGE_DEPTH:
  483. Assert(0);
  484. V_snprintf( strUsageUsageIndexName, nBufLen, "_depth" ); // no analog
  485. break;
  486. case D3DDECLUSAGE_SAMPLE:
  487. Assert(0);
  488. V_snprintf( strUsageUsageIndexName, nBufLen, "_sample" ); // no analog
  489. break;
  490. default:
  491. Debugger();
  492. break;
  493. }
  494. }
  495. uint32 D3DToGL_ASM::GetRegType( uint32 dwRegToken )
  496. {
  497. return ( ( dwRegToken & D3DSP_REGTYPE_MASK2 ) >> D3DSP_REGTYPE_SHIFT2 ) | ( ( dwRegToken & D3DSP_REGTYPE_MASK ) >> D3DSP_REGTYPE_SHIFT );
  498. }
  499. void D3DToGL_ASM::PrintIndentation( char *pBuf, int nBufLen )
  500. {
  501. for( int i=0; i<m_NumIndentTabs; i++ )
  502. {
  503. strcat_s( pBuf, nBufLen, "\t" );
  504. }
  505. }
  506. void D3DToGL_ASM::FlagIndirectRegister( uint32 dwToken, int *pARLDestReg )
  507. {
  508. switch ( dwToken & D3DVS_SWIZZLE_MASK & D3DVS_X_W )
  509. {
  510. case D3DVS_X_X:
  511. *pARLDestReg = ARL_DEST_X;
  512. break;
  513. case D3DVS_X_Y:
  514. *pARLDestReg = ARL_DEST_Y;
  515. break;
  516. case D3DVS_X_Z:
  517. *pARLDestReg = ARL_DEST_Z;
  518. break;
  519. case D3DVS_X_W:
  520. *pARLDestReg = ARL_DEST_W;
  521. break;
  522. }
  523. }
  524. //------------------------------------------------------------------------------
  525. // PrintParameterToString()
  526. //
  527. // Helper function which prints ASCII representation of passed Parameter dwToken
  528. // to string. Token defines parameter details. The dwSourceOrDest parameter says
  529. // whether or not this is a source or destination register
  530. //------------------------------------------------------------------------------
  531. void D3DToGL_ASM::PrintParameterToString ( uint32 dwToken, uint32 dwSourceOrDest, char *pRegisterName, int nBufLen, bool bGLSL, int *pARLDestReg = NULL )
  532. {
  533. char buff[32];
  534. bool bAllowWriteMask = true;
  535. uint32 dwRegNum = dwToken & D3DSP_REGNUM_MASK;
  536. uint32 dwRegType, dwSwizzle;
  537. uint32 dwSrcModifier = D3DSPSM_NONE;
  538. // Clear string to zero length
  539. V_snprintf( pRegisterName, nBufLen, "" );
  540. // Weird one...bits are split apart in the dwToken
  541. dwRegType = ( ( dwToken & D3DSP_REGTYPE_MASK2 ) >> D3DSP_REGTYPE_SHIFT2 ) | ( ( dwToken & D3DSP_REGTYPE_MASK ) >> D3DSP_REGTYPE_SHIFT );
  542. // If this is a dest register
  543. if ( dwSourceOrDest == DST_REGISTER )
  544. {
  545. // Instruction modifiers
  546. if ( dwToken & D3DSPDM_PARTIALPRECISION )
  547. {
  548. // strcat_s( pRegisterName, nBufLen, "_pp" );
  549. }
  550. if ( dwToken & D3DSPDM_SATURATE)
  551. {
  552. strcat_s( pRegisterName, nBufLen, "_SAT" );
  553. }
  554. if ( dwToken & D3DSPDM_MSAMPCENTROID)
  555. {
  556. // strcat_s( pRegisterName, nBufLen, "_centroid" );
  557. }
  558. if ( !bGLSL )
  559. {
  560. strcat_s( pRegisterName, nBufLen, " " );
  561. }
  562. }
  563. // If this is a source register
  564. if ( dwSourceOrDest == SRC_REGISTER )
  565. {
  566. dwSrcModifier = dwToken & D3DSP_SRCMOD_MASK;
  567. // If there are any source modifiers, check to see if they're at
  568. // least partially "prefix" and prepend appropriately
  569. if ( dwSrcModifier != D3DSPSM_NONE )
  570. {
  571. switch ( dwSrcModifier )
  572. {
  573. // These four start with just minus... (some may result in "postfix" notation as well later on)
  574. case D3DSPSM_NEG: // negate
  575. strcat_s( pRegisterName, nBufLen, "-" );
  576. break;
  577. case D3DSPSM_BIASNEG: // bias and negate
  578. case D3DSPSM_SIGNNEG: // sign and negate
  579. case D3DSPSM_X2NEG: // *2 and negate
  580. Assert(0);
  581. strcat_s( pRegisterName, nBufLen, "-" );
  582. break;
  583. case D3DSPSM_COMP: // complement
  584. Assert(0);
  585. strcat_s( pRegisterName, nBufLen, "1-" );
  586. break;
  587. case D3DSPSM_ABS: // abs()
  588. Assert(0);
  589. strcat_s( pRegisterName, nBufLen, "abs(" );
  590. break;
  591. case D3DSPSM_ABSNEG: // -abs()
  592. Assert(0);
  593. strcat_s( pRegisterName, nBufLen, "-abs(" );
  594. break;
  595. case D3DSPSM_NOT: // for predicate register: "!p0"
  596. Assert(0);
  597. strcat_s( pRegisterName, nBufLen, "!" );
  598. break;
  599. }
  600. }
  601. }
  602. // Register name (from type and number)
  603. switch ( dwRegType )
  604. {
  605. case D3DSPR_TEMP:
  606. V_snprintf( buff, sizeof( buff ), "r%d", dwRegNum );
  607. strcat_s( pRegisterName, nBufLen, buff );
  608. m_dwTempUsageMask |= 0x00000001 << dwRegNum; // Keep track of the use of this temp
  609. break;
  610. case D3DSPR_INPUT:
  611. if ( m_bVertexShader || ( dwSourceOrDest == SRC_REGISTER ) || bGLSL )
  612. {
  613. V_snprintf( buff, sizeof( buff ), "v%d", dwRegNum );
  614. strcat_s( pRegisterName, nBufLen, buff );
  615. }
  616. else // asm pixel shader declaration syntax:
  617. {
  618. V_snprintf( buff, sizeof( buff ), dwRegNum == 0 ? "v0 = fragment.color" : "v1 = fragment.color.secondary" );
  619. strcat_s( pRegisterName, nBufLen, buff );
  620. bAllowWriteMask = false;
  621. }
  622. break;
  623. case D3DSPR_CONST:
  624. if ( m_bConstantRegisterDefined[dwRegNum] )
  625. {
  626. // Put defined constants into their own namespace "d"
  627. V_snprintf( buff, sizeof( buff ), "d%d", dwRegNum );
  628. strcat_s( pRegisterName, nBufLen, buff );
  629. }
  630. else if ( dwToken & D3DSHADER_ADDRESSMODE_MASK )
  631. {
  632. // Index into single c[] register array with relative addressing
  633. FlagIndirectRegister( GetNextToken(), pARLDestReg );
  634. V_snprintf( buff, sizeof( buff ), "c[a0.x + %d]", dwRegNum );
  635. strcat_s( pRegisterName, nBufLen, buff );
  636. m_bConstantRegisterReferenced[dwRegNum] = true;
  637. }
  638. else
  639. {
  640. // Index into single c[] register array with absolute addressing
  641. V_snprintf( buff, sizeof( buff ), "c[%d]", dwRegNum );
  642. strcat_s( pRegisterName, nBufLen, buff );
  643. m_bConstantRegisterReferenced[dwRegNum] = true;
  644. }
  645. break;
  646. case D3DSPR_ADDR: // aliases to D3DSPR_TEXTURE
  647. if ( m_bVertexShader )
  648. {
  649. V_snprintf( buff, sizeof( buff ), "VEC_ADDRESS_REG" ); // Move into our temp, rather than a0
  650. }
  651. else
  652. {
  653. if ( dwSourceOrDest == DST_REGISTER )
  654. {
  655. V_snprintf( buff, sizeof( buff ), "t%d = fragment.texcoord[%d]", dwRegNum, dwRegNum );
  656. bAllowWriteMask = false;
  657. }
  658. else
  659. {
  660. V_snprintf( buff, sizeof( buff ), "t%d", dwRegNum );
  661. }
  662. }
  663. strcat_s( pRegisterName, nBufLen, buff );
  664. break;
  665. case D3DSPR_RASTOUT: // vertex shader oPos
  666. //V_snprintf( buff, sizeof( buff ), "oPos", dwRegNum ); // that stray parameter should have been a clue :)
  667. switch( dwRegNum )
  668. {
  669. case D3DSRO_POSITION:
  670. strcat_s( pRegisterName, nBufLen, "oPos" );
  671. m_bDeclareVSOPos = true;
  672. break;
  673. case D3DSRO_FOG:
  674. strcat_s( pRegisterName, nBufLen, "oFog" );
  675. m_bDeclareVSOFog = true;
  676. break;
  677. default:
  678. printf("\nD3DSPR_RASTOUT: dwRegNum is %08x and token is %08x",dwRegNum,dwToken);
  679. Assert(0);
  680. break;
  681. }
  682. break;
  683. case D3DSPR_ATTROUT:
  684. Assert( m_bVertexShader );
  685. V_snprintf( buff, sizeof( buff ), "oD%d", dwRegNum );
  686. strcat_s( pRegisterName, nBufLen, buff );
  687. m_bOutputColorRegister[dwRegNum] = true;
  688. break;
  689. case D3DSPR_TEXCRDOUT: // aliases to D3DSPR_OUTPUT
  690. if ( m_bVertexShader )
  691. {
  692. V_snprintf( buff, sizeof( buff ), "oT%d", dwRegNum );
  693. m_dwTexCoordOutMask |= ( 0x00000001 << dwRegNum );
  694. }
  695. else
  696. {
  697. V_snprintf( buff, sizeof( buff ), "oC%d", dwRegNum );
  698. }
  699. strcat_s( pRegisterName, nBufLen, buff );
  700. break;
  701. case D3DSPR_CONSTINT:
  702. Assert(0);
  703. V_snprintf( buff, sizeof( buff ), "xxx%d", dwRegNum );
  704. strcat_s( pRegisterName, nBufLen, buff );
  705. break;
  706. case D3DSPR_COLOROUT:
  707. if ( bGLSL )
  708. {
  709. Assert( dwRegNum == 0 );
  710. V_snprintf( buff, sizeof( buff ), "gl_FragmentColor" );
  711. }
  712. else
  713. {
  714. V_snprintf( buff, sizeof( buff ), "oC%d", dwRegNum );
  715. }
  716. strcat_s( pRegisterName, nBufLen, buff );
  717. m_bOutputColorRegister[dwRegNum] = true;
  718. break;
  719. case D3DSPR_DEPTHOUT:
  720. V_snprintf( buff, sizeof( buff ), "oDepth" );
  721. strcat_s( pRegisterName, nBufLen, buff );
  722. m_bOutputDepthRegister = true;
  723. break;
  724. case D3DSPR_SAMPLER:
  725. V_snprintf( buff, sizeof( buff ), "texture[%d]", dwRegNum );
  726. strcat_s( pRegisterName, nBufLen, buff );
  727. break;
  728. case D3DSPR_CONST2:
  729. Assert(0);
  730. V_snprintf( buff, sizeof( buff ), "c%d", dwRegNum+2048);
  731. strcat_s( pRegisterName, nBufLen, buff );
  732. break;
  733. case D3DSPR_CONST3:
  734. Assert(0);
  735. V_snprintf( buff, sizeof( buff ), "c%d", dwRegNum+4096);
  736. strcat_s( pRegisterName, nBufLen, buff );
  737. break;
  738. case D3DSPR_CONST4:
  739. Assert(0);
  740. V_snprintf( buff, sizeof( buff ), "c%d", dwRegNum+6144);
  741. strcat_s( pRegisterName, nBufLen, buff );
  742. break;
  743. case D3DSPR_CONSTBOOL:
  744. Assert(0);
  745. V_snprintf( buff, sizeof( buff ), "b%d", dwRegNum );
  746. strcat_s( pRegisterName, nBufLen, buff );
  747. break;
  748. case D3DSPR_LOOP:
  749. Assert(0);
  750. V_snprintf( buff, sizeof( buff ), "aL%d", dwRegNum );
  751. strcat_s( pRegisterName, nBufLen, buff );
  752. break;
  753. case D3DSPR_TEMPFLOAT16:
  754. Assert(0);
  755. V_snprintf( buff, sizeof( buff ), "temp_float16_xxx%d", dwRegNum );
  756. strcat_s( pRegisterName, nBufLen, buff );
  757. break;
  758. case D3DSPR_MISCTYPE:
  759. Assert(0);
  760. V_snprintf( buff, sizeof( buff ), "misc%d", dwRegNum );
  761. strcat_s( pRegisterName, nBufLen, buff );
  762. break;
  763. case D3DSPR_LABEL:
  764. Assert(0);
  765. V_snprintf( buff, sizeof( buff ), "label%d", dwRegNum );
  766. strcat_s( pRegisterName, nBufLen, buff );
  767. break;
  768. case D3DSPR_PREDICATE:
  769. Assert(0);
  770. V_snprintf( buff, sizeof( buff ), "p%d", dwRegNum );
  771. strcat_s( pRegisterName, nBufLen, buff );
  772. break;
  773. }
  774. // If this is a dest register
  775. if ( dwSourceOrDest == DST_REGISTER )
  776. {
  777. //
  778. // Write masks
  779. //
  780. // If some (not all, not none) of the write masks are set, we should include them
  781. //
  782. if ( bAllowWriteMask && ( !((dwToken & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) || ((dwToken & D3DSP_WRITEMASK_ALL) == 0x00000000) ) )
  783. {
  784. // Put the dot on there
  785. strcat_s( pRegisterName, nBufLen, "." );
  786. // Optionally put on the x, y, z or w
  787. if ( dwToken & D3DSP_WRITEMASK_0 )
  788. {
  789. strcat_s( pRegisterName, nBufLen, "x" );
  790. }
  791. if ( dwToken & D3DSP_WRITEMASK_1 )
  792. {
  793. strcat_s( pRegisterName, nBufLen, "y" );
  794. }
  795. if ( dwToken & D3DSP_WRITEMASK_2 )
  796. {
  797. strcat_s( pRegisterName, nBufLen, "z" );
  798. }
  799. if ( dwToken & D3DSP_WRITEMASK_3 )
  800. {
  801. strcat_s( pRegisterName, nBufLen, "w" );
  802. }
  803. }
  804. }
  805. else // must be a source register
  806. {
  807. uint32 dwXSwizzle, dwYSwizzle, dwZSwizzle, dwWSwizzle;
  808. // Mask out the swizzle modifier
  809. dwSwizzle = dwToken & D3DVS_SWIZZLE_MASK;
  810. // If there are any swizzles at all, tack on the appropriate notation
  811. if ( dwSwizzle != D3DVS_NOSWIZZLE )
  812. {
  813. // Separate out the two-bit codes for each component swizzle
  814. dwXSwizzle = dwSwizzle & D3DVS_X_W;
  815. dwYSwizzle = dwSwizzle & D3DVS_Y_W;
  816. dwZSwizzle = dwSwizzle & D3DVS_Z_W;
  817. dwWSwizzle = dwSwizzle & D3DVS_W_W;
  818. // Put on the dot
  819. strcat_s( pRegisterName, nBufLen, "." );
  820. // See where X comes from
  821. switch ( dwXSwizzle )
  822. {
  823. case D3DVS_X_X:
  824. strcat_s( pRegisterName, nBufLen, "x" );
  825. break;
  826. case D3DVS_X_Y:
  827. strcat_s( pRegisterName, nBufLen, "y" );
  828. break;
  829. case D3DVS_X_Z:
  830. strcat_s( pRegisterName, nBufLen, "z" );
  831. break;
  832. case D3DVS_X_W:
  833. strcat_s( pRegisterName, nBufLen, "w" );
  834. break;
  835. }
  836. // If the source of the remaining components are aren't
  837. // identical to the source of x, continue with swizzle
  838. if ( ((dwXSwizzle >> D3DVS_SWIZZLE_SHIFT) != (dwYSwizzle >> (D3DVS_SWIZZLE_SHIFT + 2))) || // X and Y sources match?
  839. ((dwXSwizzle >> D3DVS_SWIZZLE_SHIFT) != (dwZSwizzle >> (D3DVS_SWIZZLE_SHIFT + 4))) || // X and Z sources match?
  840. ((dwXSwizzle >> D3DVS_SWIZZLE_SHIFT) != (dwWSwizzle >> (D3DVS_SWIZZLE_SHIFT + 6)))) // X and W sources match?
  841. {
  842. // OpenGL seems to want us to have either 1 or 4 components in a swizzle, so just plow on through the rest
  843. switch ( dwYSwizzle )
  844. {
  845. case D3DVS_Y_X:
  846. strcat_s( pRegisterName, nBufLen, "x" );
  847. break;
  848. case D3DVS_Y_Y:
  849. strcat_s( pRegisterName, nBufLen, "y" );
  850. break;
  851. case D3DVS_Y_Z:
  852. strcat_s( pRegisterName, nBufLen, "z" );
  853. break;
  854. case D3DVS_Y_W:
  855. strcat_s( pRegisterName, nBufLen, "w" );
  856. break;
  857. }
  858. switch ( dwZSwizzle )
  859. {
  860. case D3DVS_Z_X:
  861. strcat_s( pRegisterName, nBufLen, "x" );
  862. break;
  863. case D3DVS_Z_Y:
  864. strcat_s( pRegisterName, nBufLen, "y" );
  865. break;
  866. case D3DVS_Z_Z:
  867. strcat_s( pRegisterName, nBufLen, "z" );
  868. break;
  869. case D3DVS_Z_W:
  870. strcat_s( pRegisterName, nBufLen, "w" );
  871. break;
  872. }
  873. switch ( dwWSwizzle )
  874. {
  875. case D3DVS_W_X:
  876. strcat_s( pRegisterName, nBufLen, "x" );
  877. break;
  878. case D3DVS_W_Y:
  879. strcat_s( pRegisterName, nBufLen, "y" );
  880. break;
  881. case D3DVS_W_Z:
  882. strcat_s( pRegisterName, nBufLen, "z" );
  883. break;
  884. case D3DVS_W_W:
  885. strcat_s( pRegisterName, nBufLen, "w" );
  886. break;
  887. }
  888. }
  889. }
  890. // If there are any source modifiers, check to see if they're at
  891. // least partially "postfix" and tack them on as appropriate
  892. if ( dwSrcModifier != D3DSPSM_NONE )
  893. {
  894. switch ( dwSrcModifier )
  895. {
  896. case D3DSPSM_BIAS: // bias
  897. case D3DSPSM_BIASNEG: // bias and negate
  898. Assert(0);
  899. strcat_s( pRegisterName, nBufLen, "_bx2" );
  900. break;
  901. case D3DSPSM_SIGN: // sign
  902. case D3DSPSM_SIGNNEG: // sign and negate
  903. Assert(0);
  904. strcat_s( pRegisterName, nBufLen, "_sgn" );
  905. break;
  906. case D3DSPSM_X2: // *2
  907. case D3DSPSM_X2NEG: // *2 and negate
  908. Assert(0);
  909. strcat_s( pRegisterName, nBufLen, "_x2" );
  910. break;
  911. case D3DSPSM_ABS: // abs()
  912. case D3DSPSM_ABSNEG: // -abs()
  913. Assert(0);
  914. strcat_s( pRegisterName, nBufLen, ")" );
  915. break;
  916. case D3DSPSM_DZ: // divide through by z component
  917. Assert(0);
  918. strcat_s( pRegisterName, nBufLen, "_dz" );
  919. break;
  920. case D3DSPSM_DW: // divide through by w component
  921. Assert(0);
  922. strcat_s( pRegisterName, nBufLen, "_dw" );
  923. break;
  924. }
  925. } // end postfix modifiers (really only ps.1.x)
  926. }
  927. }
  928. // These are the only ARL instructions that should appear in the instruction stream
  929. void D3DToGL_ASM::InsertMoveInstruction( char *pCode, int nCodeSize, int nARLComponent )
  930. {
  931. switch ( nARLComponent )
  932. {
  933. case ARL_DEST_X:
  934. strcat_s( pCode, nCodeSize, "ARL a0.x, VEC_ADDRESS_REG.x;\n" );
  935. break;
  936. case ARL_DEST_Y:
  937. strcat_s( pCode, nCodeSize, "ARL a0.x, VEC_ADDRESS_REG.y;\n" );
  938. break;
  939. case ARL_DEST_Z:
  940. strcat_s( pCode, nCodeSize, "ARL a0.x, VEC_ADDRESS_REG.z;\n" );
  941. break;
  942. case ARL_DEST_W:
  943. strcat_s( pCode, nCodeSize, "ARL a0.x, VEC_ADDRESS_REG.w;\n" );
  944. break;
  945. }
  946. }
  947. // This optionally inserts a move from our dummy address register to the .x component of the real one
  948. void D3DToGL_ASM::InsertMoveFromAddressRegister( char *pCode, int nCodeSize, int nARLComp0, int nARLComp1, int nARLComp2 = ARL_DEST_NONE )
  949. {
  950. int nNumSwizzles = 0;
  951. if ( nARLComp0 != ARL_DEST_NONE )
  952. nNumSwizzles++;
  953. if ( nARLComp1 != ARL_DEST_NONE )
  954. nNumSwizzles++;
  955. if ( nARLComp2 != ARL_DEST_NONE )
  956. nNumSwizzles++;
  957. // We shouldn't have any more than one indirect address usage in a single instruction
  958. Assert( nNumSwizzles < 2 );
  959. if ( nARLComp0 != ARL_DEST_NONE )
  960. {
  961. InsertMoveInstruction( pCode, nCodeSize, nARLComp0 );
  962. }
  963. else if ( nARLComp1 != ARL_DEST_NONE )
  964. {
  965. InsertMoveInstruction( pCode, nCodeSize, nARLComp1 );
  966. }
  967. else if ( nARLComp2 != ARL_DEST_NONE )
  968. {
  969. InsertMoveInstruction( pCode, nCodeSize, nARLComp2 );
  970. }
  971. }
  972. //------------------------------------------------------------------------------
  973. // TranslateShader()
  974. //
  975. // This is the main function that the outside world sees. A pointer to the
  976. // uint32 stream returned from the D3DX compile routine is parsed and used
  977. // to write human-readable asm code into the character array pointed to by
  978. // pDisassembledCode. An error code is returned.
  979. //------------------------------------------------------------------------------
  980. static int g_translationCounter = 0;
  981. int D3DToGL_ASM::TranslateShader( uint32* code, char *pDisassembledCode, int nBufLen, bool *bVertexShader, uint32 options, int32 nShadowDepthSampler, char *debugLabel )
  982. {
  983. uint32 i, dwToken, dwRegToken, inst, nNumTokensToSkip;
  984. char buff[256];
  985. char pDestReg[32];
  986. char pSrc0Reg[32];
  987. char pSrc1Reg[32];
  988. char pSrc2Reg[32];
  989. int nARLComp0, nARLComp1, nARLComp2;
  990. // obey options
  991. m_bUseEnvParams = (options & D3DToGL_OptionUseEnvParams) != 0;
  992. m_bDoFixupZ = (options & D3DToGL_OptionDoFixupZ) != 0;
  993. m_bDoFixupY = (options & D3DToGL_OptionDoFixupY) != 0;
  994. m_bDoUserClipPlanes = (options & D3DToGL_OptionDoUserClipPlanes) != 0;
  995. // debugging
  996. m_bSpew = (options & D3DToGL_OptionSpew) != 0;
  997. // m_bSpew |= (g_translationCounter == 1012 ); // interested in this specific translation run
  998. // These are not accessed below in a way that will cause them to grow, so
  999. // we could overflow these and/or the buffer pointed to by pDisassembledCode
  1000. CUtlBuffer bufAttribCode( 100, 10000, CUtlBuffer::TEXT_BUFFER );
  1001. CUtlBuffer bufParamCode( 100, 10000, CUtlBuffer::TEXT_BUFFER );
  1002. CUtlBuffer bufALUCode( 100, 30000, CUtlBuffer::TEXT_BUFFER );
  1003. // Pointers to text buffers for assembling sections of the program
  1004. char *pHeaderCode = pDisassembledCode;
  1005. char *pAttribMapStart = NULL;
  1006. char *pAttribCode = (char *)bufAttribCode.Base();
  1007. char *pParamCode = (char *)bufParamCode.Base();
  1008. char *pALUCode = (char *)bufALUCode.Base();
  1009. V_snprintf( pHeaderCode, nBufLen, "" );
  1010. V_snprintf( pAttribCode, bufAttribCode.Size(), "" );
  1011. V_snprintf( pParamCode, bufParamCode.Size(), "" );
  1012. V_snprintf( pALUCode, bufALUCode.Size(), "" );
  1013. for ( i=0; i<MAX_SHADER_CONSTANTS; i++ )
  1014. {
  1015. m_bConstantRegisterReferenced[i] = false;
  1016. m_bConstantRegisterDefined[i] = false;
  1017. }
  1018. // Track shadow sampler usage for proper declaration
  1019. m_nShadowDepthSampler = nShadowDepthSampler;
  1020. m_bDeclareShadowOption = false;
  1021. // Various flags set while parsing code to drive various declaration instructions
  1022. m_bNeedsD2AddTemp = false;
  1023. m_bNeedsLerpTemp = false;
  1024. m_bNeedsNRMTemp = false;
  1025. m_bNeedsSinCosDeclarations = false;
  1026. m_bDeclareAddressReg = false;
  1027. m_bDeclareVSOPos = false;
  1028. m_bDeclareVSOFog = false;
  1029. m_dwTexCoordOutMask = 0;
  1030. m_bOutputColorRegister[0] = false;
  1031. m_bOutputColorRegister[1] = false;
  1032. m_bOutputColorRegister[2] = false;
  1033. m_bOutputColorRegister[3] = false;
  1034. m_bOutputDepthRegister = false;
  1035. m_dwTempUsageMask = 0x00000000;
  1036. memset( m_dwAttribMap, 0xFF, sizeof(m_dwAttribMap) );
  1037. m_pdwBaseToken = m_pdwNextToken = code; // Initialize dwToken pointers
  1038. dwToken = GetNextToken();
  1039. m_dwMajorVersion = D3DSHADER_VERSION_MAJOR( dwToken );
  1040. m_dwMinorVersion = D3DSHADER_VERSION_MINOR( dwToken );
  1041. // We only do vs_2_0 and ps_2_x
  1042. if ( m_dwMajorVersion != 2 )
  1043. {
  1044. Debugger();
  1045. }
  1046. // If pixel shader
  1047. if ( ( dwToken & 0xFFFF0000 ) == 0xFFFF0000 )
  1048. {
  1049. V_snprintf( pHeaderCode, nBufLen, "!!ARBfp1.0\n" );
  1050. m_bVertexShader = false;
  1051. }
  1052. else // vertex shader
  1053. {
  1054. if (m_bDoUserClipPlanes)
  1055. {
  1056. // include "OPTION NV_vertex_program2;"
  1057. V_snprintf( pHeaderCode, nBufLen, "!!ARBvp1.0\n#//ATTRIBMAP-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx\nOPTION NV_vertex_program2;\n" );
  1058. }
  1059. else
  1060. {
  1061. // do not include "OPTION NV_vertex_program2;"
  1062. V_snprintf( pHeaderCode, nBufLen, "!!ARBvp1.0\n#//ATTRIBMAP-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx-xx\n" );
  1063. }
  1064. // find that first 'x' which is where the attrib map will be written later.
  1065. pAttribMapStart = strchr( pHeaderCode, 'x');
  1066. m_bVertexShader = true;
  1067. }
  1068. *bVertexShader = m_bVertexShader;
  1069. if ( m_bSpew )
  1070. {
  1071. printf("\n************* translating shader " );
  1072. }
  1073. int opcounter = 0;
  1074. // Loop until we hit the end dwToken...note that D3DPS_END() == D3DVS_END() so this works for either
  1075. while ( dwToken != D3DPS_END() )
  1076. {
  1077. #ifdef POSIX
  1078. int tokenIndex = m_pdwNextToken - code;
  1079. #endif
  1080. int aluCodeLength0 = strlen( pALUCode );
  1081. dwToken = GetNextToken(); // Get next dwToken in the stream
  1082. inst = Opcode( dwToken ); // Mask out the instruction opcode
  1083. if ( m_bSpew )
  1084. {
  1085. #ifdef POSIX
  1086. printf("\n** token# %04x inst# %04d opcode %s (%08x)", tokenIndex, opcounter, GLMDecode(eD3D_SIO, inst), dwToken );
  1087. #endif
  1088. opcounter++;
  1089. }
  1090. switch ( inst )
  1091. {
  1092. // -- No arguments at all -----------------------------------------------
  1093. case D3DSIO_NOP:
  1094. case D3DSIO_PHASE:
  1095. case D3DSIO_RET:
  1096. case D3DSIO_ELSE:
  1097. case D3DSIO_ENDIF:
  1098. case D3DSIO_ENDLOOP:
  1099. case D3DSIO_ENDREP:
  1100. case D3DSIO_BREAK:
  1101. Assert(0);
  1102. PrintOpcode( inst, buff, sizeof( buff ) );
  1103. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1104. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1105. break;
  1106. // -- "Declarative" non dcl ops ----------------------------------------
  1107. case D3DSIO_TEXDEPTH:
  1108. case D3DSIO_TEXKILL:
  1109. PrintOpcode( inst, buff, sizeof( buff ) );
  1110. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1111. dwToken = GetNextToken();
  1112. PrintParameterToString( dwToken, DST_REGISTER, buff, sizeof( buff ), false );
  1113. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1114. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1115. break;
  1116. // -- Unary ops -------------------------------------------------
  1117. case D3DSIO_BEM:
  1118. case D3DSIO_TEXBEM:
  1119. case D3DSIO_TEXBEML:
  1120. case D3DSIO_TEXDP3:
  1121. case D3DSIO_TEXDP3TEX:
  1122. case D3DSIO_TEXM3x2DEPTH:
  1123. case D3DSIO_TEXM3x2TEX:
  1124. case D3DSIO_TEXM3x3:
  1125. case D3DSIO_TEXM3x3PAD:
  1126. case D3DSIO_TEXM3x3TEX:
  1127. case D3DSIO_TEXM3x3VSPEC:
  1128. case D3DSIO_TEXREG2AR:
  1129. case D3DSIO_TEXREG2GB:
  1130. case D3DSIO_TEXREG2RGB:
  1131. case D3DSIO_LABEL:
  1132. case D3DSIO_CALL:
  1133. case D3DSIO_IF:
  1134. case D3DSIO_LOOP:
  1135. case D3DSIO_REP:
  1136. case D3DSIO_BREAKP:
  1137. case D3DSIO_DSX:
  1138. case D3DSIO_DSY:
  1139. Assert(0);
  1140. break;
  1141. case D3DSIO_NRM:
  1142. m_bNeedsNRMTemp = true;
  1143. dwToken = GetNextToken();
  1144. PrintParameterToString( dwToken, DST_REGISTER, pDestReg, sizeof( pDestReg ), false );
  1145. dwToken = GetNextToken();
  1146. PrintParameterToString( dwToken, SRC_REGISTER, pSrc0Reg, sizeof( pSrc0Reg ), false );
  1147. strcat_s( pALUCode, bufALUCode.Size(), "DP3 NRM_TEMP.w, " );
  1148. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1149. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1150. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1151. strcat_s( pALUCode, bufALUCode.Size(), ";\nRSQ NRM_TEMP.w, NRM_TEMP.w;\nMUL" );
  1152. strcat_s( pALUCode, bufALUCode.Size(), pDestReg );
  1153. strcat_s( pALUCode, bufALUCode.Size(), ", NRM_TEMP.w, " );
  1154. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1155. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1156. break;
  1157. case D3DSIO_MOVA:
  1158. m_bDeclareAddressReg = true;
  1159. PrintOpcode( inst, buff, sizeof( buff ) );
  1160. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1161. dwToken = GetNextToken();
  1162. PrintParameterToString( dwToken, DST_REGISTER, buff, sizeof( buff ), false );
  1163. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1164. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1165. dwToken = GetNextToken();
  1166. PrintParameterToString( dwToken, SRC_REGISTER, buff, sizeof( buff ), false );
  1167. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1168. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1169. break;
  1170. case D3DSIO_MOV:
  1171. case D3DSIO_RCP:
  1172. case D3DSIO_RSQ:
  1173. case D3DSIO_EXP:
  1174. case D3DSIO_EXPP:
  1175. case D3DSIO_LOG:
  1176. case D3DSIO_LOGP:
  1177. case D3DSIO_FRC:
  1178. case D3DSIO_LIT:
  1179. case D3DSIO_ABS:
  1180. PrintOpcode( inst, buff, sizeof( buff ) );
  1181. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1182. dwToken = GetNextToken();
  1183. PrintParameterToString( dwToken, DST_REGISTER, buff, sizeof( buff ), false );
  1184. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1185. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1186. dwToken = GetNextToken();
  1187. PrintParameterToString( dwToken, SRC_REGISTER, buff, sizeof( buff ), false );
  1188. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1189. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1190. break;
  1191. // -- Binary ops -------------------------------------------------
  1192. case D3DSIO_TEXM3x3SPEC:
  1193. case D3DSIO_M4x4:
  1194. case D3DSIO_M4x3:
  1195. case D3DSIO_M3x4:
  1196. case D3DSIO_M3x3:
  1197. case D3DSIO_M3x2:
  1198. case D3DSIO_CALLNZ:
  1199. case D3DSIO_IFC:
  1200. case D3DSIO_BREAKC:
  1201. case D3DSIO_SETP:
  1202. case D3DSIO_TEXLDL:
  1203. Assert(0);
  1204. break;
  1205. case D3DSIO_ADD:
  1206. case D3DSIO_SUB:
  1207. case D3DSIO_MUL:
  1208. case D3DSIO_DP3:
  1209. case D3DSIO_DP4:
  1210. case D3DSIO_MIN:
  1211. case D3DSIO_MAX:
  1212. case D3DSIO_DST:
  1213. case D3DSIO_SLT:
  1214. case D3DSIO_SGE:
  1215. case D3DSIO_CRS:
  1216. case D3DSIO_POW:
  1217. // Print opcode and registers into separate buffers
  1218. PrintOpcode( inst, buff, sizeof( buff ) );
  1219. PrintParameterToString( GetNextToken(), DST_REGISTER, pDestReg, sizeof( pDestReg ), false );
  1220. nARLComp0 = ARL_DEST_NONE;
  1221. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc0Reg, sizeof( pSrc0Reg ), false, &nARLComp0 );
  1222. nARLComp1 = ARL_DEST_NONE;
  1223. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc1Reg, sizeof( pSrc1Reg ), false, &nARLComp1 );
  1224. // This optionally inserts a move from our dummy address register to the .x component of the real one
  1225. InsertMoveFromAddressRegister( pALUCode, bufALUCode.Size(), nARLComp0, nARLComp1 );
  1226. // Concat this instruction into instruction stream
  1227. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1228. strcat_s( pALUCode, bufALUCode.Size(), pDestReg );
  1229. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1230. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1231. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1232. strcat_s( pALUCode, bufALUCode.Size(), pSrc1Reg );
  1233. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1234. break;
  1235. // -- Ternary ops -------------------------------------------------
  1236. case D3DSIO_DP2ADD:
  1237. m_bNeedsD2AddTemp = true;
  1238. PrintParameterToString( GetNextToken(), DST_REGISTER, pDestReg, sizeof( pDestReg ), false );
  1239. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc0Reg, sizeof( pSrc0Reg ), false );
  1240. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc1Reg, sizeof( pSrc1Reg ), false );
  1241. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc2Reg, sizeof( pSrc2Reg ), false );
  1242. strcat_s( pALUCode, bufALUCode.Size(), "MOV DP2A0, " ); // MOV DP2A0, src0;
  1243. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1244. strcat_s( pALUCode, bufALUCode.Size(), ";\nMOV DP2A0.z, 1;\n" );// MOV DP2A0.z, 1;
  1245. strcat_s( pALUCode, bufALUCode.Size(), "MOV DP2A1, " ); // MOV DP2A1, src1;
  1246. strcat_s( pALUCode, bufALUCode.Size(), pSrc1Reg );
  1247. strcat_s( pALUCode, bufALUCode.Size(), ";\nMOV DP2A1.z, " ); // MOV DP2A1.z, src2;
  1248. strcat_s( pALUCode, bufALUCode.Size(), pSrc2Reg ); // DP3 dest, DP2A0, DP2A1;
  1249. strcat_s( pALUCode, bufALUCode.Size(), ";\nDP3" );
  1250. strcat_s( pALUCode, bufALUCode.Size(), pDestReg );
  1251. strcat_s( pALUCode, bufALUCode.Size(), ", DP2A0, DP2A1;\n" );
  1252. break;
  1253. case D3DSIO_LRP:
  1254. if ( !m_bVertexShader )
  1255. {
  1256. PrintOpcode( inst, buff, sizeof( buff ) );
  1257. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1258. PrintParameterToString( GetNextToken(), DST_REGISTER, buff, sizeof( buff ), false );
  1259. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1260. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1261. PrintParameterToString( GetNextToken(), SRC_REGISTER, buff, sizeof( buff ), false );
  1262. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1263. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1264. PrintParameterToString( GetNextToken(), SRC_REGISTER, buff, sizeof( buff ), false );
  1265. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1266. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1267. PrintParameterToString( GetNextToken(), SRC_REGISTER, buff, sizeof( buff ), false );
  1268. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1269. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1270. }
  1271. else // VS doesn't actually have a LRP instruction. Emulate with a SUB and a MAD
  1272. {
  1273. m_bNeedsLerpTemp = true;
  1274. // dest = src0 * (src1 - src2) + src2;
  1275. PrintParameterToString( GetNextToken(), DST_REGISTER, pDestReg, sizeof( pDestReg ), false );
  1276. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc0Reg, sizeof( pSrc0Reg ), false );
  1277. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc1Reg, sizeof( pSrc1Reg ), false );
  1278. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc2Reg, sizeof( pSrc2Reg ), false );
  1279. strcat_s( pALUCode, bufALUCode.Size(), "SUB LRP_TEMP, " ); // SUB LRP_TEMP, src1, src2;
  1280. strcat_s( pALUCode, bufALUCode.Size(), pSrc1Reg );
  1281. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1282. strcat_s( pALUCode, bufALUCode.Size(), pSrc2Reg );
  1283. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1284. strcat_s( pALUCode, bufALUCode.Size(), "MAD" ); // MAD dst, src0, LRP_TEMP, src2;
  1285. strcat_s( pALUCode, bufALUCode.Size(), pDestReg );
  1286. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1287. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1288. strcat_s( pALUCode, bufALUCode.Size(), ", LRP_TEMP, " );
  1289. strcat_s( pALUCode, bufALUCode.Size(), pSrc2Reg );
  1290. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1291. }
  1292. break;
  1293. case D3DSIO_SGN:
  1294. Assert( m_bVertexShader );
  1295. Assert(0); // TODO emulate with SLT etc
  1296. break;
  1297. case D3DSIO_CND:
  1298. Assert(0);
  1299. break;
  1300. case D3DSIO_CMP:
  1301. Assert( !m_bVertexShader );
  1302. // In Direct3D, result = (src0 >= 0.0) ? src1 : src2
  1303. // In OpenGL, result = (src0 < 0.0) ? src1 : src2
  1304. //
  1305. // As a result, arguments are effectively in a different order than Direct3D! !#$&*!%#$&
  1306. PrintParameterToString( GetNextToken(), DST_REGISTER, pDestReg, sizeof( pDestReg ), false );
  1307. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc0Reg, sizeof( pSrc0Reg ), false );
  1308. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc1Reg, sizeof( pSrc1Reg ), false );
  1309. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc2Reg, sizeof( pSrc2Reg ), false );
  1310. strcat_s( pALUCode, bufALUCode.Size(), "CMP" );
  1311. strcat_s( pALUCode, bufALUCode.Size(), pDestReg );
  1312. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1313. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1314. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1315. strcat_s( pALUCode, bufALUCode.Size(), pSrc2Reg ); // Src 2 |
  1316. strcat_s( pALUCode, bufALUCode.Size(), ", " ); // |--- Swap these guys from Direct3D's convention
  1317. strcat_s( pALUCode, bufALUCode.Size(), pSrc1Reg ); // Src 1 |
  1318. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1319. break;
  1320. case D3DSIO_SINCOS:
  1321. // This is the code sequence recommended to IHVs by Microsoft in the DirectX 9 DDK:
  1322. //
  1323. // http://msdn.microsoft.com/en-us/library/ms800337.aspx
  1324. //
  1325. // MUL SC_TEMP.z, src, src;
  1326. // MAD SC_TEMP.xy, SC_TEMP.z, scA, scA.wzyx;
  1327. // MAD SC_TEMP.xy, SC_TEMP, SC_TEMP.z, scB;
  1328. // MAD SC_TEMP.xy, SC_TEMP, SC_TEMP.z, scB.wzyx;
  1329. // MUL SC_TEMP.x, SC_TEMP.x, src;
  1330. // MUL SC_TEMP.xy, SC_TEMP, SC_TEMP.x;
  1331. // ADD SC_TEMP.xy, SC_TEMP, SC_TEMP;
  1332. // ADD SC_TEMP.x, -SC_TEMP.x, scB.z;
  1333. m_bNeedsSinCosDeclarations = true;
  1334. PrintParameterToString( GetNextToken(), DST_REGISTER, pDestReg, sizeof( pDestReg ), false );
  1335. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc0Reg, sizeof( pSrc0Reg ), false );
  1336. // Eat two more tokens since D3D defines similar Taylor series constants that we won't need
  1337. SkipTokens( 2 );
  1338. strcat_s( pALUCode, bufALUCode.Size(), "MUL SC_TEMP.z, " ); // MUL SC_TEMP.z, src, src;
  1339. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1340. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1341. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1342. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1343. strcat_s( pALUCode, bufALUCode.Size(), "MAD SC_TEMP.xy, SC_TEMP.z, scA, scA.wzyx;\n" );
  1344. strcat_s( pALUCode, bufALUCode.Size(), "MAD SC_TEMP.xy, SC_TEMP, SC_TEMP.z, scB;\n" );
  1345. strcat_s( pALUCode, bufALUCode.Size(), "MAD SC_TEMP.xy, SC_TEMP, SC_TEMP.z, scB.wzyx;\n" );
  1346. strcat_s( pALUCode, bufALUCode.Size(), "MUL SC_TEMP.x, SC_TEMP.x, " );
  1347. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1348. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1349. strcat_s( pALUCode, bufALUCode.Size(), "MUL SC_TEMP.xy, SC_TEMP, SC_TEMP.x;\n" );
  1350. strcat_s( pALUCode, bufALUCode.Size(), "ADD SC_TEMP.xy, SC_TEMP, SC_TEMP;\n" );
  1351. strcat_s( pALUCode, bufALUCode.Size(), "ADD SC_TEMP.x, -SC_TEMP.x, scB.z;\n" );
  1352. strcat_s( pALUCode, bufALUCode.Size(), "MOV" );
  1353. strcat_s( pALUCode, bufALUCode.Size(), pDestReg );
  1354. strcat_s( pALUCode, bufALUCode.Size(), ", SC_TEMP;\n" );
  1355. break;
  1356. case D3DSIO_MAD:
  1357. // Print opcode and registers into separate buffers
  1358. PrintOpcode( inst, buff, sizeof( buff ) );
  1359. PrintParameterToString( GetNextToken(), DST_REGISTER, pDestReg, sizeof( pDestReg ), false );
  1360. nARLComp0 = ARL_DEST_NONE;
  1361. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc0Reg, sizeof( pSrc0Reg ), false, &nARLComp0 );
  1362. nARLComp1 = ARL_DEST_NONE;
  1363. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc1Reg, sizeof( pSrc1Reg ), false, &nARLComp1 );
  1364. nARLComp2 = ARL_DEST_NONE;
  1365. PrintParameterToString( GetNextToken(), SRC_REGISTER, pSrc2Reg, sizeof( pSrc2Reg ), false, &nARLComp2 );
  1366. // This optionally inserts a move from our dummy address register to the .x component of the real one
  1367. InsertMoveFromAddressRegister( pALUCode, bufALUCode.Size(), nARLComp0, nARLComp1, nARLComp2 );
  1368. // Concat this instruction into instruction stream
  1369. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1370. strcat_s( pALUCode, bufALUCode.Size(), pDestReg );
  1371. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1372. strcat_s( pALUCode, bufALUCode.Size(), pSrc0Reg );
  1373. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1374. strcat_s( pALUCode, bufALUCode.Size(), pSrc1Reg );
  1375. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1376. strcat_s( pALUCode, bufALUCode.Size(), pSrc2Reg );
  1377. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1378. break;
  1379. // -- Quaternary op ------------------------------------------------
  1380. case D3DSIO_TEXLDD:
  1381. PrintOpcode( inst, buff, sizeof( buff ) );
  1382. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1383. PrintParameterToString( GetNextToken(), DST_REGISTER, buff, sizeof( buff ), false );
  1384. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1385. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1386. PrintParameterToString( GetNextToken(), SRC_REGISTER, buff, sizeof( buff ), false );
  1387. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1388. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1389. PrintParameterToString( GetNextToken(), SRC_REGISTER, buff, sizeof( buff ), false );
  1390. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1391. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1392. PrintParameterToString( GetNextToken(), SRC_REGISTER, buff, sizeof( buff ), false );
  1393. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1394. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1395. PrintParameterToString( GetNextToken(), SRC_REGISTER, buff, sizeof( buff ), false );
  1396. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1397. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1398. break;
  1399. // -- Special cases: texcoord vs texcrd and tex vs texld -----------
  1400. case D3DSIO_TEXCOORD:
  1401. Assert(0);
  1402. // If ps_1_4, this is texcrd
  1403. if ((m_dwMajorVersion == 1) && (m_dwMinorVersion == 4) && (!m_bVertexShader))
  1404. {
  1405. strcat_s( pALUCode, bufALUCode.Size(), "texcrd" );
  1406. }
  1407. else // else it's texcoord
  1408. {
  1409. Assert(0);
  1410. strcat_s( pALUCode, bufALUCode.Size(), "texcoord" );
  1411. }
  1412. PrintParameterToString( GetNextToken(), DST_REGISTER, buff, sizeof( buff ), false );
  1413. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1414. // If ps_1_4, texcrd also has a source parameter
  1415. if ((m_dwMajorVersion == 1) && (m_dwMinorVersion == 4) && (!m_bVertexShader))
  1416. {
  1417. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1418. PrintParameterToString( GetNextToken(), SRC_REGISTER, buff, sizeof( buff ), false );
  1419. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1420. }
  1421. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1422. break;
  1423. case D3DSIO_TEX:
  1424. if( ( OpcodeSpecificData( dwToken ) << D3DSP_OPCODESPECIFICCONTROL_SHIFT ) == D3DSI_TEXLD_PROJECT )
  1425. {
  1426. strcat_s( pALUCode, bufALUCode.Size(), "TXP" );
  1427. }
  1428. else if( ( OpcodeSpecificData( dwToken ) << D3DSP_OPCODESPECIFICCONTROL_SHIFT) == D3DSI_TEXLD_BIAS )
  1429. {
  1430. strcat_s( pALUCode, bufALUCode.Size(), "TXB" );
  1431. }
  1432. else
  1433. {
  1434. strcat_s( pALUCode, bufALUCode.Size(), "TEX" );
  1435. }
  1436. // Destination
  1437. dwToken = GetNextToken();
  1438. PrintParameterToString( dwToken, DST_REGISTER, buff, sizeof( buff ), false );
  1439. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1440. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1441. // Source0
  1442. dwToken = GetNextToken();
  1443. PrintParameterToString( dwToken, SRC_REGISTER, buff, sizeof( buff ), false );
  1444. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1445. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1446. // Source1
  1447. dwToken = GetNextToken();
  1448. PrintParameterToString( dwToken, SRC_REGISTER, buff, sizeof( buff ), false );
  1449. strcat_s( pALUCode, bufALUCode.Size(), buff );
  1450. strcat_s( pALUCode, bufALUCode.Size(), ", " );
  1451. // Syntax for shadow depth sampler
  1452. if ( ( (int) ( dwToken & D3DSP_REGNUM_MASK ) ) == m_nShadowDepthSampler )
  1453. {
  1454. m_bDeclareShadowOption = true;
  1455. strcat_s( pALUCode, bufALUCode.Size(), "SHADOW" ); // Should result in SHADOW2D target
  1456. Assert( m_dwSamplerTypes[dwToken & D3DSP_REGNUM_MASK] == SAMPLER_TYPE_2D );
  1457. }
  1458. // Sampler dimension (2D, CUBE, 3D) determined by earlier declaration
  1459. strcat_s( pALUCode, bufALUCode.Size(), g_pSamplerStrings[m_dwSamplerTypes[dwToken & D3DSP_REGNUM_MASK]] );
  1460. strcat_s( pALUCode, bufALUCode.Size(), ";\n" );
  1461. break;
  1462. case D3DSIO_DCL:
  1463. if ( m_bVertexShader )
  1464. {
  1465. dwToken = GetNextToken(); // What kind of dcl is this...
  1466. dwRegToken = GetNextToken(); // Look ahead to register token
  1467. strcat_s( pAttribCode, bufAttribCode.Size(), "ATTRIB" );
  1468. PrintParameterToString( dwRegToken, DST_REGISTER, buff, sizeof( buff ), false );
  1469. strcat_s( pAttribCode, bufAttribCode.Size(), buff );
  1470. strcat_s( pAttribCode, bufAttribCode.Size(), " = " );
  1471. // maintain attrib map
  1472. // check that this reg index has not been used before - if it has, let Houston know
  1473. uint regIndex = dwRegToken & D3DSP_REGNUM_MASK;
  1474. if (m_dwAttribMap[ regIndex ] == 0xFFFFFFFF)
  1475. {
  1476. // log it
  1477. // semantic/usage in the higher nibble
  1478. // usage index in the low nibble
  1479. uint usage = dwToken & D3DSP_DCL_USAGE_MASK;
  1480. uint usageindex = ( dwToken & D3DSP_DCL_USAGEINDEX_MASK ) >> D3DSP_DCL_USAGEINDEX_SHIFT;
  1481. m_dwAttribMap[ regIndex ] = (usage<<4) | usageindex;
  1482. // avoid writing 0xBB since runtime code uses that for an 'unused' marker
  1483. if (m_dwAttribMap[ regIndex ] == 0xBB)
  1484. {
  1485. Debugger();
  1486. }
  1487. }
  1488. else
  1489. {
  1490. //not OK
  1491. Debugger();
  1492. }
  1493. char temp[128];
  1494. // regnum goes straight into the vertex.attrib[n] index
  1495. sprintf( temp, "vertex.attrib[%-2d]; # %08x %08x\n", regIndex, dwToken, dwRegToken );
  1496. strcat_s( pAttribCode, bufAttribCode.Size(), temp );
  1497. }
  1498. else
  1499. {
  1500. dwToken = GetNextToken(); // What kind of dcl is this...
  1501. dwRegToken = GetNextToken(); // Look ahead to register token
  1502. // If the register is a sampler, the dcl has a dimension decorator that we have to save for subsequent TEX instructions
  1503. if ( GetRegType( dwRegToken ) == D3DSPR_SAMPLER )
  1504. {
  1505. switch ( TextureType( dwToken ) )
  1506. {
  1507. default:
  1508. case D3DSTT_UNKNOWN:
  1509. case D3DSTT_2D:
  1510. m_dwSamplerTypes[dwRegToken & D3DSP_REGNUM_MASK] = SAMPLER_TYPE_2D;
  1511. break;
  1512. case D3DSTT_CUBE:
  1513. m_dwSamplerTypes[dwRegToken & D3DSP_REGNUM_MASK] = SAMPLER_TYPE_CUBE;
  1514. break;
  1515. case D3DSTT_VOLUME:
  1516. m_dwSamplerTypes[dwRegToken & D3DSP_REGNUM_MASK] = SAMPLER_TYPE_3D;
  1517. break;
  1518. }
  1519. }
  1520. else // Not a sampler, we're going to generate attribute declaration code
  1521. {
  1522. strcat_s( pAttribCode, bufAttribCode.Size(), "ATTRIB" );
  1523. PrintParameterToString( dwRegToken, DST_REGISTER, buff, sizeof( buff ), false );
  1524. strcat_s( pAttribCode, bufAttribCode.Size(), buff );
  1525. strcat_s( pAttribCode, bufAttribCode.Size(), ";\n" );
  1526. }
  1527. }
  1528. break;
  1529. case D3DSIO_DEFB:
  1530. case D3DSIO_DEFI:
  1531. // Shouldn't be using bool or integer constants
  1532. Assert(0);
  1533. break;
  1534. case D3DSIO_DEF:
  1535. //
  1536. // JasonM TODO: catch D3D's sincos-specific D3DSINCOSCONST1 and D3DSINCOSCONST2 constants and filter them out here
  1537. //
  1538. strcat_s( pParamCode, bufParamCode.Size(), "PARAM" );
  1539. // Which register is being defined
  1540. dwToken = GetNextToken();
  1541. // Note that this constant was explicitly defined
  1542. m_bConstantRegisterDefined[dwToken & D3DSP_REGNUM_MASK] = true;
  1543. PrintParameterToString( dwToken, DST_REGISTER, buff, sizeof( buff ), false );
  1544. strcat_s( pParamCode, bufParamCode.Size(), buff );
  1545. strcat_s( pParamCode, bufParamCode.Size(), " = { " );
  1546. // Run through the 4 floats
  1547. for ( i=0; i<4; i++ )
  1548. {
  1549. float fConst = uint32ToFloat_ASM( GetNextToken() );
  1550. V_snprintf( buff, sizeof( buff ), i != 3 ? "%g, " : "%g", fConst); // end with comma-space
  1551. strcat_s( pParamCode, bufParamCode.Size(), buff );
  1552. }
  1553. strcat_s( pParamCode, bufParamCode.Size(), " };\n" );
  1554. break;
  1555. case D3DSIO_COMMENT:
  1556. // Using OpcodeSpecificData() can fail here since the comments can be longer than 0xff dwords
  1557. nNumTokensToSkip = ( dwToken & 0x0fff0000 ) >> 16;
  1558. SkipTokens( nNumTokensToSkip );
  1559. break;
  1560. case D3DSIO_END:
  1561. break;
  1562. }
  1563. if ( m_bSpew )
  1564. {
  1565. int aluCodeLength1 = strlen( pALUCode );
  1566. if ( aluCodeLength1 != aluCodeLength0 )
  1567. {
  1568. // code was emitted
  1569. printf( "\n > %s", pALUCode + aluCodeLength0 );
  1570. aluCodeLength0 = aluCodeLength1;
  1571. }
  1572. }
  1573. }
  1574. if ( m_bNeedsSinCosDeclarations )
  1575. {
  1576. // Note that this constant packing expects .wzyx swizzles in case we ever use the SINCOS code in a ps_2_x shader
  1577. //
  1578. // The Microsoft documentation on this is all kinds of broken and, strangely, these numbers don't
  1579. // match the D3DSINCOSCONST1 and D3DSINCOSCONST2 constants used by the D3D assembly sincos instruction...
  1580. strcat_s( pParamCode, bufParamCode.Size(), "PARAM scA = { -1.55009923e-6, -2.17013894e-5, 0.00260416674, 0.00026041668 };\n" );
  1581. strcat_s( pParamCode, bufParamCode.Size(), "PARAM scB = { -0.020833334, -0.0625, 1.0, 0.5 };\n" );
  1582. }
  1583. // Just declare the whole constant store for non-def constants
  1584. if ( m_bVertexShader )
  1585. {
  1586. if ( m_bUseEnvParams )
  1587. {
  1588. strcat_s( pParamCode, bufParamCode.Size(), "PARAM c[256] = { program.env[0..255] };\n" );
  1589. }
  1590. else
  1591. {
  1592. strcat_s( pParamCode, bufParamCode.Size(), "PARAM c[256] = { program.local[0..255] };\n" );
  1593. }
  1594. }
  1595. else
  1596. {
  1597. if ( m_bUseEnvParams )
  1598. {
  1599. strcat_s( pParamCode, bufParamCode.Size(), "PARAM c[32] = { program.env[0..31] };\n" );
  1600. }
  1601. else
  1602. {
  1603. strcat_s( pParamCode, bufParamCode.Size(), "PARAM c[32] = { program.local[0..31] };\n" );
  1604. }
  1605. }
  1606. if ( m_bDeclareAddressReg )
  1607. {
  1608. strcat_s( pParamCode, bufParamCode.Size(), "ADDRESS a0;\n" );
  1609. strcat_s( pParamCode, bufParamCode.Size(), "TEMP VEC_ADDRESS_REG;\n" );
  1610. }
  1611. // Declare temps in Param code buffer
  1612. for( int i=0; i<32; i++ )
  1613. {
  1614. char tempBuff[32];
  1615. if ( m_dwTempUsageMask & ( 0x00000001 << i ) )
  1616. {
  1617. V_snprintf( tempBuff, sizeof( tempBuff ), "TEMP r%d;\n", i );
  1618. strcat_s( pParamCode, bufParamCode.Size(), tempBuff );
  1619. }
  1620. }
  1621. if ( m_bNeedsSinCosDeclarations )
  1622. {
  1623. strcat_s( pParamCode, bufParamCode.Size(), "TEMP SC_TEMP;\n" );
  1624. }
  1625. // Optional temps needed to emulate d2add instruction in DX pixel shaders
  1626. if ( m_bNeedsD2AddTemp )
  1627. {
  1628. strcat_s( pParamCode, bufParamCode.Size(), "TEMP DP2A0;\nTEMP DP2A1;\n" );
  1629. }
  1630. // Optional temp needed to emulate lerp instruction in DX vertex shaders
  1631. if ( m_bNeedsLerpTemp )
  1632. {
  1633. strcat_s( pParamCode, bufParamCode.Size(), "TEMP LRP_TEMP;\n" );
  1634. }
  1635. // Optional temp needed to emulate NRM instruction in DX shaders
  1636. if ( m_bNeedsNRMTemp )
  1637. {
  1638. strcat_s( pParamCode, bufParamCode.Size(), "TEMP NRM_TEMP;\n" );
  1639. }
  1640. // Pixel shader color outputs (MRT support?...just declare MRT outputs as useless TEMPS)
  1641. if ( !m_bVertexShader )
  1642. {
  1643. if ( m_bOutputColorRegister[1] )
  1644. {
  1645. strcat_s( pParamCode, bufParamCode.Size(), "TEMP oC1;\n" );
  1646. }
  1647. if ( m_bOutputColorRegister[2] )
  1648. {
  1649. strcat_s( pParamCode, bufParamCode.Size(), "TEMP oC2;\n" );
  1650. }
  1651. if ( m_bOutputColorRegister[3] )
  1652. {
  1653. strcat_s( pParamCode, bufParamCode.Size(), "TEMP oC3;\n" );
  1654. }
  1655. if ( m_bOutputColorRegister[0] )
  1656. {
  1657. strcat_s( pParamCode, bufParamCode.Size(), "OUTPUT oC0 = result.color;\n" );
  1658. }
  1659. }
  1660. // this looks stale - ax it ?
  1661. //if (m_bVertexShader && !m_bDoFixupZ)
  1662. //{
  1663. // static char foo = 1;
  1664. // if(foo) Debugger();
  1665. //}
  1666. if ( m_bDeclareVSOPos && m_bVertexShader )
  1667. {
  1668. if ( m_bDoFixupZ || m_bDoFixupY)
  1669. {
  1670. // don't write to real reg - declare a temp and then declare a new output reg oPosGL
  1671. strcat_s( pParamCode, bufParamCode.Size(), "TEMP oPos;\n" );
  1672. strcat_s( pParamCode, bufParamCode.Size(), "OUTPUT oPosGL = result.position;\n" );
  1673. // TODO: insert clip distance computation something like this:
  1674. //
  1675. // strcat_s( pALUCode, bufALUCode.Size(), "DP4 oCLP[0].x, oPos, c[215]; \n" );
  1676. //
  1677. if (m_bDoFixupZ)
  1678. {
  1679. // append insns to perform Z fixup
  1680. // new Z = (old Z * 2.0) - W
  1681. // negate Z, double it, then add the 'w'.
  1682. // near: Z=0 -> Z' = +1.0. this seems wrong....
  1683. // far: Z=1 -> Z' = -1.0 uh, this ain't right...
  1684. // strcat_s( pALUCode, bufALUCode.Size(), "MAD r0.z, -oPos.z, c[0].z, oPos.w; # z' = (2*-z)+w \n" );
  1685. // double Z, subtract 'w'.
  1686. // near: Z=0 -> Z' = -1.0.
  1687. // far: Z=1 -> Z' = +1.0
  1688. //strcat_s( pALUCode, bufALUCode.Size(), "MAD r0.z, oPos.z, c[0].z, -oPos.w; # z' = (2*z)-w \n" );
  1689. strcat_s( pALUCode, bufALUCode.Size(), "MAD oPos.z, oPos.z, c[0].z, -oPos.w; # z' = (2*z)-w \n" );
  1690. }
  1691. if (m_bDoFixupY)
  1692. {
  1693. // append insns to flip Y over
  1694. // new Y = -(old Y)
  1695. strcat_s( pALUCode, bufALUCode.Size(), "MOV oPos.y, -oPos.y; # y' = -y \n" );
  1696. }
  1697. strcat_s( pALUCode, bufALUCode.Size(), "MOV oPosGL, oPos; \n" );
  1698. }
  1699. else
  1700. {
  1701. strcat_s( pParamCode, bufParamCode.Size(), "OUTPUT oPos = result.position;\n" );
  1702. // TODO: insert clip distance computation something like this:
  1703. //
  1704. // strcat_s( pALUCode, bufALUCode.Size(), "DP4 oCLP[0].x, oPos, c[215]; \n" );
  1705. //
  1706. }
  1707. }
  1708. if (m_bVertexShader && m_bDoUserClipPlanes)
  1709. {
  1710. // insert oCLP generation insts
  1711. char temp[256];
  1712. if(0)
  1713. {
  1714. V_snprintf( temp, sizeof( temp ), "DP4 result.clip[0].x, oPos, c[%d];\n", DXABSTRACT_VS_CLIP_PLANE_BASE ); // ask GLM where to stash the secret params
  1715. V_snprintf( temp, sizeof( temp ), "DP4 result.clip[1].x, oPos, c[%d];\n", DXABSTRACT_VS_CLIP_PLANE_BASE+1 );
  1716. }
  1717. if(0)
  1718. {
  1719. V_snprintf( temp, sizeof( temp ), "DP4 o[CLP0].x, oPos, c[%d];\n", DXABSTRACT_VS_CLIP_PLANE_BASE ); // ask GLM where to stash the secret params
  1720. V_snprintf( temp, sizeof( temp ), "DP4 o[CLP1].x, oPos, c[%d];\n", DXABSTRACT_VS_CLIP_PLANE_BASE+1 );
  1721. }
  1722. if(1)
  1723. {
  1724. V_snprintf( temp, sizeof( temp ), "DP4 oClip0.x, oPos, c[%d];\n", DXABSTRACT_VS_CLIP_PLANE_BASE ); // ask GLM where to stash the secret params
  1725. V_snprintf( temp, sizeof( temp ), "DP4 oClip1.x, oPos, c[%d];\n", DXABSTRACT_VS_CLIP_PLANE_BASE+1 );
  1726. }
  1727. strcat_s( pALUCode, bufALUCode.Size(), temp );
  1728. }
  1729. if ( m_bDeclareVSOFog && m_bVertexShader )
  1730. {
  1731. strcat_s( pParamCode, bufParamCode.Size(), "OUTPUT oFog = result.fogcoord;\n" );
  1732. }
  1733. for ( int i=0; i<32; i++ )
  1734. {
  1735. char outTexCoordBuff[64];
  1736. if ( m_dwTexCoordOutMask & ( 0x00000001 << i ) )
  1737. {
  1738. V_snprintf( outTexCoordBuff, sizeof( outTexCoordBuff ), "OUTPUT oT%d = result.texcoord[%d];\n", i, i );
  1739. strcat_s( pParamCode, bufParamCode.Size(), outTexCoordBuff );
  1740. }
  1741. }
  1742. if ( m_bOutputColorRegister[0] && m_bVertexShader )
  1743. {
  1744. strcat_s( pParamCode, bufParamCode.Size(), "OUTPUT oD0 = result.color;\n" );
  1745. }
  1746. if ( m_bOutputColorRegister[1] && m_bVertexShader )
  1747. {
  1748. strcat_s( pParamCode, bufParamCode.Size(), "OUTPUT oD1 = result.color.secondary;\n" );
  1749. }
  1750. if ( m_bOutputDepthRegister && !m_bVertexShader )
  1751. {
  1752. strcat_s( pParamCode, bufParamCode.Size(), "OUTPUT oDepth = result.depth;\n" );
  1753. }
  1754. if ( m_bDoUserClipPlanes && m_bVertexShader )
  1755. {
  1756. strcat_s( pParamCode, bufParamCode.Size(), "OUTPUT oClip0 = result.clip[0];\n" );
  1757. strcat_s( pParamCode, bufParamCode.Size(), "OUTPUT oClip1 = result.clip[1];\n" );
  1758. }
  1759. // do some annotation at the end of the attrib block
  1760. {
  1761. char temp[1000];
  1762. if (m_bVertexShader)
  1763. {
  1764. // write attrib map into the text starting at pAttribMapStart - two hex digits per attrib
  1765. for( int i=0; i<16; i++)
  1766. {
  1767. if (m_dwAttribMap[i] != 0xFFFFFFFF)
  1768. {
  1769. V_snprintf( temp, sizeof(temp), "%02X", m_dwAttribMap[i] );
  1770. memcpy( pAttribMapStart + (i*3), temp, 2 );
  1771. }
  1772. }
  1773. }
  1774. V_snprintf( temp, sizeof(temp), "#// trans#%d label:%s\n", g_translationCounter, debugLabel?debugLabel:"none" );
  1775. strcat_s( pAttribCode, bufAttribCode.Size(), temp );
  1776. g_translationCounter++;
  1777. }
  1778. // If we actually sample from a shadow depth sampler, we need to declare the shadow option at the top
  1779. if ( m_bDeclareShadowOption )
  1780. {
  1781. strcat_s( pHeaderCode, nBufLen, "OPTION ARB_fragment_program_shadow;\n" );
  1782. }
  1783. // Put all of the strings together for final program ( pHeaderCode + pAttribCode + pParamCode + pALUCode )
  1784. strcat_s( pHeaderCode, nBufLen, pAttribCode );
  1785. strcat_s( pHeaderCode, nBufLen, pParamCode );
  1786. strcat_s( pHeaderCode, nBufLen, pALUCode );
  1787. strcat_s( pHeaderCode, nBufLen, "END\n\0" );
  1788. if (m_bSpew)
  1789. {
  1790. printf("\n************* translation complete\n\n " );
  1791. }
  1792. return DISASM_OK;
  1793. }
  1794. #endif