BsD3D11GpuProgram.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. #include "BsD3D11GpuProgram.h"
  2. #include "BsD3D11Device.h"
  3. #include "BsException.h"
  4. #include "BsDebug.h"
  5. #include "BsGpuParams.h"
  6. #include "BsD3D11RenderSystem.h"
  7. #include "BsGpuProgramManager.h"
  8. #include "BsHardwareBufferManager.h"
  9. #include "BsD3D11HLSLParamParser.h"
  10. #include "BsD3D11GpuProgramRTTI.h"
  11. #include "BsRenderStats.h"
  12. namespace BansheeEngine
  13. {
  14. UINT32 D3D11GpuProgram::GlobalProgramId = 0;
  15. D3D11GpuProgram::D3D11GpuProgram(const String& source, const String& entryPoint, GpuProgramType gptype,
  16. GpuProgramProfile profile, const Vector<HGpuProgInclude>* includes, bool isAdjacencyInfoRequired)
  17. : GpuProgram(source, entryPoint, gptype, profile, includes, isAdjacencyInfoRequired),
  18. mColumnMajorMatrices(false), mEnableBackwardsCompatibility(false), mProgramId(0)
  19. {
  20. }
  21. D3D11GpuProgram::~D3D11GpuProgram()
  22. {
  23. }
  24. void D3D11GpuProgram::initialize_internal()
  25. {
  26. if (!isSupported())
  27. {
  28. mIsCompiled = false;
  29. mCompileError = "Specified program is not supported by the current render system.";
  30. GpuProgram::initialize_internal();
  31. return;
  32. }
  33. D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
  34. String hlslProfile = rs->getCapabilities()->gpuProgProfileToRSSpecificProfile(mProfile);
  35. ID3DBlob* microcode = compileMicrocode(hlslProfile);
  36. if (microcode != nullptr)
  37. {
  38. mMicrocode.resize(microcode->GetBufferSize());
  39. memcpy(&mMicrocode[0], microcode->GetBufferPointer(), microcode->GetBufferSize());
  40. populateParametersAndConstants(microcode);
  41. loadFromMicrocode(rs->getPrimaryDevice(), microcode);
  42. SAFE_RELEASE(microcode);
  43. }
  44. mProgramId = GlobalProgramId++;
  45. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_GpuProgram);
  46. GpuProgram::initialize_internal();
  47. }
  48. void D3D11GpuProgram::destroy_internal()
  49. {
  50. mMicrocode.clear();
  51. mInputDeclaration = nullptr;
  52. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_GpuProgram);
  53. GpuProgram::destroy_internal();
  54. }
  55. ID3DBlob* D3D11GpuProgram::compileMicrocode(const String& profile)
  56. {
  57. // TODO - Preprocessor defines aren't supported
  58. UINT compileFlags = 0;
  59. #if defined(BS_DEBUG_MODE)
  60. compileFlags |= D3DCOMPILE_DEBUG;
  61. compileFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
  62. #endif
  63. if (mColumnMajorMatrices)
  64. compileFlags |= D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
  65. else
  66. compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
  67. if (mEnableBackwardsCompatibility)
  68. compileFlags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
  69. ID3DBlob* microCode = nullptr;
  70. ID3DBlob* errors = nullptr;
  71. HRESULT hr = D3DCompile(
  72. mSource.c_str(), // [in] Pointer to the shader in memory.
  73. mSource.size(), // [in] Size of the shader in memory.
  74. nullptr, // [in] The name of the file that contains the shader code.
  75. nullptr, // [in] Optional. Pointer to a NULL-terminated array of macro definitions. See D3D_SHADER_MACRO. If not used, set this to NULL.
  76. nullptr, // [in] Optional. Pointer to an ID3DInclude Interface interface for handling include files. Setting this to NULL will cause a compile error if a shader contains a #include.
  77. mEntryPoint.c_str(),// [in] Name of the shader-entrypoint function where shader execution begins.
  78. profile.c_str(),// [in] A string that specifies the shader model; can be any profile in shader model 4 or higher.
  79. compileFlags, // [in] Effect compile flags - no D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY at the first try...
  80. 0, // [in] Effect compile flags
  81. &microCode, // [out] A pointer to an ID3DBlob Interface which contains the compiled shader, as well as any embedded debug and symbol-table information.
  82. &errors // [out] A pointer to an ID3DBlob Interface which contains a listing of errors and warnings that occurred during compilation. These errors and warnings are identical to the the debug output from a debugger.
  83. );
  84. if (FAILED(hr))
  85. {
  86. mIsCompiled = false;
  87. mCompileError = "Cannot compile D3D11 high-level shader. Errors:\n" +
  88. String(static_cast<const char*>(errors->GetBufferPointer()));
  89. SAFE_RELEASE(microCode);
  90. SAFE_RELEASE(errors);
  91. return nullptr;
  92. }
  93. else
  94. {
  95. mIsCompiled = true;
  96. mCompileError = "";
  97. SAFE_RELEASE(errors);
  98. return microCode;
  99. }
  100. }
  101. void D3D11GpuProgram::populateParametersAndConstants(ID3DBlob* microcode)
  102. {
  103. assert(microcode != nullptr);
  104. D3D11HLSLParamParser parser;
  105. if (mType == GPT_VERTEX_PROGRAM)
  106. {
  107. VertexDeclaration::VertexElementList inputParams;
  108. parser.parse(microcode, *mParametersDesc, &inputParams);
  109. mInputDeclaration = HardwareBufferManager::instance().createVertexDeclaration(inputParams);
  110. }
  111. else
  112. {
  113. parser.parse(microcode, *mParametersDesc, nullptr);
  114. }
  115. }
  116. GpuParamsPtr D3D11GpuProgram::createParameters()
  117. {
  118. GpuParamsPtr params = bs_shared_ptr<GpuParams, PoolAlloc>(mParametersDesc, mColumnMajorMatrices);
  119. return params;
  120. }
  121. const String& D3D11GpuProgram::getLanguage() const
  122. {
  123. static String name = "hlsl";
  124. return name;
  125. }
  126. /************************************************************************/
  127. /* SERIALIZATION */
  128. /************************************************************************/
  129. RTTITypeBase* D3D11GpuProgram::getRTTIStatic()
  130. {
  131. return D3D11GpuProgramRTTI::instance();
  132. }
  133. RTTITypeBase* D3D11GpuProgram::getRTTI() const
  134. {
  135. return D3D11GpuProgram::getRTTIStatic();
  136. }
  137. D3D11GpuVertexProgram::D3D11GpuVertexProgram(const String& source, const String& entryPoint,
  138. GpuProgramProfile profile, const Vector<HGpuProgInclude>* includes)
  139. : D3D11GpuProgram(source, entryPoint, GPT_VERTEX_PROGRAM, profile, includes, false)
  140. , mVertexShader(nullptr)
  141. { }
  142. D3D11GpuVertexProgram::~D3D11GpuVertexProgram()
  143. { }
  144. void D3D11GpuVertexProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  145. {
  146. HRESULT hr = device.getD3D11Device()->CreateVertexShader(
  147. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  148. device.getClassLinkage(), &mVertexShader);
  149. if (FAILED(hr) || device.hasError())
  150. {
  151. String errorDescription = device.getErrorDescription();
  152. BS_EXCEPT(RenderingAPIException,
  153. "Cannot create D3D11 vertex shader from microcode\nError Description:" + errorDescription);
  154. }
  155. }
  156. void D3D11GpuVertexProgram::destroy_internal()
  157. {
  158. SAFE_RELEASE(mVertexShader);
  159. D3D11GpuProgram::destroy_internal();
  160. }
  161. ID3D11VertexShader * D3D11GpuVertexProgram::getVertexShader() const
  162. {
  163. return mVertexShader;
  164. }
  165. /************************************************************************/
  166. /* SERIALIZATION */
  167. /************************************************************************/
  168. RTTITypeBase* D3D11GpuVertexProgram::getRTTIStatic()
  169. {
  170. return D3D11GpuVertexProgramRTTI::instance();
  171. }
  172. RTTITypeBase* D3D11GpuVertexProgram::getRTTI() const
  173. {
  174. return D3D11GpuVertexProgram::getRTTIStatic();
  175. }
  176. D3D11GpuFragmentProgram::D3D11GpuFragmentProgram(const String& source, const String& entryPoint,
  177. GpuProgramProfile profile, const Vector<HGpuProgInclude>* includes)
  178. : D3D11GpuProgram(source, entryPoint, GPT_FRAGMENT_PROGRAM, profile, includes, false)
  179. , mPixelShader(nullptr)
  180. { }
  181. D3D11GpuFragmentProgram::~D3D11GpuFragmentProgram()
  182. { }
  183. void D3D11GpuFragmentProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  184. {
  185. HRESULT hr = device.getD3D11Device()->CreatePixelShader(
  186. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  187. device.getClassLinkage(), &mPixelShader);
  188. if (FAILED(hr) || device.hasError())
  189. {
  190. String errorDescription = device.getErrorDescription();
  191. BS_EXCEPT(RenderingAPIException,
  192. "Cannot create D3D11 pixel shader from microcode.\nError Description:" + errorDescription);
  193. }
  194. }
  195. void D3D11GpuFragmentProgram::destroy_internal()
  196. {
  197. SAFE_RELEASE(mPixelShader);
  198. D3D11GpuProgram::destroy_internal();
  199. }
  200. ID3D11PixelShader * D3D11GpuFragmentProgram::getPixelShader() const
  201. {
  202. return mPixelShader;
  203. }
  204. /************************************************************************/
  205. /* SERIALIZATION */
  206. /************************************************************************/
  207. RTTITypeBase* D3D11GpuFragmentProgram::getRTTIStatic()
  208. {
  209. return D3D11GpuFragmentProgramRTTI::instance();
  210. }
  211. RTTITypeBase* D3D11GpuFragmentProgram::getRTTI() const
  212. {
  213. return D3D11GpuFragmentProgram::getRTTIStatic();
  214. }
  215. D3D11GpuGeometryProgram::D3D11GpuGeometryProgram(const String& source, const String& entryPoint,
  216. GpuProgramProfile profile, const Vector<HGpuProgInclude>* includes, bool isAdjacencyInfoRequired)
  217. : D3D11GpuProgram(source, entryPoint, GPT_GEOMETRY_PROGRAM, profile, includes, isAdjacencyInfoRequired)
  218. , mGeometryShader(nullptr)
  219. { }
  220. D3D11GpuGeometryProgram::~D3D11GpuGeometryProgram()
  221. { }
  222. void D3D11GpuGeometryProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  223. {
  224. HRESULT hr = device.getD3D11Device()->CreateGeometryShader(
  225. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  226. device.getClassLinkage(), &mGeometryShader);
  227. if (FAILED(hr) || device.hasError())
  228. {
  229. String errorDescription = device.getErrorDescription();
  230. BS_EXCEPT(RenderingAPIException,
  231. "Cannot create D3D11 geometry shader from microcode.\nError Description:" + errorDescription);
  232. }
  233. }
  234. void D3D11GpuGeometryProgram::destroy_internal()
  235. {
  236. SAFE_RELEASE(mGeometryShader);
  237. D3D11GpuProgram::destroy_internal();
  238. }
  239. ID3D11GeometryShader * D3D11GpuGeometryProgram::getGeometryShader() const
  240. {
  241. return mGeometryShader;
  242. }
  243. /************************************************************************/
  244. /* SERIALIZATION */
  245. /************************************************************************/
  246. RTTITypeBase* D3D11GpuGeometryProgram::getRTTIStatic()
  247. {
  248. return D3D11GpuGeometryProgramRTTI::instance();
  249. }
  250. RTTITypeBase* D3D11GpuGeometryProgram::getRTTI() const
  251. {
  252. return D3D11GpuGeometryProgram::getRTTIStatic();
  253. }
  254. D3D11GpuDomainProgram::D3D11GpuDomainProgram(const String& source, const String& entryPoint,
  255. GpuProgramProfile profile, const Vector<HGpuProgInclude>* includes)
  256. : D3D11GpuProgram(source, entryPoint, GPT_DOMAIN_PROGRAM, profile, includes, false)
  257. , mDomainShader(nullptr)
  258. { }
  259. D3D11GpuDomainProgram::~D3D11GpuDomainProgram()
  260. { }
  261. void D3D11GpuDomainProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  262. {
  263. HRESULT hr = device.getD3D11Device()->CreateDomainShader(
  264. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  265. device.getClassLinkage(), &mDomainShader);
  266. if (FAILED(hr) || device.hasError())
  267. {
  268. String errorDescription = device.getErrorDescription();
  269. BS_EXCEPT(RenderingAPIException,
  270. "Cannot create D3D11 domain shader from microcode.\nError Description:" + errorDescription);
  271. }
  272. }
  273. void D3D11GpuDomainProgram::destroy_internal()
  274. {
  275. SAFE_RELEASE(mDomainShader);
  276. D3D11GpuProgram::destroy_internal();
  277. }
  278. ID3D11DomainShader * D3D11GpuDomainProgram::getDomainShader() const
  279. {
  280. return mDomainShader;
  281. }
  282. /************************************************************************/
  283. /* SERIALIZATION */
  284. /************************************************************************/
  285. RTTITypeBase* D3D11GpuDomainProgram::getRTTIStatic()
  286. {
  287. return D3D11GpuDomainProgramRTTI::instance();
  288. }
  289. RTTITypeBase* D3D11GpuDomainProgram::getRTTI() const
  290. {
  291. return D3D11GpuDomainProgram::getRTTIStatic();
  292. }
  293. D3D11GpuHullProgram::D3D11GpuHullProgram(const String& source, const String& entryPoint,
  294. GpuProgramProfile profile, const Vector<HGpuProgInclude>* includes)
  295. : D3D11GpuProgram(source, entryPoint, GPT_HULL_PROGRAM, profile, includes, false)
  296. , mHullShader(nullptr)
  297. { }
  298. D3D11GpuHullProgram::~D3D11GpuHullProgram()
  299. { }
  300. void D3D11GpuHullProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  301. {
  302. // Create the shader
  303. HRESULT hr = device.getD3D11Device()->CreateHullShader(
  304. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  305. device.getClassLinkage(), &mHullShader);
  306. if (FAILED(hr) || device.hasError())
  307. {
  308. String errorDescription = device.getErrorDescription();
  309. BS_EXCEPT(RenderingAPIException,
  310. "Cannot create D3D11 hull shader from microcode.\nError Description:" + errorDescription);
  311. }
  312. }
  313. void D3D11GpuHullProgram::destroy_internal()
  314. {
  315. SAFE_RELEASE(mHullShader);
  316. D3D11GpuProgram::destroy_internal();
  317. }
  318. ID3D11HullShader* D3D11GpuHullProgram::getHullShader() const
  319. {
  320. return mHullShader;
  321. }
  322. /************************************************************************/
  323. /* SERIALIZATION */
  324. /************************************************************************/
  325. RTTITypeBase* D3D11GpuHullProgram::getRTTIStatic()
  326. {
  327. return D3D11GpuHullProgramRTTI::instance();
  328. }
  329. RTTITypeBase* D3D11GpuHullProgram::getRTTI() const
  330. {
  331. return D3D11GpuHullProgram::getRTTIStatic();
  332. }
  333. D3D11GpuComputeProgram::D3D11GpuComputeProgram(const String& source, const String& entryPoint,
  334. GpuProgramProfile profile, const Vector<HGpuProgInclude>* includes)
  335. : D3D11GpuProgram(source, entryPoint, GPT_COMPUTE_PROGRAM, profile, includes, false)
  336. , mComputeShader(nullptr)
  337. { }
  338. D3D11GpuComputeProgram::~D3D11GpuComputeProgram()
  339. { }
  340. void D3D11GpuComputeProgram::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  341. {
  342. HRESULT hr = device.getD3D11Device()->CreateComputeShader(
  343. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  344. device.getClassLinkage(), &mComputeShader);
  345. if (FAILED(hr) || device.hasError())
  346. {
  347. String errorDescription = device.getErrorDescription();
  348. BS_EXCEPT(RenderingAPIException,
  349. "Cannot create D3D11 compute shader from microcode.\nError Description:" + errorDescription);
  350. }
  351. }
  352. void D3D11GpuComputeProgram::destroy_internal()
  353. {
  354. SAFE_RELEASE(mComputeShader);
  355. D3D11GpuProgram::destroy_internal();
  356. }
  357. ID3D11ComputeShader* D3D11GpuComputeProgram::getComputeShader() const
  358. {
  359. return mComputeShader;
  360. }
  361. /************************************************************************/
  362. /* SERIALIZATION */
  363. /************************************************************************/
  364. RTTITypeBase* D3D11GpuComputeProgram::getRTTIStatic()
  365. {
  366. return D3D11GpuComputeProgramRTTI::instance();
  367. }
  368. RTTITypeBase* D3D11GpuComputeProgram::getRTTI() const
  369. {
  370. return D3D11GpuComputeProgram::getRTTIStatic();
  371. }
  372. }