BsShader.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. #include "BsShader.h"
  2. #include "BsTechnique.h"
  3. #include "BsException.h"
  4. #include "BsDebug.h"
  5. #include "BsShaderRTTI.h"
  6. #include "BsResources.h"
  7. #include "BsFrameAlloc.h"
  8. #include "BsPass.h"
  9. #include "BsSamplerState.h"
  10. namespace BansheeEngine
  11. {
  12. std::atomic<UINT32> ShaderCore::mNextShaderId = 0;
  13. template<bool Core>
  14. TSHADER_DESC<Core>::TSHADER_DESC()
  15. :queuePriority(0), queueSortType(QueueSortType::None), separablePasses(false), flags(0)
  16. {
  17. }
  18. template<bool Core>
  19. void TSHADER_DESC<Core>::addParameter(const String& name, const String& gpuVariableName, GpuParamDataType type,
  20. StringID rendererSemantic, UINT32 arraySize, UINT32 elementSize, UINT8* defaultValue)
  21. {
  22. if(type == GPDT_STRUCT && elementSize <= 0)
  23. BS_EXCEPT(InvalidParametersException, "You need to provide a non-zero element size for a struct parameter.")
  24. SHADER_DATA_PARAM_DESC desc;
  25. desc.name = name;
  26. desc.gpuVariableName = gpuVariableName;
  27. desc.type = type;
  28. desc.arraySize = arraySize;
  29. desc.rendererSemantic = rendererSemantic;
  30. desc.elementSize = elementSize;
  31. dataParams[name] = desc;
  32. if (defaultValue != nullptr)
  33. {
  34. desc.defaultValueIdx = (UINT32)dataDefaultValues.size();
  35. UINT32 defaultValueSize = Shader::getDataParamSize(type);
  36. dataDefaultValues.resize(desc.defaultValueIdx + defaultValueSize);
  37. memcpy(&dataDefaultValues[desc.defaultValueIdx], defaultValue, defaultValueSize);
  38. }
  39. else
  40. desc.defaultValueIdx = (UINT32)-1;
  41. }
  42. template<bool Core>
  43. void TSHADER_DESC<Core>::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, StringID rendererSemantic)
  44. {
  45. UINT32 defaultValueIdx = (UINT32)-1;
  46. addParameterInternal(name, gpuVariableName, type, rendererSemantic, defaultValueIdx);
  47. }
  48. template<bool Core>
  49. void TSHADER_DESC<Core>::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, const SamplerStateType& defaultValue, StringID rendererSemantic)
  50. {
  51. UINT32 defaultValueIdx = (UINT32)-1;
  52. if (Shader::isSampler(type) && defaultValue != nullptr)
  53. {
  54. defaultValueIdx = (UINT32)samplerDefaultValues.size();
  55. samplerDefaultValues.push_back(defaultValue);
  56. }
  57. addParameterInternal(name, gpuVariableName, type, rendererSemantic, defaultValueIdx);
  58. }
  59. template<bool Core>
  60. void TSHADER_DESC<Core>::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, const TextureType& defaultValue, StringID rendererSemantic)
  61. {
  62. UINT32 defaultValueIdx = (UINT32)-1;
  63. if (Shader::isTexture(type) && defaultValue != nullptr)
  64. {
  65. defaultValueIdx = (UINT32)textureDefaultValues.size();
  66. textureDefaultValues.push_back(defaultValue);
  67. }
  68. addParameterInternal(name, gpuVariableName, type, rendererSemantic, defaultValueIdx);
  69. }
  70. template<bool Core>
  71. void TSHADER_DESC<Core>::addParameterInternal(const String& name, const String& gpuVariableName, GpuParamObjectType type, StringID rendererSemantic, UINT32 defaultValueIdx)
  72. {
  73. Map<String, SHADER_OBJECT_PARAM_DESC>* DEST_LOOKUP[] = { &textureParams, &bufferParams, &samplerParams };
  74. UINT32 destIdx = 0;
  75. if (Shader::isBuffer(type))
  76. destIdx = 1;
  77. else if (Shader::isSampler(type))
  78. destIdx = 2;
  79. Map<String, SHADER_OBJECT_PARAM_DESC>& paramsMap = *DEST_LOOKUP[destIdx];
  80. auto iterFind = paramsMap.find(name);
  81. if (iterFind == paramsMap.end())
  82. {
  83. SHADER_OBJECT_PARAM_DESC desc;
  84. desc.name = name;
  85. desc.type = type;
  86. desc.rendererSemantic = rendererSemantic;
  87. desc.gpuVariableNames.push_back(gpuVariableName);
  88. desc.defaultValueIdx = defaultValueIdx;
  89. paramsMap[name] = desc;
  90. }
  91. else
  92. {
  93. SHADER_OBJECT_PARAM_DESC& desc = iterFind->second;
  94. // If same name but different properties, we ignore this param
  95. if (desc.type != type || desc.rendererSemantic != rendererSemantic)
  96. return;
  97. Vector<String>& gpuVariableNames = desc.gpuVariableNames;
  98. bool found = false;
  99. for (UINT32 i = 0; i < (UINT32)gpuVariableNames.size(); i++)
  100. {
  101. if (gpuVariableNames[i] == gpuVariableName)
  102. {
  103. found = true;
  104. break;
  105. }
  106. }
  107. if (!found)
  108. gpuVariableNames.push_back(gpuVariableName);
  109. }
  110. }
  111. template<bool Core>
  112. void TSHADER_DESC<Core>::setParamBlockAttribs(const String& name, bool shared, GpuParamBlockUsage usage, StringID rendererSemantic)
  113. {
  114. SHADER_PARAM_BLOCK_DESC desc;
  115. desc.name = name;
  116. desc.shared = shared;
  117. desc.usage = usage;
  118. desc.rendererSemantic = rendererSemantic;
  119. paramBlocks[name] = desc;
  120. }
  121. template struct TSHADER_DESC<false>;
  122. template struct TSHADER_DESC<true>;
  123. template<bool Core>
  124. TShader<Core>::TShader(const String& name, const TSHADER_DESC<Core>& desc, const Vector<SPtr<TechniqueType>>& techniques, UINT32 id)
  125. :mName(name), mDesc(desc), mTechniques(techniques), mId(id)
  126. { }
  127. template<bool Core>
  128. TShader<Core>::~TShader()
  129. { }
  130. template<bool Core>
  131. GpuParamType TShader<Core>::getParamType(const String& name) const
  132. {
  133. auto findIterData = mDesc.dataParams.find(name);
  134. if (findIterData != mDesc.dataParams.end())
  135. return GPT_DATA;
  136. auto findIterTexture = mDesc.textureParams.find(name);
  137. if (findIterTexture != mDesc.textureParams.end())
  138. return GPT_TEXTURE;
  139. auto findIterBuffer = mDesc.bufferParams.find(name);
  140. if (findIterBuffer != mDesc.bufferParams.end())
  141. return GPT_BUFFER;
  142. auto findIterSampler = mDesc.samplerParams.find(name);
  143. if (findIterSampler != mDesc.samplerParams.end())
  144. return GPT_SAMPLER;
  145. BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
  146. }
  147. template<bool Core>
  148. const SHADER_DATA_PARAM_DESC& TShader<Core>::getDataParamDesc(const String& name) const
  149. {
  150. auto findIterData = mDesc.dataParams.find(name);
  151. if (findIterData != mDesc.dataParams.end())
  152. return findIterData->second;
  153. BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
  154. }
  155. template<bool Core>
  156. const SHADER_OBJECT_PARAM_DESC& TShader<Core>::getTextureParamDesc(const String& name) const
  157. {
  158. auto findIterObject = mDesc.textureParams.find(name);
  159. if (findIterObject != mDesc.textureParams.end())
  160. return findIterObject->second;
  161. BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
  162. }
  163. template<bool Core>
  164. const SHADER_OBJECT_PARAM_DESC& TShader<Core>::getSamplerParamDesc(const String& name) const
  165. {
  166. auto findIterObject = mDesc.samplerParams.find(name);
  167. if (findIterObject != mDesc.samplerParams.end())
  168. return findIterObject->second;
  169. BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
  170. }
  171. template<bool Core>
  172. const SHADER_OBJECT_PARAM_DESC& TShader<Core>::getBufferParamDesc(const String& name) const
  173. {
  174. auto findIterObject = mDesc.bufferParams.find(name);
  175. if (findIterObject != mDesc.bufferParams.end())
  176. return findIterObject->second;
  177. BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
  178. }
  179. template<bool Core>
  180. bool TShader<Core>::hasDataParam(const String& name) const
  181. {
  182. auto findIterData = mDesc.dataParams.find(name);
  183. if (findIterData != mDesc.dataParams.end())
  184. return true;
  185. return false;
  186. }
  187. template<bool Core>
  188. bool TShader<Core>::hasTextureParam(const String& name) const
  189. {
  190. auto findIterObject = mDesc.textureParams.find(name);
  191. if (findIterObject != mDesc.textureParams.end())
  192. return true;
  193. return false;
  194. }
  195. template<bool Core>
  196. bool TShader<Core>::hasSamplerParam(const String& name) const
  197. {
  198. auto findIterObject = mDesc.samplerParams.find(name);
  199. if (findIterObject != mDesc.samplerParams.end())
  200. return true;
  201. return false;
  202. }
  203. template<bool Core>
  204. bool TShader<Core>::hasBufferParam(const String& name) const
  205. {
  206. auto findIterObject = mDesc.bufferParams.find(name);
  207. if (findIterObject != mDesc.bufferParams.end())
  208. return true;
  209. return false;
  210. }
  211. template<bool Core>
  212. typename TShader<Core>::TextureType TShader<Core>::getDefaultTexture(UINT32 index) const
  213. {
  214. if (index < (UINT32)mDesc.textureDefaultValues.size())
  215. return mDesc.textureDefaultValues[index];
  216. return TextureType();
  217. }
  218. template<bool Core>
  219. typename TShader<Core>::SamplerStateType TShader<Core>::getDefaultSampler(UINT32 index) const
  220. {
  221. if (index < (UINT32)mDesc.samplerDefaultValues.size())
  222. return mDesc.samplerDefaultValues[index];
  223. return SamplerStateType();
  224. }
  225. template<bool Core>
  226. UINT8* TShader<Core>::getDefaultValue(UINT32 index) const
  227. {
  228. if (index < (UINT32)mDesc.dataDefaultValues.size())
  229. return (UINT8*)&mDesc.dataDefaultValues[index];
  230. return nullptr;
  231. }
  232. template<bool Core>
  233. SPtr<typename TShader<Core>::TechniqueType> TShader<Core>::getBestTechnique() const
  234. {
  235. for (auto iter = mTechniques.begin(); iter != mTechniques.end(); ++iter)
  236. {
  237. if ((*iter)->isSupported())
  238. {
  239. return *iter;
  240. }
  241. }
  242. return nullptr;
  243. // TODO - Low priority. Instead of returning null use an extremely simple technique that will be supported almost everywhere as a fallback.
  244. }
  245. template class TShader < false > ;
  246. template class TShader < true >;
  247. ShaderCore::ShaderCore(const String& name, const SHADER_DESC_CORE& desc, const Vector<SPtr<TechniqueCore>>& techniques, UINT32 id)
  248. :TShader(name, desc, techniques, id)
  249. {
  250. }
  251. SPtr<ShaderCore> ShaderCore::create(const String& name, const SHADER_DESC_CORE& desc, const Vector<SPtr<TechniqueCore>>& techniques)
  252. {
  253. UINT32 id = mNextShaderId.fetch_add(1, std::memory_order_relaxed);
  254. assert(id < std::numeric_limits<UINT32>::max() && "Created too many shaders, reached maximum id.");
  255. ShaderCore* shaderCore = new (bs_alloc<ShaderCore>()) ShaderCore(name, desc, techniques, id);
  256. SPtr<ShaderCore> shaderCorePtr = bs_shared_ptr<ShaderCore>(shaderCore);
  257. shaderCorePtr->_setThisPtr(shaderCorePtr);
  258. shaderCorePtr->initialize();
  259. return shaderCorePtr;
  260. }
  261. Shader::Shader(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques, UINT32 id)
  262. :TShader(name, desc, techniques, id)
  263. {
  264. mMetaData = bs_shared_ptr_new<ShaderMetaData>();
  265. }
  266. SPtr<ShaderCore> Shader::getCore() const
  267. {
  268. return std::static_pointer_cast<ShaderCore>(mCoreSpecific);
  269. }
  270. void Shader::setIncludeFiles(const Vector<String>& includes)
  271. {
  272. SPtr<ShaderMetaData> meta = std::static_pointer_cast<ShaderMetaData>(getMetaData());
  273. meta->includes = includes;
  274. }
  275. SPtr<CoreObjectCore> Shader::createCore() const
  276. {
  277. Vector<SPtr<TechniqueCore>> techniques;
  278. for (auto& technique : mTechniques)
  279. techniques.push_back(technique->getCore());
  280. ShaderCore* shaderCore = new (bs_alloc<ShaderCore>()) ShaderCore(mName, convertDesc(mDesc), techniques, mId);
  281. SPtr<ShaderCore> shaderCorePtr = bs_shared_ptr<ShaderCore>(shaderCore);
  282. shaderCorePtr->_setThisPtr(shaderCorePtr);
  283. return shaderCorePtr;
  284. }
  285. SHADER_DESC_CORE Shader::convertDesc(const SHADER_DESC& desc) const
  286. {
  287. SHADER_DESC_CORE output;
  288. output.dataParams = desc.dataParams;
  289. output.textureParams = desc.textureParams;
  290. output.samplerParams = desc.samplerParams;
  291. output.bufferParams = desc.bufferParams;
  292. output.paramBlocks = desc.paramBlocks;
  293. output.queuePriority = desc.queuePriority;
  294. output.queueSortType = desc.queueSortType;
  295. output.separablePasses = desc.separablePasses;
  296. // Ignoring default values as they are not needed for syncing since
  297. // they're initialized through the material.
  298. return output;
  299. }
  300. void Shader::getCoreDependencies(FrameVector<SPtr<CoreObject>>& dependencies)
  301. {
  302. for (auto& technique : mTechniques)
  303. dependencies.push_back(technique);
  304. }
  305. bool Shader::isSampler(GpuParamObjectType type)
  306. {
  307. switch(type)
  308. {
  309. case GPOT_SAMPLER1D:
  310. case GPOT_SAMPLER2D:
  311. case GPOT_SAMPLER3D:
  312. case GPOT_SAMPLERCUBE:
  313. case GPOT_SAMPLER2DMS:
  314. return true;
  315. }
  316. return false;
  317. }
  318. bool Shader::isTexture(GpuParamObjectType type)
  319. {
  320. switch(type)
  321. {
  322. case GPOT_TEXTURE1D:
  323. case GPOT_TEXTURE2D:
  324. case GPOT_TEXTURE3D:
  325. case GPOT_TEXTURECUBE:
  326. case GPOT_TEXTURE2DMS:
  327. return true;
  328. }
  329. return false;
  330. }
  331. bool Shader::isBuffer(GpuParamObjectType type)
  332. {
  333. switch(type)
  334. {
  335. case GPOT_BYTE_BUFFER:
  336. case GPOT_STRUCTURED_BUFFER:
  337. case GPOT_RWBYTE_BUFFER:
  338. case GPOT_RWAPPEND_BUFFER:
  339. case GPOT_RWCONSUME_BUFFER:
  340. case GPOT_RWSTRUCTURED_BUFFER:
  341. case GPOT_RWSTRUCTURED_BUFFER_WITH_COUNTER:
  342. case GPOT_RWTYPED_BUFFER:
  343. return true;
  344. }
  345. return false;
  346. }
  347. struct ShaderDataParamsSizes
  348. {
  349. ShaderDataParamsSizes()
  350. {
  351. memset(LOOKUP, 0, sizeof(LOOKUP));
  352. LOOKUP[(UINT32)GPDT_FLOAT1] = 4;
  353. LOOKUP[(UINT32)GPDT_FLOAT2] = 8;
  354. LOOKUP[(UINT32)GPDT_FLOAT3] = 12;
  355. LOOKUP[(UINT32)GPDT_FLOAT4] = 16;
  356. LOOKUP[(UINT32)GPDT_MATRIX_2X2] = 16;
  357. LOOKUP[(UINT32)GPDT_MATRIX_2X3] = 24;
  358. LOOKUP[(UINT32)GPDT_MATRIX_2X4] = 32;
  359. LOOKUP[(UINT32)GPDT_MATRIX_3X2] = 24;
  360. LOOKUP[(UINT32)GPDT_MATRIX_3X3] = 36;
  361. LOOKUP[(UINT32)GPDT_MATRIX_3X4] = 52;
  362. LOOKUP[(UINT32)GPDT_MATRIX_4X2] = 32;
  363. LOOKUP[(UINT32)GPDT_MATRIX_4X3 ] = 52;
  364. LOOKUP[(UINT32)GPDT_MATRIX_4X4] = 64;
  365. LOOKUP[(UINT32)GPDT_INT1] = 4;
  366. LOOKUP[(UINT32)GPDT_INT2] = 8;
  367. LOOKUP[(UINT32)GPDT_INT3] = 12;
  368. LOOKUP[(UINT32)GPDT_INT4] = 16;
  369. LOOKUP[(UINT32)GPDT_BOOL] = 1;
  370. }
  371. static const UINT32 NUM_DATA_PARAMS = 25;
  372. UINT32 LOOKUP[NUM_DATA_PARAMS];
  373. };
  374. UINT32 Shader::getDataParamSize(GpuParamDataType type)
  375. {
  376. static const ShaderDataParamsSizes PARAM_SIZES;
  377. UINT32 idx = (UINT32)type;
  378. if (idx < sizeof(PARAM_SIZES.LOOKUP))
  379. return PARAM_SIZES.LOOKUP[idx];
  380. return 0;
  381. }
  382. HShader Shader::create(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques)
  383. {
  384. ShaderPtr newShader = _createPtr(name, desc, techniques);
  385. return static_resource_cast<Shader>(gResources()._createResourceHandle(newShader));
  386. }
  387. ShaderPtr Shader::_createPtr(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques)
  388. {
  389. UINT32 id = ShaderCore::mNextShaderId.fetch_add(1, std::memory_order_relaxed);
  390. assert(id < std::numeric_limits<UINT32>::max() && "Created too many shaders, reached maximum id.");
  391. ShaderPtr newShader = bs_core_ptr<Shader>(new (bs_alloc<Shader>()) Shader(name, desc, techniques, id));
  392. newShader->_setThisPtr(newShader);
  393. newShader->initialize();
  394. return newShader;
  395. }
  396. ShaderPtr Shader::createEmpty()
  397. {
  398. ShaderPtr newShader = bs_core_ptr<Shader>(new (bs_alloc<Shader>()) Shader());
  399. newShader->_setThisPtr(newShader);
  400. return newShader;
  401. }
  402. RTTITypeBase* Shader::getRTTIStatic()
  403. {
  404. return ShaderRTTI::instance();
  405. }
  406. RTTITypeBase* Shader::getRTTI() const
  407. {
  408. return Shader::getRTTIStatic();
  409. }
  410. RTTITypeBase* ShaderMetaData::getRTTIStatic()
  411. {
  412. return ShaderMetaDataRTTI::instance();
  413. }
  414. RTTITypeBase* ShaderMetaData::getRTTI() const
  415. {
  416. return ShaderMetaData::getRTTIStatic();
  417. }
  418. }