BsShader.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. namespace BansheeEngine
  10. {
  11. SHADER_DESC::SHADER_DESC()
  12. :queuePriority(0), queueSortType(QueueSortType::None), separablePasses(false)
  13. {
  14. }
  15. void SHADER_DESC::addParameter(const String& name, const String& gpuVariableName, GpuParamDataType type, UINT32 rendererSemantic, UINT32 arraySize, UINT32 elementSize)
  16. {
  17. if(type == GPDT_STRUCT && elementSize <= 0)
  18. BS_EXCEPT(InvalidParametersException, "You need to provide a non-zero element size for a struct parameter.")
  19. SHADER_DATA_PARAM_DESC desc;
  20. desc.name = name;
  21. desc.gpuVariableName = gpuVariableName;
  22. desc.type = type;
  23. desc.arraySize = arraySize;
  24. desc.rendererSemantic = rendererSemantic;
  25. desc.elementSize = elementSize;
  26. dataParams[name] = desc;
  27. objectParams.erase(name);
  28. }
  29. void SHADER_DESC::addParameter(const String& name, const String& gpuVariableName, GpuParamObjectType type, UINT32 rendererSemantic)
  30. {
  31. auto iterFind = objectParams.find(name);
  32. if (iterFind == objectParams.end())
  33. {
  34. SHADER_OBJECT_PARAM_DESC desc;
  35. desc.name = name;
  36. desc.type = type;
  37. desc.rendererSemantic = rendererSemantic;
  38. desc.gpuVariableNames.push_back(gpuVariableName);
  39. objectParams[name] = desc;
  40. }
  41. else
  42. {
  43. SHADER_OBJECT_PARAM_DESC& desc = iterFind->second;
  44. if (desc.type != type || desc.rendererSemantic != rendererSemantic)
  45. BS_EXCEPT(InvalidParametersException, "Shader parameter with the name \"" + name + "\" already exists with different properties.");
  46. Vector<String>& gpuVariableNames = desc.gpuVariableNames;
  47. bool found = false;
  48. for (UINT32 i = 0; i < (UINT32)gpuVariableNames.size(); i++)
  49. {
  50. if (gpuVariableNames[i] == gpuVariableName)
  51. {
  52. found = true;
  53. break;
  54. }
  55. }
  56. if (!found)
  57. gpuVariableNames.push_back(gpuVariableName);
  58. }
  59. dataParams.erase(name);
  60. }
  61. void SHADER_DESC::setParamBlockAttribs(const String& name, bool shared, GpuParamBlockUsage usage, UINT32 rendererSemantic)
  62. {
  63. SHADER_PARAM_BLOCK_DESC desc;
  64. desc.name = name;
  65. desc.shared = shared;
  66. desc.usage = usage;
  67. desc.rendererSemantic = rendererSemantic;
  68. paramBlocks[name] = desc;
  69. }
  70. ShaderBase::ShaderBase(const String& name, const SHADER_DESC& desc)
  71. :mName(name), mDesc(desc)
  72. {
  73. }
  74. GpuParamType ShaderBase::getParamType(const String& name) const
  75. {
  76. auto findIterData = mDesc.dataParams.find(name);
  77. if (findIterData != mDesc.dataParams.end())
  78. return GPT_DATA;
  79. auto findIterObject = mDesc.objectParams.find(name);
  80. if (findIterObject != mDesc.objectParams.end())
  81. return GPT_OBJECT;
  82. BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
  83. }
  84. const SHADER_DATA_PARAM_DESC& ShaderBase::getDataParamDesc(const String& name) const
  85. {
  86. auto findIterData = mDesc.dataParams.find(name);
  87. if (findIterData != mDesc.dataParams.end())
  88. return findIterData->second;
  89. BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
  90. }
  91. const SHADER_OBJECT_PARAM_DESC& ShaderBase::getObjectParamDesc(const String& name) const
  92. {
  93. auto findIterObject = mDesc.objectParams.find(name);
  94. if (findIterObject != mDesc.objectParams.end())
  95. return findIterObject->second;
  96. BS_EXCEPT(InternalErrorException, "Cannot find the parameter with the name: " + name);
  97. }
  98. bool ShaderBase::hasDataParam(const String& name) const
  99. {
  100. auto findIterData = mDesc.dataParams.find(name);
  101. if (findIterData != mDesc.dataParams.end())
  102. return true;
  103. return false;
  104. }
  105. bool ShaderBase::hasObjectParam(const String& name) const
  106. {
  107. auto findIterObject = mDesc.objectParams.find(name);
  108. if (findIterObject != mDesc.objectParams.end())
  109. return true;
  110. return false;
  111. }
  112. template<bool Core>
  113. TShader<Core>::TShader(const String& name, const SHADER_DESC& desc, const Vector<SPtr<TechniqueType>>& techniques)
  114. :ShaderBase(name, desc), mTechniques(techniques)
  115. { }
  116. template<bool Core>
  117. TShader<Core>::~TShader()
  118. { }
  119. template<bool Core>
  120. SPtr<typename TShader<Core>::TechniqueType> TShader<Core>::getBestTechnique() const
  121. {
  122. for (auto iter = mTechniques.begin(); iter != mTechniques.end(); ++iter)
  123. {
  124. if ((*iter)->isSupported())
  125. {
  126. return *iter;
  127. }
  128. }
  129. return nullptr;
  130. // TODO - Low priority. Instead of returning null use an extremely simple technique that will be supported almost everywhere as a fallback.
  131. }
  132. template class TShader < false > ;
  133. template class TShader < true >;
  134. ShaderCore::ShaderCore(const String& name, const SHADER_DESC& desc, const Vector<SPtr<TechniqueCore>>& techniques)
  135. :TShader(name, desc, techniques)
  136. {
  137. }
  138. SPtr<ShaderCore> ShaderCore::create(const String& name, const SHADER_DESC& desc, const Vector<SPtr<TechniqueCore>>& techniques)
  139. {
  140. ShaderCore* shaderCore = new (bs_alloc<ShaderCore>()) ShaderCore(name, desc, techniques);
  141. SPtr<ShaderCore> shaderCorePtr = bs_shared_ptr<ShaderCore, GenAlloc>(shaderCore);
  142. shaderCorePtr->_setThisPtr(shaderCorePtr);
  143. shaderCorePtr->initialize();
  144. return shaderCorePtr;
  145. }
  146. Shader::Shader(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques)
  147. :TShader(name, desc, techniques)
  148. {
  149. }
  150. SPtr<ShaderCore> Shader::getCore() const
  151. {
  152. return std::static_pointer_cast<ShaderCore>(mCoreSpecific);
  153. }
  154. SPtr<CoreObjectCore> Shader::createCore() const
  155. {
  156. Vector<SPtr<TechniqueCore>> techniques;
  157. for (auto& technique : mTechniques)
  158. techniques.push_back(technique->getCore());
  159. ShaderCore* shaderCore = new (bs_alloc<ShaderCore>()) ShaderCore(mName, mDesc, techniques);
  160. SPtr<ShaderCore> shaderCorePtr = bs_shared_ptr<ShaderCore, GenAlloc>(shaderCore);
  161. shaderCorePtr->_setThisPtr(shaderCorePtr);
  162. return shaderCorePtr;
  163. }
  164. void Shader::getResourceDependencies(Vector<HResource>& dependencies) const
  165. {
  166. TechniquePtr bestTechnique = getBestTechnique();
  167. if (bestTechnique == nullptr) // No valid technique
  168. return;
  169. UINT32 numPasses = bestTechnique->getNumPasses();
  170. for (UINT32 i = 0; i < numPasses; i++)
  171. {
  172. PassPtr pass = bestTechnique->getPass(i);
  173. HGpuProgram vertProg = pass->getVertexProgram();
  174. if (vertProg != nullptr)
  175. dependencies.push_back(vertProg);
  176. HGpuProgram fragProg = pass->getFragmentProgram();
  177. if (fragProg != nullptr)
  178. dependencies.push_back(fragProg);
  179. HGpuProgram geomProg = pass->getGeometryProgram();
  180. if (geomProg != nullptr)
  181. dependencies.push_back(geomProg);
  182. HGpuProgram domProg = pass->getDomainProgram();
  183. if (domProg != nullptr)
  184. dependencies.push_back(domProg);
  185. HGpuProgram hullProg = pass->getHullProgram();
  186. if (hullProg != nullptr)
  187. dependencies.push_back(hullProg);
  188. HGpuProgram computeProg = pass->getComputeProgram();
  189. if (computeProg != nullptr)
  190. dependencies.push_back(computeProg);
  191. HBlendState blendState = pass->getBlendState();
  192. if (blendState != nullptr)
  193. dependencies.push_back(blendState);
  194. HRasterizerState rasterizerState = pass->getRasterizerState();
  195. if (rasterizerState != nullptr)
  196. dependencies.push_back(rasterizerState);
  197. HDepthStencilState depthStencilState = pass->getDepthStencilState();
  198. if (depthStencilState != nullptr)
  199. dependencies.push_back(depthStencilState);
  200. }
  201. }
  202. void Shader::getCoreDependencies(Vector<SPtr<CoreObject>>& dependencies)
  203. {
  204. for (auto& technique : mTechniques)
  205. dependencies.push_back(technique);
  206. }
  207. bool Shader::isSampler(GpuParamObjectType type)
  208. {
  209. switch(type)
  210. {
  211. case GPOT_SAMPLER1D:
  212. case GPOT_SAMPLER2D:
  213. case GPOT_SAMPLER3D:
  214. case GPOT_SAMPLERCUBE:
  215. case GPOT_SAMPLER2DMS:
  216. return true;
  217. }
  218. return false;
  219. }
  220. bool Shader::isTexture(GpuParamObjectType type)
  221. {
  222. switch(type)
  223. {
  224. case GPOT_TEXTURE1D:
  225. case GPOT_TEXTURE2D:
  226. case GPOT_TEXTURE3D:
  227. case GPOT_TEXTURECUBE:
  228. case GPOT_TEXTURE2DMS:
  229. return true;
  230. }
  231. return false;
  232. }
  233. bool Shader::isBuffer(GpuParamObjectType type)
  234. {
  235. switch(type)
  236. {
  237. case GPOT_BYTE_BUFFER:
  238. case GPOT_STRUCTURED_BUFFER:
  239. case GPOT_RWBYTE_BUFFER:
  240. case GPOT_RWAPPEND_BUFFER:
  241. case GPOT_RWCONSUME_BUFFER:
  242. case GPOT_RWSTRUCTURED_BUFFER:
  243. case GPOT_RWSTRUCTURED_BUFFER_WITH_COUNTER:
  244. case GPOT_RWTYPED_BUFFER:
  245. return true;
  246. }
  247. return false;
  248. }
  249. HShader Shader::create(const String& name, const SHADER_DESC& desc, const Vector<SPtr<Technique>>& techniques)
  250. {
  251. ShaderPtr newShader = bs_core_ptr<Shader, PoolAlloc>(new (bs_alloc<Shader, PoolAlloc>()) Shader(name, desc, techniques));
  252. newShader->_setThisPtr(newShader);
  253. newShader->initialize();
  254. return static_resource_cast<Shader>(gResources()._createResourceHandle(newShader));
  255. }
  256. ShaderPtr Shader::createEmpty()
  257. {
  258. ShaderPtr newShader = bs_core_ptr<Shader, PoolAlloc>(new (bs_alloc<Shader, PoolAlloc>()) Shader());
  259. newShader->_setThisPtr(newShader);
  260. return newShader;
  261. }
  262. RTTITypeBase* Shader::getRTTIStatic()
  263. {
  264. return ShaderRTTI::instance();
  265. }
  266. RTTITypeBase* Shader::getRTTI() const
  267. {
  268. return Shader::getRTTIStatic();
  269. }
  270. }