BsD3D11GpuProgram.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #include "BsD3D11GpuProgram.h"
  2. #include "BsD3D11Device.h"
  3. #include "BsException.h"
  4. #include "BsDebug.h"
  5. #include "BsGpuParams.h"
  6. #include "BsD3D11RenderAPI.h"
  7. #include "BsGpuProgramManager.h"
  8. #include "BsHardwareBufferManager.h"
  9. #include "BsD3D11HLSLParamParser.h"
  10. #include "BsRenderStats.h"
  11. namespace BansheeEngine
  12. {
  13. UINT32 D3D11GpuProgramCore::GlobalProgramId = 0;
  14. D3D11GpuProgramCore::D3D11GpuProgramCore(const String& source, const String& entryPoint, GpuProgramType gptype,
  15. GpuProgramProfile profile, bool isAdjacencyInfoRequired)
  16. : GpuProgramCore(source, entryPoint, gptype, profile, isAdjacencyInfoRequired),
  17. mEnableBackwardsCompatibility(false), mProgramId(0)
  18. {
  19. }
  20. D3D11GpuProgramCore::~D3D11GpuProgramCore()
  21. {
  22. mMicrocode.clear();
  23. mInputDeclaration = nullptr;
  24. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_GpuProgram);
  25. }
  26. void D3D11GpuProgramCore::initialize()
  27. {
  28. if (!isSupported())
  29. {
  30. mIsCompiled = false;
  31. mCompileError = "Specified program is not supported by the current render system.";
  32. GpuProgramCore::initialize();
  33. return;
  34. }
  35. D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPICore::instancePtr());
  36. String hlslProfile = rs->getCapabilities()->gpuProgProfileToRSSpecificProfile(mProperties.getProfile());
  37. ID3DBlob* microcode = compileMicrocode(hlslProfile);
  38. if (microcode != nullptr)
  39. {
  40. mMicrocode.resize(microcode->GetBufferSize());
  41. memcpy(&mMicrocode[0], microcode->GetBufferPointer(), microcode->GetBufferSize());
  42. populateParametersAndConstants(microcode);
  43. loadFromMicrocode(rs->getPrimaryDevice(), microcode);
  44. SAFE_RELEASE(microcode);
  45. }
  46. mProgramId = GlobalProgramId++;
  47. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_GpuProgram);
  48. GpuProgramCore::initialize();
  49. }
  50. ID3DBlob* D3D11GpuProgramCore::compileMicrocode(const String& profile)
  51. {
  52. // TODO - Preprocessor defines aren't supported
  53. UINT compileFlags = 0;
  54. #if defined(BS_DEBUG_MODE)
  55. compileFlags |= D3DCOMPILE_DEBUG;
  56. compileFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
  57. #endif
  58. compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
  59. if (mEnableBackwardsCompatibility)
  60. compileFlags |= D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
  61. ID3DBlob* microCode = nullptr;
  62. ID3DBlob* errors = nullptr;
  63. const String& source = mProperties.getSource();
  64. const String& entryPoint = mProperties.getEntryPoint();
  65. HRESULT hr = D3DCompile(
  66. source.c_str(), // [in] Pointer to the shader in memory.
  67. source.size(), // [in] Size of the shader in memory.
  68. nullptr, // [in] The name of the file that contains the shader code.
  69. nullptr, // [in] Optional. Pointer to a NULL-terminated array of macro definitions. See D3D_SHADER_MACRO. If not used, set this to NULL.
  70. 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.
  71. entryPoint.c_str(), // [in] Name of the shader-entrypoint function where shader execution begins.
  72. profile.c_str(),// [in] A string that specifies the shader model; can be any profile in shader model 4 or higher.
  73. compileFlags, // [in] Effect compile flags - no D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY at the first try...
  74. 0, // [in] Effect compile flags
  75. &microCode, // [out] A pointer to an ID3DBlob Interface which contains the compiled shader, as well as any embedded debug and symbol-table information.
  76. &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.
  77. );
  78. if (FAILED(hr))
  79. {
  80. mIsCompiled = false;
  81. mCompileError = "Cannot compile D3D11 high-level shader. Errors:\n" +
  82. String(static_cast<const char*>(errors->GetBufferPointer()));
  83. SAFE_RELEASE(microCode);
  84. SAFE_RELEASE(errors);
  85. return nullptr;
  86. }
  87. else
  88. {
  89. mIsCompiled = true;
  90. mCompileError = "";
  91. SAFE_RELEASE(errors);
  92. return microCode;
  93. }
  94. }
  95. void D3D11GpuProgramCore::populateParametersAndConstants(ID3DBlob* microcode)
  96. {
  97. assert(microcode != nullptr);
  98. D3D11HLSLParamParser parser;
  99. if (mProperties.getType() == GPT_VERTEX_PROGRAM)
  100. {
  101. List<VertexElement> inputParams;
  102. parser.parse(microcode, *mParametersDesc, &inputParams);
  103. mInputDeclaration = HardwareBufferCoreManager::instance().createVertexDeclaration(inputParams);
  104. }
  105. else
  106. {
  107. parser.parse(microcode, *mParametersDesc, nullptr);
  108. }
  109. }
  110. D3D11GpuVertexProgramCore::D3D11GpuVertexProgramCore(const String& source, const String& entryPoint,
  111. GpuProgramProfile profile)
  112. : D3D11GpuProgramCore(source, entryPoint, GPT_VERTEX_PROGRAM, profile, false)
  113. , mVertexShader(nullptr)
  114. { }
  115. D3D11GpuVertexProgramCore::~D3D11GpuVertexProgramCore()
  116. {
  117. SAFE_RELEASE(mVertexShader);
  118. }
  119. void D3D11GpuVertexProgramCore::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  120. {
  121. HRESULT hr = device.getD3D11Device()->CreateVertexShader(
  122. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  123. device.getClassLinkage(), &mVertexShader);
  124. if (FAILED(hr) || device.hasError())
  125. {
  126. String errorDescription = device.getErrorDescription();
  127. BS_EXCEPT(RenderingAPIException,
  128. "Cannot create D3D11 vertex shader from microcode\nError Description:" + errorDescription);
  129. }
  130. }
  131. ID3D11VertexShader * D3D11GpuVertexProgramCore::getVertexShader() const
  132. {
  133. return mVertexShader;
  134. }
  135. D3D11GpuFragmentProgramCore::D3D11GpuFragmentProgramCore(const String& source, const String& entryPoint,
  136. GpuProgramProfile profile)
  137. : D3D11GpuProgramCore(source, entryPoint, GPT_FRAGMENT_PROGRAM, profile, false)
  138. , mPixelShader(nullptr)
  139. { }
  140. D3D11GpuFragmentProgramCore::~D3D11GpuFragmentProgramCore()
  141. {
  142. SAFE_RELEASE(mPixelShader);
  143. }
  144. void D3D11GpuFragmentProgramCore::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  145. {
  146. HRESULT hr = device.getD3D11Device()->CreatePixelShader(
  147. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  148. device.getClassLinkage(), &mPixelShader);
  149. if (FAILED(hr) || device.hasError())
  150. {
  151. String errorDescription = device.getErrorDescription();
  152. BS_EXCEPT(RenderingAPIException,
  153. "Cannot create D3D11 pixel shader from microcode.\nError Description:" + errorDescription);
  154. }
  155. }
  156. ID3D11PixelShader * D3D11GpuFragmentProgramCore::getPixelShader() const
  157. {
  158. return mPixelShader;
  159. }
  160. D3D11GpuGeometryProgramCore::D3D11GpuGeometryProgramCore(const String& source, const String& entryPoint,
  161. GpuProgramProfile profile, bool isAdjacencyInfoRequired)
  162. : D3D11GpuProgramCore(source, entryPoint, GPT_GEOMETRY_PROGRAM, profile, isAdjacencyInfoRequired)
  163. , mGeometryShader(nullptr)
  164. { }
  165. D3D11GpuGeometryProgramCore::~D3D11GpuGeometryProgramCore()
  166. {
  167. SAFE_RELEASE(mGeometryShader);
  168. }
  169. void D3D11GpuGeometryProgramCore::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  170. {
  171. HRESULT hr = device.getD3D11Device()->CreateGeometryShader(
  172. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  173. device.getClassLinkage(), &mGeometryShader);
  174. if (FAILED(hr) || device.hasError())
  175. {
  176. String errorDescription = device.getErrorDescription();
  177. BS_EXCEPT(RenderingAPIException,
  178. "Cannot create D3D11 geometry shader from microcode.\nError Description:" + errorDescription);
  179. }
  180. }
  181. ID3D11GeometryShader * D3D11GpuGeometryProgramCore::getGeometryShader() const
  182. {
  183. return mGeometryShader;
  184. }
  185. D3D11GpuDomainProgramCore::D3D11GpuDomainProgramCore(const String& source, const String& entryPoint,
  186. GpuProgramProfile profile)
  187. : D3D11GpuProgramCore(source, entryPoint, GPT_DOMAIN_PROGRAM, profile, false)
  188. , mDomainShader(nullptr)
  189. { }
  190. D3D11GpuDomainProgramCore::~D3D11GpuDomainProgramCore()
  191. {
  192. SAFE_RELEASE(mDomainShader);
  193. }
  194. void D3D11GpuDomainProgramCore::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  195. {
  196. HRESULT hr = device.getD3D11Device()->CreateDomainShader(
  197. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  198. device.getClassLinkage(), &mDomainShader);
  199. if (FAILED(hr) || device.hasError())
  200. {
  201. String errorDescription = device.getErrorDescription();
  202. BS_EXCEPT(RenderingAPIException,
  203. "Cannot create D3D11 domain shader from microcode.\nError Description:" + errorDescription);
  204. }
  205. }
  206. ID3D11DomainShader * D3D11GpuDomainProgramCore::getDomainShader() const
  207. {
  208. return mDomainShader;
  209. }
  210. D3D11GpuHullProgramCore::D3D11GpuHullProgramCore(const String& source, const String& entryPoint,
  211. GpuProgramProfile profile)
  212. : D3D11GpuProgramCore(source, entryPoint, GPT_HULL_PROGRAM, profile, false)
  213. , mHullShader(nullptr)
  214. { }
  215. D3D11GpuHullProgramCore::~D3D11GpuHullProgramCore()
  216. {
  217. SAFE_RELEASE(mHullShader);
  218. }
  219. void D3D11GpuHullProgramCore::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  220. {
  221. // Create the shader
  222. HRESULT hr = device.getD3D11Device()->CreateHullShader(
  223. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  224. device.getClassLinkage(), &mHullShader);
  225. if (FAILED(hr) || device.hasError())
  226. {
  227. String errorDescription = device.getErrorDescription();
  228. BS_EXCEPT(RenderingAPIException,
  229. "Cannot create D3D11 hull shader from microcode.\nError Description:" + errorDescription);
  230. }
  231. }
  232. ID3D11HullShader* D3D11GpuHullProgramCore::getHullShader() const
  233. {
  234. return mHullShader;
  235. }
  236. D3D11GpuComputeProgramCore::D3D11GpuComputeProgramCore(const String& source, const String& entryPoint,
  237. GpuProgramProfile profile)
  238. : D3D11GpuProgramCore(source, entryPoint, GPT_COMPUTE_PROGRAM, profile, false)
  239. , mComputeShader(nullptr)
  240. { }
  241. D3D11GpuComputeProgramCore::~D3D11GpuComputeProgramCore()
  242. {
  243. SAFE_RELEASE(mComputeShader);
  244. }
  245. void D3D11GpuComputeProgramCore::loadFromMicrocode(D3D11Device& device, ID3D10Blob* microcode)
  246. {
  247. HRESULT hr = device.getD3D11Device()->CreateComputeShader(
  248. static_cast<DWORD*>(microcode->GetBufferPointer()), microcode->GetBufferSize(),
  249. device.getClassLinkage(), &mComputeShader);
  250. if (FAILED(hr) || device.hasError())
  251. {
  252. String errorDescription = device.getErrorDescription();
  253. BS_EXCEPT(RenderingAPIException,
  254. "Cannot create D3D11 compute shader from microcode.\nError Description:" + errorDescription);
  255. }
  256. }
  257. ID3D11ComputeShader* D3D11GpuComputeProgramCore::getComputeShader() const
  258. {
  259. return mComputeShader;
  260. }
  261. }