shaderCompHLSL.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "shaderGen/HLSL/shaderCompHLSL.h"
  24. #include "shaderGen/shaderComp.h"
  25. #include "shaderGen/langElement.h"
  26. #include "gfx/gfxDevice.h"
  27. Var * ShaderConnectorHLSL::getElement( RegisterType type,
  28. U32 numElements,
  29. U32 numRegisters )
  30. {
  31. Var *ret = NULL;
  32. if ( type == RT_BLENDINDICES )
  33. {
  34. ret = getIndexedElement( mCurBlendIndicesElem, type, numElements, numRegisters );
  35. }
  36. else if ( type == RT_BLENDWEIGHT )
  37. {
  38. ret = getIndexedElement( mCurBlendWeightsElem, type, numElements, numRegisters );
  39. }
  40. else
  41. {
  42. ret = getIndexedElement( mCurTexElem, type, numElements, numRegisters );
  43. }
  44. // Adjust texture offset if this is a texcoord type
  45. if( type == RT_TEXCOORD )
  46. {
  47. if ( numRegisters != -1 )
  48. mCurTexElem += numRegisters;
  49. else
  50. mCurTexElem += numElements;
  51. }
  52. else if ( type == RT_BLENDINDICES )
  53. {
  54. if ( numRegisters != -1 )
  55. mCurBlendIndicesElem += numRegisters;
  56. else
  57. mCurBlendIndicesElem += numElements;
  58. }
  59. else if ( type == RT_BLENDWEIGHT )
  60. {
  61. if ( numRegisters != -1 )
  62. mCurBlendWeightsElem += numRegisters;
  63. else
  64. mCurBlendWeightsElem += numElements;
  65. }
  66. return ret;
  67. }
  68. Var * ShaderConnectorHLSL::getIndexedElement( U32 index, RegisterType type, U32 numElements /*= 1*/, U32 numRegisters /*= -1 */ )
  69. {
  70. switch( type )
  71. {
  72. case RT_POSITION:
  73. {
  74. Var *newVar = new Var;
  75. mElementList.push_back( newVar );
  76. newVar->setConnectName( "POSITION" );
  77. newVar->rank = 0;
  78. return newVar;
  79. }
  80. case RT_VPOS:
  81. {
  82. Var *newVar = new Var;
  83. mElementList.push_back(newVar);
  84. newVar->setConnectName("VPOS");
  85. newVar->rank = 0;
  86. return newVar;
  87. }
  88. case RT_SVPOSITION:
  89. {
  90. Var *newVar = new Var;
  91. mElementList.push_back(newVar);
  92. newVar->setConnectName("SV_Position");
  93. newVar->rank = 0;
  94. return newVar;
  95. }
  96. case RT_NORMAL:
  97. {
  98. Var *newVar = new Var;
  99. mElementList.push_back( newVar );
  100. newVar->setConnectName( "NORMAL" );
  101. newVar->rank = 1;
  102. return newVar;
  103. }
  104. case RT_BINORMAL:
  105. {
  106. Var *newVar = new Var;
  107. mElementList.push_back( newVar );
  108. newVar->setConnectName( "BINORMAL" );
  109. newVar->rank = 2;
  110. return newVar;
  111. }
  112. case RT_TANGENT:
  113. {
  114. Var *newVar = new Var;
  115. mElementList.push_back( newVar );
  116. newVar->setConnectName( "TANGENT" );
  117. newVar->rank = 3;
  118. return newVar;
  119. }
  120. case RT_COLOR:
  121. {
  122. Var *newVar = new Var;
  123. mElementList.push_back( newVar );
  124. newVar->setConnectName( "COLOR" );
  125. newVar->rank = 4;
  126. return newVar;
  127. }
  128. case RT_TEXCOORD:
  129. {
  130. Var *newVar = new Var;
  131. mElementList.push_back( newVar );
  132. // This was needed for hardware instancing, but
  133. // i don't really remember why right now.
  134. if ( index > mCurTexElem )
  135. mCurTexElem = index + 1;
  136. char out[32];
  137. dSprintf( (char*)out, sizeof(out), "TEXCOORD%d", index );
  138. newVar->setConnectName( out );
  139. newVar->constNum = index;
  140. newVar->arraySize = numElements;
  141. newVar->rank = 5 + index;
  142. return newVar;
  143. }
  144. case RT_BLENDINDICES:
  145. {
  146. Var *newVar = new Var;
  147. mElementList.push_back( newVar );
  148. // This was needed for hardware instancing, but
  149. // i don't really remember why right now.
  150. if ( index > mCurBlendIndicesElem )
  151. mCurBlendIndicesElem = index + 1;
  152. char out[32];
  153. dSprintf( (char*)out, sizeof(out), "BLENDINDICES%d", index );
  154. newVar->setConnectName( out );
  155. newVar->constNum = index;
  156. newVar->arraySize = numElements;
  157. return newVar;
  158. }
  159. case RT_BLENDWEIGHT:
  160. {
  161. Var *newVar = new Var;
  162. mElementList.push_back( newVar );
  163. // This was needed for hardware instancing, but
  164. // i don't really remember why right now.
  165. if ( index > mCurBlendWeightsElem )
  166. mCurBlendWeightsElem = index + 1;
  167. char out[32];
  168. dSprintf( (char*)out, sizeof(out), "BLENDWEIGHT%d", index );
  169. newVar->setConnectName( out );
  170. newVar->constNum = index;
  171. newVar->arraySize = numElements;
  172. return newVar;
  173. }
  174. default:
  175. break;
  176. }
  177. return NULL;
  178. }
  179. S32 QSORT_CALLBACK ShaderConnectorHLSL::_hlsl4VarSort(const void* e1, const void* e2)
  180. {
  181. Var* a = *((Var **)e1);
  182. Var* b = *((Var **)e2);
  183. return a->rank - b->rank;
  184. }
  185. void ShaderConnectorHLSL::sortVars()
  186. {
  187. // If shader model 4+ than we gotta sort the vars to make sure the order is consistent
  188. if (GFX->getPixelShaderVersion() >= 4.f)
  189. {
  190. dQsort((void *)&mElementList[0], mElementList.size(), sizeof(Var *), _hlsl4VarSort);
  191. return;
  192. }
  193. return;
  194. }
  195. void ShaderConnectorHLSL::setName( const char *newName )
  196. {
  197. dStrcpy( (char*)mName, newName, 32 );
  198. }
  199. void ShaderConnectorHLSL::reset()
  200. {
  201. for( U32 i=0; i<mElementList.size(); i++ )
  202. {
  203. mElementList[i] = NULL;
  204. }
  205. mElementList.setSize( 0 );
  206. mCurTexElem = 0;
  207. mCurBlendIndicesElem = 0;
  208. mCurBlendWeightsElem = 0;
  209. }
  210. void ShaderConnectorHLSL::print( Stream &stream, bool isVertexShader )
  211. {
  212. const char * header = "struct ";
  213. const char * header2 = "\r\n{\r\n";
  214. const char * footer = "};\r\n\r\n\r\n";
  215. stream.write( dStrlen(header), header );
  216. stream.write( dStrlen((char*)mName), mName );
  217. stream.write( dStrlen(header2), header2 );
  218. // print out elements
  219. for( U32 i=0; i<mElementList.size(); i++ )
  220. {
  221. U8 output[256];
  222. Var *var = mElementList[i];
  223. if (var->arraySize <= 1)
  224. dSprintf( (char*)output, sizeof(output), " %s %-15s : %s;\r\n", var->type, var->name, var->connectName );
  225. else
  226. dSprintf( (char*)output, sizeof(output), " %s %s[%d] : %s;\r\n", var->type, var->name, var->arraySize, var->connectName );
  227. stream.write( dStrlen((char*)output), output );
  228. }
  229. stream.write( dStrlen(footer), footer );
  230. }
  231. void ParamsDefHLSL::assignConstantNumbers()
  232. {
  233. // Here we assign constant number to uniform vars, sorted
  234. // by their update frequency.
  235. U32 mCurrConst = 0;
  236. for (U32 bin = cspUninit+1; bin < csp_Count; bin++)
  237. {
  238. // Find all the uniform variables that are part of this group and assign constant numbers
  239. for( U32 i=0; i<LangElement::elementList.size(); i++)
  240. {
  241. Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
  242. if( var )
  243. {
  244. bool shaderConst = var->uniform && !var->sampler && !var->texture;
  245. AssertFatal((!shaderConst) || var->constSortPos != cspUninit, "Const sort position has not been set, variable will not receive a constant number!!");
  246. if( shaderConst && var->constSortPos == bin)
  247. {
  248. var->constNum = mCurrConst;
  249. // Increment our constant number based on the variable type
  250. if (String::compare((const char*)var->type, "float4x4") == 0)
  251. {
  252. mCurrConst += (4 * var->arraySize);
  253. }
  254. else
  255. {
  256. if (String::compare((const char*)var->type, "float3x3") == 0)
  257. {
  258. mCurrConst += (3 * var->arraySize);
  259. }
  260. else
  261. {
  262. if (String::compare((const char*)var->type, "float4x3") == 0)
  263. {
  264. mCurrConst += (3 * var->arraySize);
  265. }
  266. else
  267. {
  268. mCurrConst += var->arraySize;
  269. }
  270. }
  271. }
  272. }
  273. }
  274. }
  275. }
  276. }
  277. void VertexParamsDefHLSL::print( Stream &stream, bool isVerterShader )
  278. {
  279. assignConstantNumbers();
  280. const char *opener = "ConnectData main( VertData IN";
  281. stream.write( dStrlen(opener), opener );
  282. // find all the uniform variables and print them out
  283. for( U32 i=0; i<LangElement::elementList.size(); i++)
  284. {
  285. Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
  286. if( var )
  287. {
  288. if( var->uniform )
  289. {
  290. const char* nextVar = ",\r\n ";
  291. stream.write( dStrlen(nextVar), nextVar );
  292. U8 varNum[64];
  293. dSprintf( (char*)varNum, sizeof(varNum), "register(C%d)", var->constNum );
  294. U8 output[256];
  295. if (var->arraySize <= 1)
  296. dSprintf( (char*)output, sizeof(output), "uniform %-8s %-15s : %s", var->type, var->name, varNum );
  297. else
  298. dSprintf( (char*)output, sizeof(output), "uniform %-8s %s[%d] : %s", var->type, var->name, var->arraySize, varNum );
  299. stream.write( dStrlen((char*)output), output );
  300. }
  301. }
  302. }
  303. const char *closer = "\r\n)\r\n{\r\n ConnectData OUT;\r\n\r\n";
  304. stream.write( dStrlen(closer), closer );
  305. }
  306. void PixelParamsDefHLSL::print( Stream &stream, bool isVerterShader )
  307. {
  308. assignConstantNumbers();
  309. const char * opener = "Fragout main( ConnectData IN";
  310. stream.write( dStrlen(opener), opener );
  311. // find all the sampler & uniform variables and print them out
  312. for( U32 i=0; i<LangElement::elementList.size(); i++)
  313. {
  314. Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
  315. if( var )
  316. {
  317. if( var->uniform )
  318. {
  319. WRITESTR( ",\r\n " );
  320. U8 varNum[32];
  321. if( var->sampler )
  322. {
  323. dSprintf( (char*)varNum, sizeof(varNum), ": register(S%d)", var->constNum );
  324. }
  325. else if (var->texture)
  326. {
  327. dSprintf((char*)varNum, sizeof(varNum), ": register(T%d)", var->constNum);
  328. }
  329. else
  330. {
  331. dSprintf( (char*)varNum, sizeof(varNum), ": register(C%d)", var->constNum );
  332. }
  333. U8 output[256];
  334. if (var->arraySize <= 1)
  335. dSprintf( (char*)output, sizeof(output), "uniform %-9s %-15s %s", var->type, var->name, varNum );
  336. else
  337. dSprintf( (char*)output, sizeof(output), "uniform %-9s %s[%d] %s", var->type, var->name, var->arraySize, varNum );
  338. WRITESTR( (char*) output );
  339. }
  340. }
  341. }
  342. const char *closer = "\r\n)\r\n{\r\n Fragout OUT;\r\n\r\n";
  343. stream.write( dStrlen(closer), closer );
  344. }