gfxD3D11Shader.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2015 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. #ifndef _GFXD3D11SHADER_H_
  23. #define _GFXD3D11SHADER_H_
  24. #include <d3dcompiler.h>
  25. #include "core/util/path.h"
  26. #include "core/util/tDictionary.h"
  27. #include "gfx/gfxShader.h"
  28. #include "gfx/gfxResource.h"
  29. #include "gfx/genericConstBuffer.h"
  30. #include "gfx/D3D11/gfxD3D11Device.h"
  31. class GFXD3D11Shader;
  32. enum CONST_CLASS
  33. {
  34. D3DPC_SCALAR,
  35. D3DPC_VECTOR,
  36. D3DPC_MATRIX_ROWS,
  37. D3DPC_MATRIX_COLUMNS,
  38. D3DPC_OBJECT,
  39. D3DPC_STRUCT
  40. };
  41. enum CONST_TYPE
  42. {
  43. D3DPT_VOID,
  44. D3DPT_BOOL,
  45. D3DPT_INT,
  46. D3DPT_FLOAT,
  47. D3DPT_STRING,
  48. D3DPT_TEXTURE,
  49. D3DPT_TEXTURE1D,
  50. D3DPT_TEXTURE2D,
  51. D3DPT_TEXTURE3D,
  52. D3DPT_TEXTURECUBE,
  53. D3DPT_SAMPLER,
  54. D3DPT_SAMPLER1D,
  55. D3DPT_SAMPLER2D,
  56. D3DPT_SAMPLER3D,
  57. D3DPT_SAMPLERCUBE,
  58. D3DPT_PIXELSHADER,
  59. D3DPT_VERTEXSHADER,
  60. D3DPT_PIXELFRAGMENT,
  61. D3DPT_VERTEXFRAGMENT
  62. };
  63. enum REGISTER_TYPE
  64. {
  65. D3DRS_BOOL,
  66. D3DRS_INT4,
  67. D3DRS_FLOAT4,
  68. D3DRS_SAMPLER
  69. };
  70. struct ConstantDesc
  71. {
  72. String Name = String::EmptyString;
  73. S32 RegisterIndex = 0;
  74. S32 RegisterCount = 0;
  75. S32 Rows = 0;
  76. S32 Columns = 0;
  77. S32 Elements = 0;
  78. S32 StructMembers = 0;
  79. REGISTER_TYPE RegisterSet = D3DRS_FLOAT4;
  80. CONST_CLASS Class = D3DPC_SCALAR;
  81. CONST_TYPE Type = D3DPT_FLOAT;
  82. U32 Bytes = 0;
  83. };
  84. class ConstantTable
  85. {
  86. public:
  87. bool Create(const void* data);
  88. U32 GetConstantCount() const { return m_constants.size(); }
  89. const String& GetCreator() const { return m_creator; }
  90. const ConstantDesc* GetConstantByIndex(U32 i) const { return &m_constants[i]; }
  91. const ConstantDesc* GetConstantByName(const String& name) const;
  92. void ClearConstants() { m_constants.clear(); }
  93. private:
  94. Vector<ConstantDesc> m_constants;
  95. String m_creator;
  96. };
  97. // Structs
  98. struct CTHeader
  99. {
  100. U32 Size;
  101. U32 Creator;
  102. U32 Version;
  103. U32 Constants;
  104. U32 ConstantInfo;
  105. U32 Flags;
  106. U32 Target;
  107. };
  108. struct CTInfo
  109. {
  110. U32 Name;
  111. U16 RegisterSet;
  112. U16 RegisterIndex;
  113. U16 RegisterCount;
  114. U16 Reserved;
  115. U32 TypeInfo;
  116. U32 DefaultValue;
  117. };
  118. struct CTType
  119. {
  120. U16 Class;
  121. U16 Type;
  122. U16 Rows;
  123. U16 Columns;
  124. U16 Elements;
  125. U16 StructMembers;
  126. U32 StructMemberInfo;
  127. };
  128. // Shader instruction opcodes
  129. const U32 SIO_COMMENT = 0x0000FFFE;
  130. const U32 SIO_END = 0x0000FFFF;
  131. const U32 SI_OPCODE_MASK = 0x0000FFFF;
  132. const U32 SI_COMMENTSIZE_MASK = 0x7FFF0000;
  133. const U32 CTAB_CONSTANT = 0x42415443;
  134. // Member functions
  135. inline bool ConstantTable::Create(const void* data)
  136. {
  137. const U32* ptr = static_cast<const U32*>(data);
  138. while(*++ptr != SIO_END)
  139. {
  140. if((*ptr & SI_OPCODE_MASK) == SIO_COMMENT)
  141. {
  142. // Check for CTAB comment
  143. U32 comment_size = (*ptr & SI_COMMENTSIZE_MASK) >> 16;
  144. if(*(ptr+1) != CTAB_CONSTANT)
  145. {
  146. ptr += comment_size;
  147. continue;
  148. }
  149. // Read header
  150. const char* ctab = reinterpret_cast<const char*>(ptr+2);
  151. size_t ctab_size = (comment_size-1)*4;
  152. const CTHeader* header = reinterpret_cast<const CTHeader*>(ctab);
  153. if(ctab_size < sizeof(*header) || header->Size != sizeof(*header))
  154. return false;
  155. m_creator = ctab + header->Creator;
  156. // Read constants
  157. m_constants.reserve(header->Constants);
  158. const CTInfo* info = reinterpret_cast<const CTInfo*>(ctab + header->ConstantInfo);
  159. for(U32 i = 0; i < header->Constants; ++i)
  160. {
  161. const CTType* type = reinterpret_cast<const CTType*>(ctab + info[i].TypeInfo);
  162. // Fill struct
  163. ConstantDesc desc;
  164. desc.Name = ctab + info[i].Name;
  165. desc.RegisterSet = static_cast<REGISTER_TYPE>(info[i].RegisterSet);
  166. desc.RegisterIndex = info[i].RegisterIndex;
  167. desc.RegisterCount = info[i].RegisterCount;
  168. desc.Rows = type->Rows;
  169. desc.Class = static_cast<CONST_CLASS>(type->Class);
  170. desc.Type = static_cast<CONST_TYPE>(type->Type);
  171. desc.Columns = type->Columns;
  172. desc.Elements = type->Elements;
  173. desc.StructMembers = type->StructMembers;
  174. desc.Bytes = 4 * desc.Elements * desc.Rows * desc.Columns;
  175. m_constants.push_back(desc);
  176. }
  177. return true;
  178. }
  179. }
  180. return false;
  181. }
  182. inline const ConstantDesc* ConstantTable::GetConstantByName(const String& name) const
  183. {
  184. Vector<ConstantDesc>::const_iterator it;
  185. for(it = m_constants.begin(); it != m_constants.end(); ++it)
  186. {
  187. if(it->Name == name)
  188. return &(*it);
  189. }
  190. return NULL;
  191. }
  192. /////////////////// Constant Buffers /////////////////////////////
  193. // Maximum number of CBuffers ($Globals & $Params)
  194. const U32 CBUFFER_MAX = 2;
  195. struct ConstSubBufferDesc
  196. {
  197. U32 start;
  198. U32 size;
  199. ConstSubBufferDesc() : start(0), size(0){}
  200. };
  201. class GFXD3D11ConstBufferLayout : public GenericConstBufferLayout
  202. {
  203. public:
  204. GFXD3D11ConstBufferLayout();
  205. /// Get our constant sub buffer data
  206. Vector<ConstSubBufferDesc> &getSubBufferDesc(){ return mSubBuffers; }
  207. /// We need to manually set the size due to D3D11 alignment
  208. void setSize(U32 size){ mBufferSize = size;}
  209. /// Set a parameter, given a base pointer
  210. virtual bool set(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
  211. protected:
  212. /// Set a matrix, given a base pointer
  213. virtual bool setMatrix(const ParamDesc& pd, const GFXShaderConstType constType, const U32 size, const void* data, U8* basePointer);
  214. Vector<ConstSubBufferDesc> mSubBuffers;
  215. };
  216. class GFXD3D11ShaderConstHandle : public GFXShaderConstHandle
  217. {
  218. public:
  219. // GFXShaderConstHandle
  220. const String& getName() const;
  221. GFXShaderConstType getType() const;
  222. U32 getArraySize() const;
  223. WeakRefPtr<GFXD3D11Shader> mShader;
  224. bool mVertexConstant;
  225. GenericConstBufferLayout::ParamDesc mVertexHandle;
  226. bool mPixelConstant;
  227. GenericConstBufferLayout::ParamDesc mPixelHandle;
  228. /// Is true if this constant is for hardware mesh instancing.
  229. ///
  230. /// Note: We currently store its settings in mPixelHandle.
  231. ///
  232. bool mInstancingConstant;
  233. void setValid( bool valid ) { mValid = valid; }
  234. S32 getSamplerRegister() const;
  235. // Returns true if this is a handle to a sampler register.
  236. bool isSampler() const
  237. {
  238. return ( mPixelConstant && mPixelHandle.constType >= GFXSCT_Sampler ) || ( mVertexConstant && mVertexHandle.constType >= GFXSCT_Sampler );
  239. }
  240. /// Restore to uninitialized state.
  241. void clear()
  242. {
  243. mShader = NULL;
  244. mVertexConstant = false;
  245. mPixelConstant = false;
  246. mInstancingConstant = false;
  247. mVertexHandle.clear();
  248. mPixelHandle.clear();
  249. mValid = false;
  250. }
  251. GFXD3D11ShaderConstHandle();
  252. };
  253. /// The D3D11 implementation of a shader constant buffer.
  254. class GFXD3D11ShaderConstBuffer : public GFXShaderConstBuffer
  255. {
  256. friend class GFXD3D11Shader;
  257. // Cache device context
  258. ID3D11DeviceContext* mDeviceContext;
  259. public:
  260. GFXD3D11ShaderConstBuffer(GFXD3D11Shader* shader,
  261. GFXD3D11ConstBufferLayout* vertexLayout,
  262. GFXD3D11ConstBufferLayout* pixelLayout);
  263. virtual ~GFXD3D11ShaderConstBuffer();
  264. /// Called by GFXD3D11Device to activate this buffer.
  265. /// @param mPrevShaderBuffer The previously active buffer
  266. void activate(GFXD3D11ShaderConstBuffer *prevShaderBuffer);
  267. /// Used internally by GXD3D11ShaderConstBuffer to determine if it's dirty.
  268. bool isDirty();
  269. /// Called from GFXD3D11Shader when constants have changed and need
  270. /// to be the shader this buffer references is reloaded.
  271. void onShaderReload(GFXD3D11Shader *shader);
  272. // GFXShaderConstBuffer
  273. virtual GFXShader* getShader();
  274. virtual void set(GFXShaderConstHandle* handle, const F32 fv);
  275. virtual void set(GFXShaderConstHandle* handle, const Point2F& fv);
  276. virtual void set(GFXShaderConstHandle* handle, const Point3F& fv);
  277. virtual void set(GFXShaderConstHandle* handle, const Point4F& fv);
  278. virtual void set(GFXShaderConstHandle* handle, const PlaneF& fv);
  279. virtual void set(GFXShaderConstHandle* handle, const LinearColorF& fv);
  280. virtual void set(GFXShaderConstHandle* handle, const S32 f);
  281. virtual void set(GFXShaderConstHandle* handle, const Point2I& fv);
  282. virtual void set(GFXShaderConstHandle* handle, const Point3I& fv);
  283. virtual void set(GFXShaderConstHandle* handle, const Point4I& fv);
  284. virtual void set(GFXShaderConstHandle* handle, const AlignedArray<F32>& fv);
  285. virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point2F>& fv);
  286. virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point3F>& fv);
  287. virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point4F>& fv);
  288. virtual void set(GFXShaderConstHandle* handle, const AlignedArray<S32>& fv);
  289. virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point2I>& fv);
  290. virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point3I>& fv);
  291. virtual void set(GFXShaderConstHandle* handle, const AlignedArray<Point4I>& fv);
  292. virtual void set(GFXShaderConstHandle* handle, const MatrixF& mat, const GFXShaderConstType matType = GFXSCT_Float4x4);
  293. virtual void set(GFXShaderConstHandle* handle, const MatrixF* mat, const U32 arraySize, const GFXShaderConstType matrixType = GFXSCT_Float4x4);
  294. // GFXResource
  295. virtual const String describeSelf() const;
  296. virtual void zombify();
  297. virtual void resurrect();
  298. protected:
  299. void _createBuffers();
  300. template<class T>
  301. inline void SET_CONSTANT(GFXShaderConstHandle* handle,
  302. const T& fv,
  303. GenericConstBuffer *vBuffer,
  304. GenericConstBuffer *pBuffer);
  305. // Constant buffers, VSSetConstantBuffers1 has issues on win 7. So unfortunately for now we have multiple constant buffers
  306. ID3D11Buffer* mConstantBuffersV[CBUFFER_MAX];
  307. ID3D11Buffer* mConstantBuffersP[CBUFFER_MAX];
  308. /// We keep a weak reference to the shader
  309. /// because it will often be deleted.
  310. WeakRefPtr<GFXD3D11Shader> mShader;
  311. //vertex
  312. GFXD3D11ConstBufferLayout* mVertexConstBufferLayout;
  313. GenericConstBuffer* mVertexConstBuffer;
  314. //pixel
  315. GFXD3D11ConstBufferLayout* mPixelConstBufferLayout;
  316. GenericConstBuffer* mPixelConstBuffer;
  317. };
  318. class gfxD3D11Include;
  319. typedef StrongRefPtr<gfxD3D11Include> gfxD3DIncludeRef;
  320. /////////////////// GFXShader implementation /////////////////////////////
  321. class GFXD3D11Shader : public GFXShader
  322. {
  323. friend class GFXD3D11Device;
  324. friend class GFXD3D11ShaderConstBuffer;
  325. public:
  326. typedef Map<String, GFXD3D11ShaderConstHandle*> HandleMap;
  327. GFXD3D11Shader();
  328. virtual ~GFXD3D11Shader();
  329. // GFXShader
  330. virtual GFXShaderConstBufferRef allocConstBuffer();
  331. virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const;
  332. virtual GFXShaderConstHandle* getShaderConstHandle(const String& name);
  333. virtual GFXShaderConstHandle* findShaderConstHandle(const String& name);
  334. virtual U32 getAlignmentValue(const GFXShaderConstType constType) const;
  335. virtual bool getDisassembly( String &outStr ) const;
  336. // GFXResource
  337. virtual void zombify();
  338. virtual void resurrect();
  339. protected:
  340. virtual bool _init();
  341. static const U32 smCompiledShaderTag;
  342. ConstantTable table;
  343. ID3D11VertexShader *mVertShader;
  344. ID3D11PixelShader *mPixShader;
  345. GFXD3D11ConstBufferLayout* mVertexConstBufferLayout;
  346. GFXD3D11ConstBufferLayout* mPixelConstBufferLayout;
  347. static gfxD3DIncludeRef smD3DInclude;
  348. HandleMap mHandles;
  349. /// The shader disassembly from DX when this shader is compiled.
  350. /// We only store this data in non-release builds.
  351. String mDissasembly;
  352. /// Vector of sampler type descriptions consolidated from _compileShader.
  353. Vector<GFXShaderConstDesc> mSamplerDescriptions;
  354. /// Vector of descriptions (consolidated for the getShaderConstDesc call)
  355. Vector<GFXShaderConstDesc> mShaderConsts;
  356. // These two functions are used when compiling shaders from hlsl
  357. virtual bool _compileShader( const Torque::Path &filePath,
  358. const String &target,
  359. const D3D_SHADER_MACRO *defines,
  360. GenericConstBufferLayout *bufferLayout,
  361. Vector<GFXShaderConstDesc> &samplerDescriptions );
  362. void _getShaderConstants( ID3D11ShaderReflection* refTable,
  363. GenericConstBufferLayout *bufferLayout,
  364. Vector<GFXShaderConstDesc> &samplerDescriptions );
  365. bool _convertShaderVariable(const D3D11_SHADER_TYPE_DESC &typeDesc, GFXShaderConstDesc &desc);
  366. bool _saveCompiledOutput( const Torque::Path &filePath,
  367. ID3DBlob *buffer,
  368. GenericConstBufferLayout *bufferLayout,
  369. Vector<GFXShaderConstDesc> &samplerDescriptions );
  370. // Loads precompiled shaders
  371. bool _loadCompiledOutput( const Torque::Path &filePath,
  372. const String &target,
  373. GenericConstBufferLayout *bufferLayoutF,
  374. Vector<GFXShaderConstDesc> &samplerDescriptions );
  375. // This is used in both cases
  376. virtual void _buildShaderConstantHandles(GenericConstBufferLayout *layout, bool vertexConst);
  377. virtual void _buildSamplerShaderConstantHandles( Vector<GFXShaderConstDesc> &samplerDescriptions );
  378. /// Used to build the instancing shader constants from
  379. /// the instancing vertex format.
  380. void _buildInstancingShaderConstantHandles();
  381. };
  382. inline bool GFXD3D11Shader::getDisassembly(String &outStr) const
  383. {
  384. outStr = mDissasembly;
  385. return (outStr.isNotEmpty());
  386. }
  387. #endif