shaderCompHLSL.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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 = getIndexedElement( mCurTexElem, type, numElements, numRegisters );
  32. // Adjust texture offset if this is a texcoord type
  33. if( type == RT_TEXCOORD )
  34. {
  35. if ( numRegisters != -1 )
  36. mCurTexElem += numRegisters;
  37. else
  38. mCurTexElem += numElements;
  39. }
  40. return ret;
  41. }
  42. Var * ShaderConnectorHLSL::getIndexedElement( U32 index, RegisterType type, U32 numElements /*= 1*/, U32 numRegisters /*= -1 */ )
  43. {
  44. switch( type )
  45. {
  46. case RT_POSITION:
  47. {
  48. Var *newVar = new Var;
  49. mElementList.push_back( newVar );
  50. newVar->setConnectName( "POSITION" );
  51. return newVar;
  52. }
  53. case RT_NORMAL:
  54. {
  55. Var *newVar = new Var;
  56. mElementList.push_back( newVar );
  57. newVar->setConnectName( "NORMAL" );
  58. return newVar;
  59. }
  60. case RT_BINORMAL:
  61. {
  62. Var *newVar = new Var;
  63. mElementList.push_back( newVar );
  64. newVar->setConnectName( "BINORMAL" );
  65. return newVar;
  66. }
  67. case RT_TANGENT:
  68. {
  69. Var *newVar = new Var;
  70. mElementList.push_back( newVar );
  71. newVar->setConnectName( "TANGENT" );
  72. return newVar;
  73. }
  74. case RT_COLOR:
  75. {
  76. Var *newVar = new Var;
  77. mElementList.push_back( newVar );
  78. newVar->setConnectName( "COLOR" );
  79. return newVar;
  80. }
  81. case RT_VPOS:
  82. {
  83. Var *newVar = new Var;
  84. mElementList.push_back( newVar );
  85. newVar->setConnectName( "VPOS" );
  86. return newVar;
  87. }
  88. case RT_TEXCOORD:
  89. {
  90. Var *newVar = new Var;
  91. mElementList.push_back( newVar );
  92. // This was needed for hardware instancing, but
  93. // i don't really remember why right now.
  94. if ( index > mCurTexElem )
  95. mCurTexElem = index + 1;
  96. char out[32];
  97. dSprintf( (char*)out, sizeof(out), "TEXCOORD%d", index );
  98. newVar->setConnectName( out );
  99. newVar->constNum = index;
  100. newVar->arraySize = numElements;
  101. return newVar;
  102. }
  103. default:
  104. break;
  105. }
  106. return NULL;
  107. }
  108. void ShaderConnectorHLSL::sortVars()
  109. {
  110. if ( GFX->getPixelShaderVersion() >= 2.0 )
  111. return;
  112. // Sort connector variables - They must be sorted on hardware that is running
  113. // ps 1.4 and below. The reason is that texture coordinate registers MUST
  114. // map exactly to their respective texture stage. Ie. if you have fog
  115. // coordinates being passed into a pixel shader in texture coordinate register
  116. // number 4, the fog texture MUST reside in texture stage 4 for it to work.
  117. // The problem is solved by pushing non-texture coordinate data to the end
  118. // of the structure so that the texture coodinates are all at the "top" of the
  119. // structure in the order that the features are processed.
  120. // create list of just the texCoords, sorting by 'mapsToSampler'
  121. Vector< Var * > texCoordList;
  122. // - first pass is just coords mapped to a sampler
  123. for( U32 i=0; i<mElementList.size(); i++ )
  124. {
  125. Var *var = mElementList[i];
  126. if( var->mapsToSampler )
  127. {
  128. texCoordList.push_back( var );
  129. }
  130. }
  131. // - next pass is for the others
  132. for( U32 i=0; i<mElementList.size(); i++ )
  133. {
  134. Var *var = mElementList[i];
  135. if( dStrstr( (const char *)var->connectName, "TEX" ) &&
  136. !var->mapsToSampler )
  137. {
  138. texCoordList.push_back( var );
  139. }
  140. }
  141. // rename the connectNames
  142. for( U32 i=0; i<texCoordList.size(); i++ )
  143. {
  144. char out[32];
  145. dSprintf( (char*)out, sizeof(out), "TEXCOORD%d", i );
  146. texCoordList[i]->setConnectName( out );
  147. }
  148. // write new, sorted list over old one
  149. if( texCoordList.size() )
  150. {
  151. U32 index = 0;
  152. for( U32 i=0; i<mElementList.size(); i++ )
  153. {
  154. Var *var = mElementList[i];
  155. if( dStrstr( (const char *)var->connectName, "TEX" ) )
  156. {
  157. mElementList[i] = texCoordList[index];
  158. index++;
  159. }
  160. }
  161. }
  162. }
  163. void ShaderConnectorHLSL::setName( char *newName )
  164. {
  165. dStrcpy( (char*)mName, newName );
  166. }
  167. void ShaderConnectorHLSL::reset()
  168. {
  169. for( U32 i=0; i<mElementList.size(); i++ )
  170. {
  171. mElementList[i] = NULL;
  172. }
  173. mElementList.setSize( 0 );
  174. mCurTexElem = 0;
  175. }
  176. void ShaderConnectorHLSL::print( Stream &stream, bool isVertexShader )
  177. {
  178. const char * header = "struct ";
  179. const char * header2 = "\r\n{\r\n";
  180. const char * footer = "};\r\n\r\n\r\n";
  181. stream.write( dStrlen(header), header );
  182. stream.write( dStrlen((char*)mName), mName );
  183. stream.write( dStrlen(header2), header2 );
  184. // print out elements
  185. for( U32 i=0; i<mElementList.size(); i++ )
  186. {
  187. U8 output[256];
  188. Var *var = mElementList[i];
  189. if (var->arraySize <= 1)
  190. dSprintf( (char*)output, sizeof(output), " %s %-15s : %s;\r\n", var->type, var->name, var->connectName );
  191. else
  192. dSprintf( (char*)output, sizeof(output), " %s %s[%d] : %s;\r\n", var->type, var->name, var->arraySize, var->connectName );
  193. stream.write( dStrlen((char*)output), output );
  194. }
  195. stream.write( dStrlen(footer), footer );
  196. }
  197. void ParamsDefHLSL::assignConstantNumbers()
  198. {
  199. // Here we assign constant number to uniform vars, sorted
  200. // by their update frequency.
  201. U32 mCurrConst = 0;
  202. for (U32 bin = cspUninit+1; bin < csp_Count; bin++)
  203. {
  204. // Find all the uniform variables that are part of this group and assign constant numbers
  205. for( U32 i=0; i<LangElement::elementList.size(); i++)
  206. {
  207. Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
  208. if( var )
  209. {
  210. bool shaderConst = var->uniform && !var->sampler;
  211. AssertFatal((!shaderConst) || var->constSortPos != cspUninit, "Const sort position has not been set, variable will not receive a constant number!!");
  212. if( shaderConst && var->constSortPos == bin)
  213. {
  214. var->constNum = mCurrConst;
  215. // Increment our constant number based on the variable type
  216. if (dStrcmp((const char*)var->type, "float4x4") == 0)
  217. {
  218. mCurrConst += (4 * var->arraySize);
  219. } else {
  220. if (dStrcmp((const char*)var->type, "float3x3") == 0)
  221. {
  222. mCurrConst += (3 * var->arraySize);
  223. } else {
  224. mCurrConst += var->arraySize;
  225. }
  226. }
  227. }
  228. }
  229. }
  230. }
  231. }
  232. void VertexParamsDefHLSL::print( Stream &stream, bool isVerterShader )
  233. {
  234. assignConstantNumbers();
  235. const char *opener = "ConnectData main( VertData IN";
  236. stream.write( dStrlen(opener), opener );
  237. // find all the uniform variables and print them out
  238. for( U32 i=0; i<LangElement::elementList.size(); i++)
  239. {
  240. Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
  241. if( var )
  242. {
  243. if( var->uniform )
  244. {
  245. const char* nextVar = ",\r\n ";
  246. stream.write( dStrlen(nextVar), nextVar );
  247. U8 varNum[64];
  248. dSprintf( (char*)varNum, sizeof(varNum), "register(C%d)", var->constNum );
  249. U8 output[256];
  250. if (var->arraySize <= 1)
  251. dSprintf( (char*)output, sizeof(output), "uniform %-8s %-15s : %s", var->type, var->name, varNum );
  252. else
  253. dSprintf( (char*)output, sizeof(output), "uniform %-8s %s[%d] : %s", var->type, var->name, var->arraySize, varNum );
  254. stream.write( dStrlen((char*)output), output );
  255. }
  256. }
  257. }
  258. const char *closer = "\r\n)\r\n{\r\n ConnectData OUT;\r\n\r\n";
  259. stream.write( dStrlen(closer), closer );
  260. }
  261. void PixelParamsDefHLSL::print( Stream &stream, bool isVerterShader )
  262. {
  263. assignConstantNumbers();
  264. const char * opener = "Fragout main( ConnectData IN";
  265. stream.write( dStrlen(opener), opener );
  266. // find all the sampler & uniform variables and print them out
  267. for( U32 i=0; i<LangElement::elementList.size(); i++)
  268. {
  269. Var *var = dynamic_cast<Var*>(LangElement::elementList[i]);
  270. if( var )
  271. {
  272. if( var->uniform )
  273. {
  274. WRITESTR( ",\r\n " );
  275. U8 varNum[32];
  276. if( var->sampler )
  277. {
  278. dSprintf( (char*)varNum, sizeof(varNum), ": register(S%d)", var->constNum );
  279. }
  280. else
  281. {
  282. dSprintf( (char*)varNum, sizeof(varNum), ": register(C%d)", var->constNum );
  283. }
  284. U8 output[256];
  285. if (var->arraySize <= 1)
  286. dSprintf( (char*)output, sizeof(output), "uniform %-9s %-15s %s", var->type, var->name, varNum );
  287. else
  288. dSprintf( (char*)output, sizeof(output), "uniform %-9s %s[%d] %s", var->type, var->name, var->arraySize, varNum );
  289. WRITESTR( (char*) output );
  290. }
  291. }
  292. }
  293. const char *closer = "\r\n)\r\n{\r\n Fragout OUT;\r\n\r\n";
  294. stream.write( dStrlen(closer), closer );
  295. }