gfxD3D9Shader.cpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557
  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. #if defined(TORQUE_OS_XENON)
  24. # include <xtl.h>
  25. #else
  26. # include <d3d9.h>
  27. #endif
  28. #include "gfx/D3D9/gfxD3D9Shader.h"
  29. #include "gfx/D3D9/gfxD3D9Device.h"
  30. #include "core/frameAllocator.h"
  31. #include "core/stream/fileStream.h"
  32. #include "core/util/safeDelete.h"
  33. #include "console/console.h"
  34. #include "math/mMathFn.h"
  35. using namespace Torque;
  36. extern bool gDisassembleAllShaders;
  37. /// D3DXInclude plugin
  38. class _gfxD3DXInclude : public ID3DXInclude, public StrongRefBase
  39. {
  40. private:
  41. Vector<String> mLastPath;
  42. public:
  43. void setPath( const String &path )
  44. {
  45. mLastPath.clear();
  46. mLastPath.push_back( path );
  47. }
  48. _gfxD3DXInclude() {}
  49. virtual ~_gfxD3DXInclude() {}
  50. STDMETHOD(Close)(THIS_ LPCVOID pData);
  51. // 360
  52. STDMETHOD(Open)(THIS_ D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes, /* OUT */ LPSTR pFullPath, DWORD cbFullPath);
  53. // PC
  54. STDMETHOD(Open)(THIS_ D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes)
  55. {
  56. return Open( IncludeType, pFileName, pParentData, ppData, pBytes, NULL, 0 );
  57. }
  58. };
  59. _gfxD3DXIncludeRef GFXD3D9Shader::smD3DXInclude = NULL;
  60. HRESULT _gfxD3DXInclude::Open(THIS_ D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName,
  61. LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes,
  62. LPSTR pFullPath, DWORD cbFullPath)
  63. {
  64. // First try making the path relative to the parent.
  65. Torque::Path path = Torque::Path::Join( mLastPath.last(), '/', pFileName );
  66. path = Torque::Path::CompressPath( path );
  67. if ( !Torque::FS::ReadFile( path, (void *&)*ppData, *pBytes, true ) )
  68. {
  69. // Ok... now try using the path as is.
  70. path = String( pFileName );
  71. path = Torque::Path::CompressPath( path );
  72. if ( !Torque::FS::ReadFile( path, (void *&)*ppData, *pBytes, true ) )
  73. {
  74. AssertISV(false, avar( "Failed to open include '%s'.", pFileName));
  75. return E_FAIL;
  76. }
  77. }
  78. // If the data was of zero size then we cannot recurse
  79. // into this file and DX won't call Close() below.
  80. //
  81. // So in this case don't push on the path.
  82. if ( *pBytes > 0 )
  83. mLastPath.push_back( path.getRootAndPath() );
  84. return S_OK;
  85. }
  86. HRESULT _gfxD3DXInclude::Close( THIS_ LPCVOID pData )
  87. {
  88. // Free the data file and pop its path off the stack.
  89. delete [] (U8*)pData;
  90. mLastPath.pop_back();
  91. return S_OK;
  92. }
  93. GFXD3D9ShaderConstHandle::GFXD3D9ShaderConstHandle()
  94. {
  95. clear();
  96. }
  97. const String& GFXD3D9ShaderConstHandle::getName() const
  98. {
  99. if ( mVertexConstant )
  100. return mVertexHandle.name;
  101. else
  102. return mPixelHandle.name;
  103. }
  104. GFXShaderConstType GFXD3D9ShaderConstHandle::getType() const
  105. {
  106. if ( mVertexConstant )
  107. return mVertexHandle.constType;
  108. else
  109. return mPixelHandle.constType;
  110. }
  111. U32 GFXD3D9ShaderConstHandle::getArraySize() const
  112. {
  113. if ( mVertexConstant )
  114. return mVertexHandle.arraySize;
  115. else
  116. return mPixelHandle.arraySize;
  117. }
  118. S32 GFXD3D9ShaderConstHandle::getSamplerRegister() const
  119. {
  120. if ( !mValid || !isSampler() )
  121. return -1;
  122. // We always store sampler type and register index in the pixelHandle,
  123. // sampler registers are shared between vertex and pixel shaders anyway.
  124. return mPixelHandle.offset;
  125. }
  126. //------------------------------------------------------------------------------
  127. //------------------------------------------------------------------------------
  128. bool GFXD3D9ShaderBufferLayout::setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer)
  129. {
  130. PROFILE_SCOPE(GFXD3D9ShaderBufferLayout_setMatrix);
  131. if (pd.constType == GFXSCT_Float4x4)
  132. {
  133. // Special case, we can just blast this guy.
  134. AssertFatal(pd.size >= size, "Not enough room in the buffer for this data!");
  135. if (dMemcmp(basePointer+pd.offset, data, size) != 0)
  136. {
  137. dMemcpy(basePointer+pd.offset, data, size);
  138. return true;
  139. }
  140. return false;
  141. }
  142. else if (pd.constType == GFXSCT_Float4x3)
  143. {
  144. const U32 csize = 48;
  145. // Loop through and copy
  146. bool ret = false;
  147. U8* currDestPointer = basePointer + pd.offset;
  148. const U8* currSourcePointer = static_cast<const U8*>(data);
  149. const U8* endData = currSourcePointer + size;
  150. while (currSourcePointer < endData)
  151. {
  152. #ifdef TORQUE_DOUBLE_CHECK_43MATS
  153. Point4F col;
  154. ((MatrixF*)currSourcePointer)->getRow(3, &col);
  155. AssertFatal(col.x == 0.0f && col.y == 0.0f && col.z == 0.0f && col.w == 1.0f, "3rd row used");
  156. #endif
  157. if (dMemcmp(currDestPointer, currSourcePointer, csize) != 0)
  158. {
  159. dMemcpy(currDestPointer, currSourcePointer, csize);
  160. ret = true;
  161. }
  162. else if (pd.constType == GFXSCT_Float4x3)
  163. {
  164. ret = true;
  165. }
  166. currDestPointer += csize;
  167. currSourcePointer += sizeof(MatrixF);
  168. }
  169. return ret;
  170. }
  171. else
  172. {
  173. PROFILE_SCOPE(GFXD3D9ShaderBufferLayout_setMatrix_not4x4);
  174. // Figure out how big of a chunk we are copying. We're going to copy 4 columns by N rows of data
  175. U32 csize;
  176. switch (pd.constType)
  177. {
  178. case GFXSCT_Float2x2 :
  179. csize = 32;
  180. break;
  181. case GFXSCT_Float3x3 :
  182. csize = 48;
  183. break;
  184. case GFXSCT_Float3x4 :
  185. csize = 64;
  186. break;
  187. default:
  188. AssertFatal(false, "Unhandled case!");
  189. return false;
  190. break;
  191. }
  192. // Loop through and copy
  193. bool ret = false;
  194. U8* currDestPointer = basePointer+pd.offset;
  195. const U8* currSourcePointer = static_cast<const U8*>(data);
  196. const U8* endData = currSourcePointer + size;
  197. while (currSourcePointer < endData)
  198. {
  199. if (dMemcmp(currDestPointer, currSourcePointer, csize) != 0)
  200. {
  201. dMemcpy(currDestPointer, currSourcePointer, csize);
  202. ret = true;
  203. }
  204. else if (pd.constType == GFXSCT_Float4x3)
  205. {
  206. ret = true;
  207. }
  208. currDestPointer += csize;
  209. currSourcePointer += sizeof(MatrixF);
  210. }
  211. return ret;
  212. }
  213. }
  214. //------------------------------------------------------------------------------
  215. GFXD3D9ShaderConstBuffer::GFXD3D9ShaderConstBuffer( GFXD3D9Shader* shader,
  216. GFXD3D9ShaderBufferLayout* vertexLayoutF,
  217. GFXD3D9ShaderBufferLayout* vertexLayoutI,
  218. GFXD3D9ShaderBufferLayout* pixelLayoutF,
  219. GFXD3D9ShaderBufferLayout* pixelLayoutI )
  220. {
  221. AssertFatal( shader, "GFXD3D9ShaderConstBuffer() - Got a null shader!" );
  222. // We hold on to this so we don't have to call
  223. // this virtual method during activation.
  224. mDevice = static_cast<GFXD3D9Device*>( GFX )->getDevice();
  225. mShader = shader;
  226. // TODO: Remove buffers and layouts that don't exist for performance?
  227. mVertexConstBufferLayoutF = vertexLayoutF;
  228. mVertexConstBufferF = new GenericConstBuffer(vertexLayoutF);
  229. mVertexConstBufferLayoutI = vertexLayoutI;
  230. mVertexConstBufferI = new GenericConstBuffer(vertexLayoutI);
  231. mPixelConstBufferLayoutF = pixelLayoutF;
  232. mPixelConstBufferF = new GenericConstBuffer(pixelLayoutF);
  233. mPixelConstBufferLayoutI = pixelLayoutI;
  234. mPixelConstBufferI = new GenericConstBuffer(pixelLayoutI);
  235. }
  236. GFXD3D9ShaderConstBuffer::~GFXD3D9ShaderConstBuffer()
  237. {
  238. SAFE_DELETE(mVertexConstBufferF);
  239. SAFE_DELETE(mPixelConstBufferF);
  240. SAFE_DELETE(mVertexConstBufferI);
  241. SAFE_DELETE(mPixelConstBufferI);
  242. if ( mShader )
  243. mShader->_unlinkBuffer( this );
  244. }
  245. GFXShader* GFXD3D9ShaderConstBuffer::getShader()
  246. {
  247. return mShader;
  248. }
  249. // This is kind of cheesy, but I don't think templates would work well here because
  250. // these functions potentially need to be handled differently by other derived types
  251. template<class T>
  252. inline void GFXD3D9ShaderConstBuffer::SET_CONSTANT( GFXShaderConstHandle* handle, const T& fv, GenericConstBuffer *vBuffer, GenericConstBuffer *pBuffer )
  253. {
  254. AssertFatal(dynamic_cast<const GFXD3D9ShaderConstHandle*>(handle), "Incorrect const buffer type!");
  255. const GFXD3D9ShaderConstHandle* h = static_cast<const GFXD3D9ShaderConstHandle*>(handle);
  256. AssertFatal(h, "Handle is NULL!" );
  257. AssertFatal(h->isValid(), "Handle is not valid!" );
  258. AssertFatal(!h->isSampler(), "Handle is sampler constant!" );
  259. AssertFatal(!mShader.isNull(), "Buffer's shader is null!" );
  260. AssertFatal(!h->mShader.isNull(), "Handle's shader is null!" );
  261. AssertFatal(h->mShader.getPointer() == mShader.getPointer(), "Mismatched shaders!");
  262. if ( h->mInstancingConstant )
  263. {
  264. dMemcpy( mInstPtr+h->mPixelHandle.offset, &fv, sizeof( fv ) );
  265. return;
  266. }
  267. if (h->mVertexConstant)
  268. vBuffer->set(h->mVertexHandle, fv);
  269. if (h->mPixelConstant)
  270. pBuffer->set(h->mPixelHandle, fv);
  271. }
  272. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv)
  273. {
  274. SET_CONSTANT(handle, fv, mVertexConstBufferF, mPixelConstBufferF);
  275. }
  276. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2F& fv)
  277. {
  278. SET_CONSTANT(handle, fv, mVertexConstBufferF, mPixelConstBufferF);
  279. }
  280. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3F& fv)
  281. {
  282. SET_CONSTANT(handle, fv, mVertexConstBufferF, mPixelConstBufferF);
  283. }
  284. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4F& fv)
  285. {
  286. SET_CONSTANT(handle, fv, mVertexConstBufferF, mPixelConstBufferF);
  287. }
  288. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const PlaneF& fv)
  289. {
  290. SET_CONSTANT(handle, fv, mVertexConstBufferF, mPixelConstBufferF);
  291. }
  292. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const ColorF& fv)
  293. {
  294. SET_CONSTANT(handle, fv, mVertexConstBufferF, mPixelConstBufferF);
  295. }
  296. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const S32 f)
  297. {
  298. // This is the only type that is allowed to be used
  299. // with a sampler shader constant type, but it is only
  300. // allowed to be set from GLSL.
  301. //
  302. // So we ignore it here... all other cases will assert.
  303. //
  304. if ( ((GFXD3D9ShaderConstHandle*)handle)->isSampler() )
  305. return;
  306. SET_CONSTANT(handle, f, mVertexConstBufferI, mPixelConstBufferI);
  307. }
  308. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point2I& fv)
  309. {
  310. SET_CONSTANT(handle, fv, mVertexConstBufferI, mPixelConstBufferI);
  311. }
  312. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point3I& fv)
  313. {
  314. SET_CONSTANT(handle, fv, mVertexConstBufferI, mPixelConstBufferI);
  315. }
  316. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const Point4I& fv)
  317. {
  318. SET_CONSTANT(handle, fv, mVertexConstBufferI, mPixelConstBufferI);
  319. }
  320. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<F32>& fv)
  321. {
  322. SET_CONSTANT(handle, fv, mVertexConstBufferF, mPixelConstBufferF);
  323. }
  324. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point2F>& fv)
  325. {
  326. SET_CONSTANT(handle, fv, mVertexConstBufferF, mPixelConstBufferF);
  327. }
  328. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point3F>& fv)
  329. {
  330. SET_CONSTANT(handle, fv, mVertexConstBufferF, mPixelConstBufferF);
  331. }
  332. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv)
  333. {
  334. SET_CONSTANT(handle, fv, mVertexConstBufferF, mPixelConstBufferF);
  335. }
  336. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<S32>& fv)
  337. {
  338. SET_CONSTANT(handle, fv, mVertexConstBufferI, mPixelConstBufferI);
  339. }
  340. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point2I>& fv)
  341. {
  342. SET_CONSTANT(handle, fv, mVertexConstBufferI, mPixelConstBufferI);
  343. }
  344. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point3I>& fv)
  345. {
  346. SET_CONSTANT(handle, fv, mVertexConstBufferI, mPixelConstBufferI);
  347. }
  348. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const AlignedArray<Point4I>& fv)
  349. {
  350. SET_CONSTANT(handle, fv, mVertexConstBufferI, mPixelConstBufferI);
  351. }
  352. #undef SET_CONSTANT
  353. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matrixType)
  354. {
  355. AssertFatal(handle, "Handle is NULL!" );
  356. AssertFatal(handle->isValid(), "Handle is not valid!" );
  357. AssertFatal(dynamic_cast<const GFXD3D9ShaderConstHandle*>(handle), "Incorrect const buffer type!");
  358. const GFXD3D9ShaderConstHandle* h = static_cast<const GFXD3D9ShaderConstHandle*>(handle);
  359. AssertFatal(!h->isSampler(), "Handle is sampler constant!" );
  360. AssertFatal(h->mShader == mShader, "Mismatched shaders!");
  361. MatrixF transposed;
  362. if (matrixType == GFXSCT_Float4x3)
  363. {
  364. transposed = mat;
  365. }
  366. else
  367. {
  368. mat.transposeTo(transposed);
  369. }
  370. if (h->mInstancingConstant)
  371. {
  372. if ( matrixType == GFXSCT_Float4x4 )
  373. dMemcpy( mInstPtr+h->mPixelHandle.offset, mat, sizeof( mat ) );
  374. // TODO: Support 3x3 and 2x2 matricies?
  375. return;
  376. }
  377. if (h->mVertexConstant)
  378. mVertexConstBufferF->set(h->mVertexHandle, transposed, matrixType);
  379. if (h->mPixelConstant)
  380. mPixelConstBufferF->set(h->mPixelHandle, transposed, matrixType);
  381. }
  382. void GFXD3D9ShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType)
  383. {
  384. AssertFatal(handle, "Handle is NULL!" );
  385. AssertFatal(handle->isValid(), "Handle is not valid!" );
  386. AssertFatal(dynamic_cast<const GFXD3D9ShaderConstHandle*>(handle), "Incorrect const buffer type!");
  387. const GFXD3D9ShaderConstHandle* h = static_cast<const GFXD3D9ShaderConstHandle*>(handle);
  388. AssertFatal(!h->isSampler(), "Handle is sampler constant!" );
  389. AssertFatal(h->mShader == mShader, "Mismatched shaders!");
  390. static Vector<MatrixF> transposed;
  391. if (arraySize > transposed.size())
  392. transposed.setSize(arraySize);
  393. if (matrixType == GFXSCT_Float4x3)
  394. {
  395. dMemcpy(transposed.address(), mat, arraySize * sizeof(MatrixF));
  396. }
  397. else
  398. {
  399. for (U32 i = 0; i < arraySize; i++)
  400. mat[i].transposeTo(transposed[i]);
  401. }
  402. // TODO: Maybe support this in the future?
  403. if (h->mInstancingConstant)
  404. return;
  405. if (h->mVertexConstant)
  406. mVertexConstBufferF->set(h->mVertexHandle, transposed.begin(), arraySize, matrixType);
  407. if (h->mPixelConstant)
  408. mPixelConstBufferF->set(h->mPixelHandle, transposed.begin(), arraySize, matrixType);
  409. }
  410. const String GFXD3D9ShaderConstBuffer::describeSelf() const
  411. {
  412. String ret;
  413. ret = String(" GFXD3D9ShaderConstBuffer\n");
  414. for (U32 i = 0; i < mVertexConstBufferLayoutF->getParameterCount(); i++)
  415. {
  416. GenericConstBufferLayout::ParamDesc pd;
  417. mVertexConstBufferLayoutF->getDesc(i, pd);
  418. ret += String::ToString(" Constant name: %s", pd.name.c_str());
  419. }
  420. return ret;
  421. }
  422. void GFXD3D9ShaderConstBuffer::zombify()
  423. {
  424. }
  425. void GFXD3D9ShaderConstBuffer::resurrect()
  426. {
  427. }
  428. bool GFXD3D9ShaderConstBuffer::isDirty()
  429. {
  430. bool ret = mVertexConstBufferF->isDirty();
  431. ret |= mVertexConstBufferI->isDirty();
  432. ret |= mPixelConstBufferF->isDirty();
  433. ret |= mPixelConstBufferI->isDirty();
  434. return ret;
  435. }
  436. void GFXD3D9ShaderConstBuffer::activate( GFXD3D9ShaderConstBuffer *prevShaderBuffer )
  437. {
  438. PROFILE_SCOPE(GFXD3D9ShaderConstBuffer_activate);
  439. // NOTE: This is a really critical function as it gets
  440. // called between every draw call to update the constants.
  441. //
  442. // Alot of the calls here are inlined... be careful
  443. // what you change.
  444. // If the buffer has changed we need to compare it
  445. // with the new buffer to see if we can skip copying
  446. // equal buffer content.
  447. //
  448. // If the buffer hasn't changed then we only will
  449. // be copying the changes that have occured since
  450. // the last activate call.
  451. //
  452. if ( prevShaderBuffer != this )
  453. {
  454. // If the previous buffer is dirty, than we can't compare
  455. // against it, because it hasn't sent its contents to the
  456. // card yet and must be copied.
  457. if ( prevShaderBuffer && !prevShaderBuffer->isDirty() )
  458. {
  459. PROFILE_SCOPE(GFXD3D9ShaderConstBuffer_activate_dirty_check_1);
  460. // If the buffer content is equal then we set the dirty
  461. // flag to false knowing the current state of the card matches
  462. // the new buffer.
  463. //
  464. // If the content is not equal we set the dirty flag to
  465. // true which causes the full content of the buffer to be
  466. // copied to the card.
  467. //
  468. mVertexConstBufferF->setDirty( !prevShaderBuffer->mVertexConstBufferF->isEqual( mVertexConstBufferF ) );
  469. mPixelConstBufferF->setDirty( !prevShaderBuffer->mPixelConstBufferF->isEqual( mPixelConstBufferF ) );
  470. mVertexConstBufferI->setDirty( !prevShaderBuffer->mVertexConstBufferF->isEqual( mVertexConstBufferI ) );
  471. mPixelConstBufferI->setDirty( !prevShaderBuffer->mPixelConstBufferF->isEqual( mPixelConstBufferI ) );
  472. }
  473. else
  474. {
  475. // This happens rarely... but it can happen.
  476. //
  477. // We copy the entire dirty state to the card.
  478. PROFILE_SCOPE(GFXD3D9ShaderConstBuffer_activate_dirty_check_2);
  479. mVertexConstBufferF->setDirty( true );
  480. mPixelConstBufferF->setDirty( true );
  481. mVertexConstBufferI->setDirty( true );
  482. mPixelConstBufferI->setDirty( true );
  483. }
  484. }
  485. const U32 bytesToFloat4 = 16;
  486. const U32 bytesToInt4 = 16;
  487. U32 start, bufferSize;
  488. const U8* buf;
  489. if ( mVertexConstBufferF->isDirty() )
  490. {
  491. buf = mVertexConstBufferF->getDirtyBuffer( &start, &bufferSize );
  492. mDevice->SetVertexShaderConstantF( start / bytesToFloat4, (float*)buf, bufferSize / bytesToFloat4 );
  493. }
  494. if ( mPixelConstBufferF->isDirty() )
  495. {
  496. buf = mPixelConstBufferF->getDirtyBuffer( &start, &bufferSize );
  497. mDevice->SetPixelShaderConstantF( start / bytesToFloat4, (float*)buf, bufferSize / bytesToFloat4 );
  498. }
  499. if ( mVertexConstBufferI->isDirty() )
  500. {
  501. buf = mVertexConstBufferI->getDirtyBuffer( &start, &bufferSize );
  502. mDevice->SetVertexShaderConstantI( start / bytesToInt4, (int*)buf, bufferSize / bytesToInt4 );
  503. }
  504. if ( mPixelConstBufferI->isDirty() )
  505. {
  506. buf = mPixelConstBufferI->getDirtyBuffer( &start, &bufferSize );
  507. mDevice->SetPixelShaderConstantI( start / bytesToInt4, (int*)buf, bufferSize / bytesToInt4 );
  508. }
  509. #ifdef TORQUE_DEBUG
  510. // Make sure all the constants for this buffer were assigned.
  511. if ( mWasLost )
  512. {
  513. mVertexConstBufferF->assertUnassignedConstants( mShader->getVertexShaderFile().c_str() );
  514. mVertexConstBufferI->assertUnassignedConstants( mShader->getVertexShaderFile().c_str() );
  515. mPixelConstBufferF->assertUnassignedConstants( mShader->getPixelShaderFile().c_str() );
  516. mPixelConstBufferI->assertUnassignedConstants( mShader->getPixelShaderFile().c_str() );
  517. }
  518. #endif
  519. // Clear the lost state.
  520. mWasLost = false;
  521. }
  522. void GFXD3D9ShaderConstBuffer::onShaderReload( GFXD3D9Shader *shader )
  523. {
  524. AssertFatal( shader == mShader, "GFXD3D9ShaderConstBuffer::onShaderReload is hosed!" );
  525. SAFE_DELETE( mVertexConstBufferF );
  526. SAFE_DELETE( mPixelConstBufferF );
  527. SAFE_DELETE( mVertexConstBufferI );
  528. SAFE_DELETE( mPixelConstBufferI );
  529. AssertFatal( mVertexConstBufferLayoutF == shader->mVertexConstBufferLayoutF, "GFXD3D9ShaderConstBuffer::onShaderReload is hosed!" );
  530. AssertFatal( mPixelConstBufferLayoutF == shader->mPixelConstBufferLayoutF, "GFXD3D9ShaderConstBuffer::onShaderReload is hosed!" );
  531. AssertFatal( mVertexConstBufferLayoutI == shader->mVertexConstBufferLayoutI, "GFXD3D9ShaderConstBuffer::onShaderReload is hosed!" );
  532. AssertFatal( mPixelConstBufferLayoutI == shader->mPixelConstBufferLayoutI, "GFXD3D9ShaderConstBuffer::onShaderReload is hosed!" );
  533. mVertexConstBufferF = new GenericConstBuffer( mVertexConstBufferLayoutF );
  534. mVertexConstBufferI = new GenericConstBuffer( mVertexConstBufferLayoutI );
  535. mPixelConstBufferF = new GenericConstBuffer( mPixelConstBufferLayoutF );
  536. mPixelConstBufferI = new GenericConstBuffer( mPixelConstBufferLayoutI );
  537. // Set the lost state.
  538. mWasLost = true;
  539. }
  540. //------------------------------------------------------------------------------
  541. GFXD3D9Shader::GFXD3D9Shader()
  542. {
  543. VECTOR_SET_ASSOCIATION( mShaderConsts );
  544. mD3D9Device = dynamic_cast<GFXD3D9Device *>(GFX)->getDevice();
  545. AssertFatal(mD3D9Device, "Invalid device for shader.");
  546. mVertShader = NULL;
  547. mPixShader = NULL;
  548. mVertexConstBufferLayoutF = NULL;
  549. mPixelConstBufferLayoutF = NULL;
  550. mVertexConstBufferLayoutI = NULL;
  551. mPixelConstBufferLayoutI = NULL;
  552. if( smD3DXInclude == NULL )
  553. smD3DXInclude = new _gfxD3DXInclude;
  554. }
  555. //------------------------------------------------------------------------------
  556. GFXD3D9Shader::~GFXD3D9Shader()
  557. {
  558. for (HandleMap::Iterator i = mHandles.begin(); i != mHandles.end(); i++)
  559. delete i->value;
  560. SAFE_DELETE(mVertexConstBufferLayoutF);
  561. SAFE_DELETE(mPixelConstBufferLayoutF);
  562. SAFE_DELETE(mVertexConstBufferLayoutI);
  563. SAFE_DELETE(mPixelConstBufferLayoutI);
  564. SAFE_RELEASE(mVertShader);
  565. SAFE_RELEASE(mPixShader);
  566. }
  567. bool GFXD3D9Shader::_init()
  568. {
  569. PROFILE_SCOPE( GFXD3D9Shader_Init );
  570. if ( mPixVersion > GFX->getPixelShaderVersion() )
  571. {
  572. if ( smLogErrors )
  573. Con::errorf( "GFXD3D9Shader::init - Bad pixel shader version!" );
  574. return false;
  575. }
  576. if ( mPixVersion < 1.0f && mPixelFile.getFileName().isNotEmpty() )
  577. {
  578. if ( smLogErrors )
  579. Con::errorf( "GFXD3D9Shader::init - Pixel shaders not supported on SM %.1f!", mPixVersion );
  580. return false;
  581. }
  582. SAFE_RELEASE(mVertShader);
  583. SAFE_RELEASE(mPixShader);
  584. U32 mjVer = (U32)mFloor( mPixVersion );
  585. U32 mnVer = (U32)( ( mPixVersion - F32( mjVer ) ) * 10.01f ); // 10.01 instead of 10.0 because of floating point issues
  586. String vertTarget = String::ToString("vs_%d_%d", mjVer, mnVer);
  587. String pixTarget = String::ToString("ps_%d_%d", mjVer, mnVer);
  588. // Adjust version for vertex shaders
  589. if (mjVer == 2 && mnVer == 1)
  590. {
  591. pixTarget = "ps_2_a";
  592. vertTarget = "vs_2_0";
  593. }
  594. else if ( mjVer == 2 && mnVer == 2 )
  595. {
  596. pixTarget = "ps_2_b";
  597. vertTarget = "vs_2_0";
  598. }
  599. else if ( ( mPixVersion < 2.0f ) && ( mPixVersion > 1.101f ) )
  600. vertTarget = "vs_1_1";
  601. // Create the macro array including the system wide macros.
  602. const U32 macroCount = smGlobalMacros.size() + mMacros.size() + 2;
  603. FrameTemp<D3DXMACRO> d3dXMacros( macroCount );
  604. for ( U32 i=0; i < smGlobalMacros.size(); i++ )
  605. {
  606. d3dXMacros[i].Name = smGlobalMacros[i].name.c_str();
  607. d3dXMacros[i].Definition = smGlobalMacros[i].value.c_str();
  608. }
  609. for ( U32 i=0; i < mMacros.size(); i++ )
  610. {
  611. d3dXMacros[i+smGlobalMacros.size()].Name = mMacros[i].name.c_str();
  612. d3dXMacros[i+smGlobalMacros.size()].Definition = mMacros[i].value.c_str();
  613. }
  614. String smVersion = String::ToString( mjVer * 10 + mnVer );
  615. d3dXMacros[macroCount - 2].Name = "TORQUE_SM";
  616. d3dXMacros[macroCount - 2].Definition = smVersion.c_str();
  617. d3dXMacros[macroCount - 1].Name = NULL;
  618. d3dXMacros[macroCount - 1].Definition = NULL;
  619. if ( !mVertexConstBufferLayoutF )
  620. mVertexConstBufferLayoutF = new GFXD3D9ShaderBufferLayout();
  621. else
  622. mVertexConstBufferLayoutF->clear();
  623. if ( !mVertexConstBufferLayoutI )
  624. mVertexConstBufferLayoutI = new GFXD3D9ShaderBufferLayout();
  625. else
  626. mVertexConstBufferLayoutI->clear();
  627. if ( !mPixelConstBufferLayoutF )
  628. mPixelConstBufferLayoutF = new GFXD3D9ShaderBufferLayout();
  629. else
  630. mPixelConstBufferLayoutF->clear();
  631. if ( !mPixelConstBufferLayoutI )
  632. mPixelConstBufferLayoutI = new GFXD3D9ShaderBufferLayout();
  633. else
  634. mPixelConstBufferLayoutI->clear();
  635. mSamplerDescriptions.clear();
  636. mShaderConsts.clear();
  637. if ( GFXD3DX.isLoaded && !Con::getBoolVariable( "$shaders::forceLoadCSF", false ) )
  638. {
  639. if ( !mVertexFile.isEmpty() &&
  640. !_compileShader( mVertexFile, vertTarget, d3dXMacros, mVertexConstBufferLayoutF, mVertexConstBufferLayoutI, mSamplerDescriptions ) )
  641. return false;
  642. if ( !mPixelFile.isEmpty() &&
  643. !_compileShader( mPixelFile, pixTarget, d3dXMacros, mPixelConstBufferLayoutF, mPixelConstBufferLayoutI, mSamplerDescriptions ) )
  644. return false;
  645. }
  646. else
  647. {
  648. if ( !_loadCompiledOutput( mVertexFile, vertTarget, mVertexConstBufferLayoutF, mVertexConstBufferLayoutI, mSamplerDescriptions ) )
  649. {
  650. if ( smLogErrors )
  651. Con::errorf( "GFXD3D9Shader::init - Unable to load precompiled vertex shader for '%s'.",
  652. mVertexFile.getFullPath().c_str() );
  653. return false;
  654. }
  655. if ( !_loadCompiledOutput( mPixelFile, pixTarget, mPixelConstBufferLayoutF, mPixelConstBufferLayoutI, mSamplerDescriptions ) )
  656. {
  657. if ( smLogErrors )
  658. Con::errorf( "GFXD3D9Shader::init - Unable to load precompiled pixel shader for '%s'.",
  659. mPixelFile.getFullPath().c_str() );
  660. return false;
  661. }
  662. }
  663. // Existing handles are resored to an uninitialized state.
  664. // Those that are found when parsing the layout parameters
  665. // will then be re-initialized.
  666. HandleMap::Iterator iter = mHandles.begin();
  667. for ( ; iter != mHandles.end(); iter++ )
  668. (iter->value)->clear();
  669. _buildShaderConstantHandles(mVertexConstBufferLayoutF, true);
  670. _buildShaderConstantHandles(mVertexConstBufferLayoutI, true);
  671. _buildShaderConstantHandles(mPixelConstBufferLayoutF, false);
  672. _buildShaderConstantHandles(mPixelConstBufferLayoutI, false);
  673. _buildSamplerShaderConstantHandles( mSamplerDescriptions );
  674. _buildInstancingShaderConstantHandles();
  675. // Notify any existing buffers that the buffer
  676. // layouts have changed and they need to update.
  677. Vector<GFXShaderConstBuffer*>::iterator biter = mActiveBuffers.begin();
  678. for ( ; biter != mActiveBuffers.end(); biter++ )
  679. ((GFXD3D9ShaderConstBuffer*)(*biter))->onShaderReload( this );
  680. return true;
  681. }
  682. bool GFXD3D9Shader::_compileShader( const Torque::Path &filePath,
  683. const String& target,
  684. const D3DXMACRO *defines,
  685. GenericConstBufferLayout* bufferLayoutF,
  686. GenericConstBufferLayout* bufferLayoutI,
  687. Vector<GFXShaderConstDesc> &samplerDescriptions )
  688. {
  689. PROFILE_SCOPE( GFXD3D9Shader_CompileShader );
  690. HRESULT res = D3DERR_INVALIDCALL;
  691. LPD3DXBUFFER code = NULL;
  692. LPD3DXBUFFER errorBuff = NULL;
  693. #ifdef TORQUE_DEBUG
  694. U32 flags = D3DXSHADER_DEBUG;
  695. #else
  696. U32 flags = 0;
  697. #endif
  698. #ifdef TORQUE_OS_XENON
  699. flags |= D3DXSHADER_PREFER_FLOW_CONTROL;
  700. #endif
  701. #ifdef D3DXSHADER_USE_LEGACY_D3DX9_31_DLL
  702. if( D3DX_SDK_VERSION >= 32 )
  703. {
  704. // will need to use old compiler for 1_1 shaders - check for pixel
  705. // or vertex shader with appropriate version.
  706. if ((target.compare("vs1", 3) == 0) || (target.compare("vs_1", 4) == 0))
  707. flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;
  708. if ((target.compare("ps1", 3) == 0) || (target.compare("ps_1", 4) == 0))
  709. flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;
  710. }
  711. #endif
  712. #if !defined(TORQUE_OS_XENON) && (D3DX_SDK_VERSION <= 40)
  713. #error This version of the DirectX SDK is too old. Please install a newer version of the DirectX SDK: http://msdn.microsoft.com/en-us/directx/default.aspx
  714. #endif
  715. ID3DXConstantTable* table = NULL;
  716. static String sHLSLStr( "hlsl" );
  717. static String sOBJStr( "obj" );
  718. // Is it an HLSL shader?
  719. if ( filePath.getExtension().equal(sHLSLStr, String::NoCase) )
  720. {
  721. FrameAllocatorMarker fam;
  722. char *buffer = NULL;
  723. // Set this so that the D3DXInclude::Open will have this
  724. // information for relative paths.
  725. smD3DXInclude->setPath( filePath.getRootAndPath() );
  726. FileStream s;
  727. if ( !s.open( filePath, Torque::FS::File::Read ) )
  728. {
  729. AssertISV(false, avar("GFXD3D9Shader::initShader - failed to open shader '%s'.", filePath.getFullPath().c_str()));
  730. if ( smLogErrors )
  731. Con::errorf( "GFXD3D9Shader::_compileShader - Failed to open shader file '%s'.",
  732. filePath.getFullPath().c_str() );
  733. return false;
  734. }
  735. // Convert the path which might have virtualized
  736. // mount paths to a real file system path.
  737. Torque::Path realPath;
  738. if ( !FS::GetFSPath( filePath, realPath ) )
  739. realPath = filePath;
  740. // Add a #line pragma so that error and warning messages
  741. // returned by the HLSL compiler report the right file.
  742. String linePragma = String::ToString( "#line 1 \"%s\"\r\n", realPath.getFullPath().c_str() );
  743. U32 linePragmaLen = linePragma.length();
  744. U32 bufSize = s.getStreamSize();
  745. buffer = (char *)fam.alloc( bufSize + linePragmaLen + 1 );
  746. dStrncpy( buffer, linePragma.c_str(), linePragmaLen );
  747. s.read( bufSize, buffer + linePragmaLen );
  748. buffer[bufSize+linePragmaLen] = 0;
  749. res = GFXD3DX.D3DXCompileShader( buffer, bufSize + linePragmaLen, defines, smD3DXInclude, "main",
  750. target, flags, &code, &errorBuff, &table );
  751. }
  752. // Is it a precompiled obj shader?
  753. else if ( filePath.getExtension().equal( sOBJStr, String::NoCase ) )
  754. {
  755. FileStream s;
  756. if(!s.open(filePath, Torque::FS::File::Read))
  757. {
  758. AssertISV(false, avar("GFXD3D9Shader::initShader - failed to open shader '%s'.", filePath.getFullPath().c_str()));
  759. if ( smLogErrors )
  760. Con::errorf( "GFXD3D9Shader::_compileShader - Failed to open shader file '%s'.",
  761. filePath.getFullPath().c_str() );
  762. return false;
  763. }
  764. res = GFXD3DX.D3DXCreateBuffer(s.getStreamSize(), &code);
  765. AssertISV(res == D3D_OK, "Unable to create buffer!");
  766. s.read(s.getStreamSize(), code->GetBufferPointer());
  767. if (res == D3D_OK)
  768. {
  769. DWORD* data = (DWORD*) code->GetBufferPointer();
  770. res = GFXD3DX.D3DXGetShaderConstantTable(data, &table);
  771. }
  772. }
  773. else
  774. {
  775. if ( smLogErrors )
  776. Con::errorf( "GFXD3D9Shader::_compileShader - Unsupported shader file type '%s'.",
  777. filePath.getFullPath().c_str() );
  778. return false;
  779. }
  780. if ( res != D3D_OK && smLogErrors )
  781. Con::errorf( "GFXD3D9Shader::_compileShader - Error compiling shader: %s: %s (%x)",
  782. DXGetErrorStringA(res), DXGetErrorDescriptionA(res), res );
  783. if ( errorBuff )
  784. {
  785. // remove \n at end of buffer
  786. U8 *buffPtr = (U8*) errorBuff->GetBufferPointer();
  787. U32 len = dStrlen( (const char*) buffPtr );
  788. buffPtr[len-1] = '\0';
  789. if( res != D3D_OK )
  790. {
  791. if ( smLogErrors )
  792. Con::errorf( " %s", (const char*) errorBuff->GetBufferPointer() );
  793. }
  794. else
  795. {
  796. if ( smLogWarnings )
  797. Con::warnf( "%s", (const char*) errorBuff->GetBufferPointer() );
  798. }
  799. }
  800. else if ( code == NULL && smLogErrors )
  801. Con::errorf( "GFXD3D9Shader::_compileShader - no compiled code produced; possibly missing file '%s'.",
  802. filePath.getFullPath().c_str() );
  803. // Create the proper shader if we have code
  804. if( code != NULL )
  805. {
  806. #ifndef TORQUE_SHIPPING
  807. LPD3DXBUFFER disassem = NULL;
  808. D3DXDisassembleShader( (DWORD*)code->GetBufferPointer(), false, NULL, &disassem );
  809. mDissasembly = (const char*)disassem->GetBufferPointer();
  810. SAFE_RELEASE( disassem );
  811. if ( gDisassembleAllShaders )
  812. {
  813. String filename = filePath.getFullPath();
  814. filename.replace( ".hlsl", "_dis.txt" );
  815. FileStream *fstream = FileStream::createAndOpen( filename, Torque::FS::File::Write );
  816. if ( fstream )
  817. {
  818. fstream->write( mDissasembly );
  819. fstream->close();
  820. delete fstream;
  821. }
  822. }
  823. #endif
  824. if (target.compare("ps_", 3) == 0)
  825. res = mD3D9Device->CreatePixelShader( (DWORD*)code->GetBufferPointer(), &mPixShader );
  826. else
  827. res = mD3D9Device->CreateVertexShader( (DWORD*)code->GetBufferPointer(), &mVertShader );
  828. if (res == S_OK)
  829. _getShaderConstants(table, bufferLayoutF, bufferLayoutI, samplerDescriptions);
  830. #ifdef TORQUE_ENABLE_CSF_GENERATION
  831. // Ok, we've got a valid shader and constants, let's write them all out.
  832. if ( !_saveCompiledOutput(filePath, code, bufferLayoutF, bufferLayoutI) && smLogErrors )
  833. Con::errorf( "GFXD3D9Shader::_compileShader - Unable to save shader compile output for: %s",
  834. filePath.getFullPath().c_str() );
  835. #endif
  836. SAFE_RELEASE(table);
  837. if ( res != S_OK && smLogErrors )
  838. Con::errorf( "GFXD3D9Shader::_compileShader - Unable to create shader for '%s'.",
  839. filePath.getFullPath().c_str() );
  840. }
  841. bool result = code != NULL && res == S_OK;
  842. SAFE_RELEASE( code );
  843. SAFE_RELEASE( errorBuff );
  844. return result;
  845. }
  846. void GFXD3D9Shader::_getShaderConstants( ID3DXConstantTable *table,
  847. GenericConstBufferLayout *bufferLayoutF,
  848. GenericConstBufferLayout* bufferLayoutI,
  849. Vector<GFXShaderConstDesc> &samplerDescriptions )
  850. {
  851. PROFILE_SCOPE( GFXD3D9Shader_GetShaderConstants );
  852. AssertFatal(table, "NULL constant table not allowed, is this an assembly shader?");
  853. D3DXCONSTANTTABLE_DESC tableDesc;
  854. D3D9Assert(table->GetDesc(&tableDesc), "Unable to get constant table info.");
  855. for (U32 i = 0; i < tableDesc.Constants; i++)
  856. {
  857. D3DXHANDLE handle = table->GetConstant(0, i);
  858. const U32 descSize=16;
  859. D3DXCONSTANT_DESC constantDescArray[descSize];
  860. U32 size = descSize;
  861. if (table->GetConstantDesc(handle, constantDescArray, &size) == S_OK)
  862. {
  863. D3DXCONSTANT_DESC& constantDesc = constantDescArray[0];
  864. GFXShaderConstDesc desc;
  865. desc.name = String(constantDesc.Name);
  866. // Prepend a "$" if it doesn't exist. Just to make things consistent.
  867. if (desc.name.find("$") != 0)
  868. desc.name = String::ToString("$%s", desc.name.c_str());
  869. //Con::printf("name %s: , offset: %d, size: %d, constantDesc.Elements: %d", desc.name.c_str(), constantDesc.RegisterIndex, constantDesc.Bytes, constantDesc.Elements);
  870. desc.arraySize = constantDesc.Elements;
  871. GenericConstBufferLayout* bufferLayout = NULL;
  872. switch (constantDesc.RegisterSet)
  873. {
  874. case D3DXRS_INT4 :
  875. {
  876. bufferLayout = bufferLayoutI;
  877. switch (constantDesc.Class)
  878. {
  879. case D3DXPC_SCALAR :
  880. desc.constType = GFXSCT_Int;
  881. break;
  882. case D3DXPC_VECTOR :
  883. {
  884. switch (constantDesc.Columns)
  885. {
  886. case 1 :
  887. desc.constType = GFXSCT_Int;
  888. break;
  889. case 2 :
  890. desc.constType = GFXSCT_Int2;
  891. break;
  892. case 3 :
  893. desc.constType = GFXSCT_Int3;
  894. break;
  895. case 4 :
  896. desc.constType = GFXSCT_Int4;
  897. break;
  898. default:
  899. AssertFatal(false, "Unknown int vector type!");
  900. break;
  901. }
  902. }
  903. break;
  904. }
  905. desc.constType = GFXSCT_Int4;
  906. break;
  907. }
  908. case D3DXRS_FLOAT4 :
  909. {
  910. bufferLayout = bufferLayoutF;
  911. switch (constantDesc.Class)
  912. {
  913. case D3DXPC_SCALAR:
  914. desc.constType = GFXSCT_Float;
  915. break;
  916. case D3DXPC_VECTOR :
  917. {
  918. switch (constantDesc.Columns)
  919. {
  920. case 1 :
  921. desc.constType = GFXSCT_Float;
  922. break;
  923. case 2 :
  924. desc.constType = GFXSCT_Float2;
  925. break;
  926. case 3 :
  927. desc.constType = GFXSCT_Float3;
  928. break;
  929. case 4 :
  930. desc.constType = GFXSCT_Float4;
  931. break;
  932. default:
  933. AssertFatal(false, "Unknown float vector type!");
  934. break;
  935. }
  936. }
  937. break;
  938. case D3DXPC_MATRIX_ROWS :
  939. case D3DXPC_MATRIX_COLUMNS :
  940. {
  941. S32 fd, sd;
  942. fd = constantDesc.RegisterCount / constantDesc.Elements;
  943. sd = constantDesc.Class == D3DXPC_MATRIX_ROWS ? constantDesc.Columns : constantDesc.Rows;
  944. switch (fd)
  945. {
  946. case 2 :
  947. AssertFatal(sd == 2, "non-square 2x? mats not supported");
  948. desc.constType = GFXSCT_Float2x2;
  949. break;
  950. case 3 :
  951. switch (sd)
  952. {
  953. case 3 :
  954. desc.constType = GFXSCT_Float3x3;
  955. break;
  956. case 4 :
  957. desc.constType = GFXSCT_Float4x3;
  958. break;
  959. default:
  960. AssertFatal(false, "Unsupported matrix size");
  961. break;
  962. }
  963. break;
  964. case 4 :
  965. switch (sd)
  966. {
  967. case 3:
  968. desc.constType = GFXSCT_Float3x4;
  969. break;
  970. case 4:
  971. desc.constType = GFXSCT_Float4x4;
  972. break;
  973. default:
  974. AssertFatal(false, "Unsupported matrix size");
  975. break;
  976. }
  977. break;
  978. }
  979. }
  980. break;
  981. case D3DXPC_OBJECT :
  982. case D3DXPC_STRUCT :
  983. bufferLayout = NULL;
  984. break;
  985. }
  986. }
  987. break;
  988. case D3DXRS_SAMPLER :
  989. {
  990. AssertFatal( constantDesc.Elements == 1, "Sampler Arrays not yet supported!" );
  991. switch (constantDesc.Type)
  992. {
  993. case D3DXPT_SAMPLER :
  994. case D3DXPT_SAMPLER1D :
  995. case D3DXPT_SAMPLER2D :
  996. case D3DXPT_SAMPLER3D :
  997. // Hi-jack the desc's arraySize to store the registerIndex.
  998. desc.constType = GFXSCT_Sampler;
  999. desc.arraySize = constantDesc.RegisterIndex;
  1000. samplerDescriptions.push_back( desc );
  1001. mShaderConsts.push_back(desc);
  1002. break;
  1003. case D3DXPT_SAMPLERCUBE :
  1004. desc.constType = GFXSCT_SamplerCube;
  1005. desc.arraySize = constantDesc.RegisterIndex;
  1006. samplerDescriptions.push_back( desc );
  1007. mShaderConsts.push_back(desc);
  1008. break;
  1009. }
  1010. }
  1011. break;
  1012. default:
  1013. AssertFatal(false, "Unknown shader constant class enum");
  1014. break;
  1015. }
  1016. if (bufferLayout)
  1017. {
  1018. mShaderConsts.push_back(desc);
  1019. U32 alignBytes = getAlignmentValue(desc.constType);
  1020. U32 paramSize = alignBytes * desc.arraySize;
  1021. bufferLayout->addParameter( desc.name,
  1022. desc.constType,
  1023. constantDesc.RegisterIndex * sizeof(Point4F),
  1024. paramSize,
  1025. desc.arraySize,
  1026. alignBytes );
  1027. }
  1028. }
  1029. else
  1030. AssertFatal(false, "Unable to get shader constant description! (may need more elements of constantDesc");
  1031. }
  1032. }
  1033. const U32 GFXD3D9Shader::smCompiledShaderTag = MakeFourCC('t','c','s','f');
  1034. bool GFXD3D9Shader::_saveCompiledOutput( const Torque::Path &filePath,
  1035. LPD3DXBUFFER buffer,
  1036. GenericConstBufferLayout *bufferLayoutF,
  1037. GenericConstBufferLayout *bufferLayoutI,
  1038. Vector<GFXShaderConstDesc> &samplerDescriptions )
  1039. {
  1040. Torque::Path outputPath(filePath);
  1041. outputPath.setExtension("csf"); // "C"ompiled "S"hader "F"ile (fancy!)
  1042. FileStream f;
  1043. if (!f.open(outputPath, Torque::FS::File::Write))
  1044. return false;
  1045. if (!f.write(smCompiledShaderTag))
  1046. return false;
  1047. // We could reverse engineer the structure in the compiled output, but this
  1048. // is a bit easier because we can just read it into the struct that we want.
  1049. if (!bufferLayoutF->write(&f))
  1050. return false;
  1051. if (!bufferLayoutI->write(&f))
  1052. return false;
  1053. U32 bufferSize = buffer->GetBufferSize();
  1054. if (!f.write(bufferSize))
  1055. return false;
  1056. if (!f.write(bufferSize, buffer->GetBufferPointer()))
  1057. return false;
  1058. // Write out sampler descriptions.
  1059. f.write( samplerDescriptions.size() );
  1060. for ( U32 i = 0; i < samplerDescriptions.size(); i++ )
  1061. {
  1062. f.write( samplerDescriptions[i].name );
  1063. f.write( (U32)(samplerDescriptions[i].constType) );
  1064. f.write( samplerDescriptions[i].arraySize );
  1065. }
  1066. f.close();
  1067. return true;
  1068. }
  1069. bool GFXD3D9Shader::_loadCompiledOutput( const Torque::Path &filePath,
  1070. const String &target,
  1071. GenericConstBufferLayout *bufferLayoutF,
  1072. GenericConstBufferLayout *bufferLayoutI,
  1073. Vector<GFXShaderConstDesc> &samplerDescriptions )
  1074. {
  1075. Torque::Path outputPath(filePath);
  1076. outputPath.setExtension("csf"); // "C"ompiled "S"hader "F"ile (fancy!)
  1077. FileStream f;
  1078. if (!f.open(outputPath, Torque::FS::File::Read))
  1079. return false;
  1080. U32 fileTag;
  1081. if (!f.read(&fileTag))
  1082. return false;
  1083. if (fileTag != smCompiledShaderTag)
  1084. return false;
  1085. if (!bufferLayoutF->read(&f))
  1086. return false;
  1087. if (!bufferLayoutI->read(&f))
  1088. return false;
  1089. U32 bufferSize;
  1090. if (!f.read(&bufferSize))
  1091. return false;
  1092. U32 waterMark = FrameAllocator::getWaterMark();
  1093. DWORD* buffer = static_cast<DWORD*>(FrameAllocator::alloc(bufferSize));
  1094. if (!f.read(bufferSize, buffer))
  1095. return false;
  1096. // Read sampler descriptions.
  1097. U32 samplerCount;
  1098. f.read( &samplerCount );
  1099. for ( U32 i = 0; i < samplerCount; i++ )
  1100. {
  1101. GFXShaderConstDesc samplerDesc;
  1102. f.read( &(samplerDesc.name) );
  1103. f.read( (U32*)&(samplerDesc.constType) );
  1104. f.read( &(samplerDesc.arraySize) );
  1105. samplerDescriptions.push_back( samplerDesc );
  1106. }
  1107. f.close();
  1108. HRESULT res;
  1109. if (target.compare("ps_", 3) == 0)
  1110. res = mD3D9Device->CreatePixelShader(buffer, &mPixShader );
  1111. else
  1112. res = mD3D9Device->CreateVertexShader(buffer, &mVertShader );
  1113. AssertFatal(SUCCEEDED(res), "Unable to load shader!");
  1114. FrameAllocator::setWaterMark(waterMark);
  1115. return SUCCEEDED(res);
  1116. }
  1117. void GFXD3D9Shader::_buildShaderConstantHandles(GenericConstBufferLayout* layout, bool vertexConst)
  1118. {
  1119. for (U32 i = 0; i < layout->getParameterCount(); i++)
  1120. {
  1121. GenericConstBufferLayout::ParamDesc pd;
  1122. layout->getDesc(i, pd);
  1123. GFXD3D9ShaderConstHandle* handle;
  1124. HandleMap::Iterator j = mHandles.find(pd.name);
  1125. if (j != mHandles.end())
  1126. {
  1127. handle = j->value;
  1128. handle->mShader = this;
  1129. handle->setValid( true );
  1130. }
  1131. else
  1132. {
  1133. handle = new GFXD3D9ShaderConstHandle();
  1134. handle->mShader = this;
  1135. mHandles[pd.name] = handle;
  1136. handle->setValid( true );
  1137. }
  1138. if ( vertexConst )
  1139. {
  1140. handle->mVertexConstant = true;
  1141. handle->mVertexHandle = pd;
  1142. }
  1143. else
  1144. {
  1145. handle->mPixelConstant = true;
  1146. handle->mPixelHandle = pd;
  1147. }
  1148. }
  1149. }
  1150. void GFXD3D9Shader::_buildSamplerShaderConstantHandles( Vector<GFXShaderConstDesc> &samplerDescriptions )
  1151. {
  1152. Vector<GFXShaderConstDesc>::iterator iter = samplerDescriptions.begin();
  1153. for ( ; iter != samplerDescriptions.end(); iter++ )
  1154. {
  1155. const GFXShaderConstDesc &desc = *iter;
  1156. AssertFatal( desc.constType == GFXSCT_Sampler ||
  1157. desc.constType == GFXSCT_SamplerCube,
  1158. "GFXD3D9Shader::_buildSamplerShaderConstantHandles - Invalid samplerDescription type!" );
  1159. GFXD3D9ShaderConstHandle *handle;
  1160. HandleMap::Iterator j = mHandles.find(desc.name);
  1161. if ( j != mHandles.end() )
  1162. handle = j->value;
  1163. else
  1164. {
  1165. handle = new GFXD3D9ShaderConstHandle();
  1166. mHandles[desc.name] = handle;
  1167. }
  1168. handle->mShader = this;
  1169. handle->setValid( true );
  1170. handle->mPixelConstant = true;
  1171. handle->mPixelHandle.name = desc.name;
  1172. handle->mPixelHandle.constType = desc.constType;
  1173. handle->mPixelHandle.offset = desc.arraySize;
  1174. }
  1175. }
  1176. void GFXD3D9Shader::_buildInstancingShaderConstantHandles()
  1177. {
  1178. // If we have no instancing than just return
  1179. if (!mInstancingFormat)
  1180. return;
  1181. U32 offset = 0;
  1182. for ( U32 i=0; i < mInstancingFormat->getElementCount(); i++ )
  1183. {
  1184. const GFXVertexElement &element = mInstancingFormat->getElement( i );
  1185. String constName = String::ToString( "$%s", element.getSemantic().c_str() );
  1186. GFXD3D9ShaderConstHandle *handle;
  1187. HandleMap::Iterator j = mHandles.find( constName );
  1188. if ( j != mHandles.end() )
  1189. handle = j->value;
  1190. else
  1191. {
  1192. handle = new GFXD3D9ShaderConstHandle();
  1193. mHandles[ constName ] = handle;
  1194. }
  1195. handle->mShader = this;
  1196. handle->setValid( true );
  1197. handle->mInstancingConstant = true;
  1198. // We shouldn't have an instancing constant that is also
  1199. // a vertex or pixel constant! This means the shader features
  1200. // are confused as to what is instanced.
  1201. //
  1202. AssertFatal( !handle->mVertexConstant &&
  1203. !handle->mPixelConstant,
  1204. "GFXD3D9Shader::_buildInstancingShaderConstantHandles - Bad instanced constant!" );
  1205. // HACK: The GFXD3D9ShaderConstHandle will check mVertexConstant then
  1206. // fall back to reading the mPixelHandle values. We depend on this here
  1207. // and store the data we need in the mPixelHandle constant although its
  1208. // not a pixel shader constant.
  1209. //
  1210. handle->mPixelHandle.name = constName;
  1211. handle->mPixelHandle.offset = offset;
  1212. // If this is a matrix we will have 2 or 3 more of these
  1213. // semantics with the same name after it.
  1214. for ( ; i < mInstancingFormat->getElementCount(); i++ )
  1215. {
  1216. const GFXVertexElement &nextElement = mInstancingFormat->getElement( i );
  1217. if ( nextElement.getSemantic() != element.getSemantic() )
  1218. {
  1219. i--;
  1220. break;
  1221. }
  1222. offset += nextElement.getSizeInBytes();
  1223. }
  1224. }
  1225. }
  1226. GFXShaderConstBufferRef GFXD3D9Shader::allocConstBuffer()
  1227. {
  1228. if (mVertexConstBufferLayoutF && mPixelConstBufferLayoutF)
  1229. {
  1230. GFXD3D9ShaderConstBuffer* buffer = new GFXD3D9ShaderConstBuffer(this, mVertexConstBufferLayoutF, mVertexConstBufferLayoutI, mPixelConstBufferLayoutF, mPixelConstBufferLayoutI);
  1231. mActiveBuffers.push_back( buffer );
  1232. buffer->registerResourceWithDevice(getOwningDevice());
  1233. return buffer;
  1234. } else {
  1235. return NULL;
  1236. }
  1237. }
  1238. /// Returns a shader constant handle for name
  1239. GFXShaderConstHandle* GFXD3D9Shader::getShaderConstHandle(const String& name)
  1240. {
  1241. HandleMap::Iterator i = mHandles.find(name);
  1242. if ( i != mHandles.end() )
  1243. {
  1244. return i->value;
  1245. }
  1246. else
  1247. {
  1248. GFXD3D9ShaderConstHandle *handle = new GFXD3D9ShaderConstHandle();
  1249. handle->setValid( false );
  1250. handle->mShader = this;
  1251. mHandles[name] = handle;
  1252. return handle;
  1253. }
  1254. }
  1255. /// Returns a shader constant handle for name, if the variable doesn't exist NULL is returned.
  1256. GFXShaderConstHandle* GFXD3D9Shader::findShaderConstHandle(const String& name)
  1257. {
  1258. HandleMap::Iterator i = mHandles.find(name);
  1259. if ( i != mHandles.end() )
  1260. {
  1261. return i->value;
  1262. }
  1263. else
  1264. {
  1265. return NULL;
  1266. }
  1267. }
  1268. const Vector<GFXShaderConstDesc>& GFXD3D9Shader::getShaderConstDesc() const
  1269. {
  1270. return mShaderConsts;
  1271. }
  1272. U32 GFXD3D9Shader::getAlignmentValue(const GFXShaderConstType constType) const
  1273. {
  1274. const U32 mRowSizeF = 16;
  1275. const U32 mRowSizeI = 16;
  1276. switch (constType)
  1277. {
  1278. case GFXSCT_Float :
  1279. case GFXSCT_Float2 :
  1280. case GFXSCT_Float3 :
  1281. case GFXSCT_Float4 :
  1282. return mRowSizeF;
  1283. break;
  1284. // Matrices
  1285. case GFXSCT_Float2x2 :
  1286. return mRowSizeF * 2;
  1287. break;
  1288. case GFXSCT_Float3x3 :
  1289. return mRowSizeF * 3;
  1290. break;
  1291. case GFXSCT_Float3x4 :
  1292. return mRowSizeF * 4;
  1293. break;
  1294. case GFXSCT_Float4x4 :
  1295. return mRowSizeF * 4;
  1296. break;
  1297. case GFXSCT_Float4x3 :
  1298. return mRowSizeF * 3;
  1299. break;
  1300. //// Scalar
  1301. case GFXSCT_Int :
  1302. case GFXSCT_Int2 :
  1303. case GFXSCT_Int3 :
  1304. case GFXSCT_Int4 :
  1305. return mRowSizeI;
  1306. break;
  1307. default:
  1308. AssertFatal(false, "Unsupported type!");
  1309. return 0;
  1310. break;
  1311. }
  1312. }
  1313. void GFXD3D9Shader::zombify()
  1314. {
  1315. // Shaders don't need zombification
  1316. }
  1317. void GFXD3D9Shader::resurrect()
  1318. {
  1319. // Shaders are never zombies, and therefore don't have to be brought back.
  1320. }