CmD3D11HLSLParamParser.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #include "CmD3D11HLSLParamParser.h"
  2. #include "CmD3D11Mappings.h"
  3. #include "CmGpuParamDesc.h"
  4. #include "CmException.h"
  5. #include "CmDebug.h"
  6. namespace CamelotEngine
  7. {
  8. void D3D11HLSLParamParser::parse(ID3DBlob* microcode, GpuParamDesc& desc, VertexDeclarationPtr& inputParams)
  9. {
  10. const char* commentString = nullptr;
  11. ID3DBlob* pIDisassembly = nullptr;
  12. char* pDisassembly = nullptr;
  13. HRESULT hr = D3DDisassemble((UINT*)microcode->GetBufferPointer(),
  14. microcode->GetBufferSize(), D3D_DISASM_ENABLE_COLOR_CODE, commentString, &pIDisassembly);
  15. const char* assemblyCode = static_cast<const char*>(pIDisassembly->GetBufferPointer());
  16. if (FAILED(hr))
  17. CM_EXCEPT(RenderingAPIException, "Unable to disassemble shader.");
  18. ID3D11ShaderReflection* shaderReflection;
  19. hr = D3DReflect((void*)microcode->GetBufferPointer(), microcode->GetBufferSize(),
  20. IID_ID3D11ShaderReflection, (void**)&shaderReflection);
  21. if (FAILED(hr))
  22. CM_EXCEPT(RenderingAPIException, "Cannot reflect D3D11 high-level shader.");
  23. D3D11_SHADER_DESC shaderDesc;
  24. hr = shaderReflection->GetDesc(&shaderDesc);
  25. if (FAILED(hr))
  26. CM_EXCEPT(RenderingAPIException, "Cannot reflect D3D11 high-level shader.");
  27. if(inputParams != nullptr)
  28. {
  29. D3D11_SIGNATURE_PARAMETER_DESC inputParamDesc;
  30. for (UINT32 i = 0; i < shaderDesc.InputParameters; i++)
  31. {
  32. hr = shaderReflection->GetInputParameterDesc(i, &inputParamDesc);
  33. if (FAILED(hr))
  34. CM_EXCEPT(RenderingAPIException, "Cannot get input param desc with index: " + toString(i));
  35. inputParams->addElement(inputParamDesc.Stream, inputParamDesc.Register,
  36. D3D11Mappings::getInputType(inputParamDesc.ComponentType), D3D11Mappings::get(inputParamDesc.SemanticName), inputParamDesc.SemanticIndex);
  37. }
  38. }
  39. for(UINT32 i = 0; i < shaderDesc.BoundResources; i++)
  40. {
  41. D3D11_SHADER_INPUT_BIND_DESC bindingDesc;
  42. hr = shaderReflection->GetResourceBindingDesc(i, &bindingDesc);
  43. if (FAILED(hr))
  44. CM_EXCEPT(RenderingAPIException, "Cannot get resource binding desc with index: " + toString(i));
  45. parseResource(bindingDesc, desc);
  46. }
  47. for(UINT32 i = 0; i < shaderDesc.ConstantBuffers; i++)
  48. {
  49. ID3D11ShaderReflectionConstantBuffer* shaderReflectionConstantBuffer;
  50. shaderReflectionConstantBuffer = shaderReflection->GetConstantBufferByIndex(i);
  51. parseBuffer(shaderReflectionConstantBuffer, desc);
  52. }
  53. // TODO - Parse:
  54. // - Tex arrays, RW tex arrays and MS textures
  55. // - UINT8, UINT and double values
  56. shaderReflection->Release();
  57. }
  58. void D3D11HLSLParamParser::parseResource(D3D11_SHADER_INPUT_BIND_DESC& resourceDesc, GpuParamDesc& desc)
  59. {
  60. for(UINT32 i = 0; i < resourceDesc.BindCount; i++)
  61. {
  62. if(resourceDesc.Type == D3D_SIT_CBUFFER || resourceDesc.Type == D3D_SIT_TBUFFER)
  63. {
  64. GpuParamBlockDesc blockDesc;
  65. blockDesc.name = resourceDesc.Name;
  66. blockDesc.slot = resourceDesc.BindPoint + i;
  67. blockDesc.blockSize = 0; // Calculated manually as we add parameters
  68. desc.paramBlocks.insert(std::make_pair(blockDesc.name, blockDesc));
  69. }
  70. else
  71. {
  72. GpuParamSpecialDesc memberDesc;
  73. memberDesc.name = resourceDesc.Name;
  74. memberDesc.slot = resourceDesc.BindPoint + i;
  75. memberDesc.type = GST_UNKNOWN;
  76. switch(resourceDesc.Type)
  77. {
  78. case D3D_SIT_SAMPLER:
  79. memberDesc.type = GST_SAMPLER2D; // Actual dimension of the sampler doesn't matter
  80. desc.samplers.insert(std::make_pair(memberDesc.name, memberDesc));
  81. break;
  82. case D3D_SIT_TEXTURE:
  83. switch(resourceDesc.Dimension)
  84. {
  85. case D3D_SRV_DIMENSION_TEXTURE1D:
  86. memberDesc.type = GST_TEXTURE1D;
  87. break;
  88. case D3D_SRV_DIMENSION_TEXTURE2D:
  89. memberDesc.type = GST_TEXTURE2D;
  90. break;
  91. case D3D_SRV_DIMENSION_TEXTURE3D:
  92. memberDesc.type = GST_TEXTURE3D;
  93. break;
  94. case D3D_SRV_DIMENSION_TEXTURECUBE:
  95. memberDesc.type = GST_TEXTURECUBE;
  96. break;
  97. default:
  98. LOGWRN("Skipping texture because it has unsupported dimension: " + toString(resourceDesc.Dimension));
  99. }
  100. if(memberDesc.type != GST_UNKNOWN)
  101. desc.textures.insert(std::make_pair(memberDesc.name, memberDesc));
  102. break;
  103. case D3D_SIT_STRUCTURED:
  104. memberDesc.type = GST_STRUCTURED_BUFFER;
  105. desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
  106. break;
  107. case D3D_SIT_BYTEADDRESS:
  108. memberDesc.type = GST_BYTE_BUFFER;
  109. desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
  110. break;
  111. case D3D11_SIT_UAV_RWTYPED:
  112. memberDesc.type = GST_RWTYPED_BUFFER;
  113. desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
  114. break;
  115. case D3D11_SIT_UAV_RWSTRUCTURED:
  116. memberDesc.type = GST_RWSTRUCTURED_BUFFER;
  117. desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
  118. break;
  119. case D3D11_SIT_UAV_RWBYTEADDRESS:
  120. memberDesc.type = GST_RWBYTE_BUFFER;
  121. desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
  122. break;
  123. case D3D_SIT_UAV_APPEND_STRUCTURED:
  124. memberDesc.type = GST_RWAPPEND_BUFFER;
  125. desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
  126. break;
  127. case D3D_SIT_UAV_CONSUME_STRUCTURED:
  128. memberDesc.type = GST_RWCONSUME_BUFFER;
  129. desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
  130. break;
  131. case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER:
  132. memberDesc.type = GST_RWSTRUCTURED_BUFFER_WITH_COUNTER;
  133. desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
  134. break;
  135. default:
  136. LOGWRN("Skipping resource because it has unsupported type: " + toString(resourceDesc.Type));
  137. }
  138. }
  139. }
  140. }
  141. void D3D11HLSLParamParser::parseBuffer(ID3D11ShaderReflectionConstantBuffer* bufferReflection, GpuParamDesc& desc)
  142. {
  143. D3D11_SHADER_BUFFER_DESC constantBufferDesc;
  144. HRESULT hr = bufferReflection->GetDesc(&constantBufferDesc);
  145. if (FAILED(hr))
  146. CM_EXCEPT(RenderingAPIException, "Failed to retrieve HLSL constant buffer description.");
  147. if(constantBufferDesc.Type != D3D_CT_CBUFFER && constantBufferDesc.Type != D3D_CT_TBUFFER)
  148. {
  149. LOGWRN("D3D11 HLSL parsing: Unsupported constant buffer type, skipping. Type: " + toString(constantBufferDesc.Type));
  150. return;
  151. }
  152. GpuParamBlockDesc& blockDesc = desc.paramBlocks[constantBufferDesc.Name];
  153. for(UINT32 j = 0; j < constantBufferDesc.Variables; j++)
  154. {
  155. ID3D11ShaderReflectionVariable* varRef;
  156. varRef = bufferReflection->GetVariableByIndex(j);
  157. D3D11_SHADER_VARIABLE_DESC varDesc;
  158. HRESULT hr = varRef->GetDesc(&varDesc);
  159. if (FAILED(hr))
  160. CM_EXCEPT(RenderingAPIException, "Failed to retrieve HLSL constant buffer variable description.");
  161. ID3D11ShaderReflectionType* varRefType;
  162. varRefType = varRef->GetType();
  163. D3D11_SHADER_TYPE_DESC varTypeDesc;
  164. varRefType->GetDesc(&varTypeDesc);
  165. parseVariable(varTypeDesc, varDesc, desc, blockDesc);
  166. }
  167. #if CM_DEBUG_MODE
  168. if(constantBufferDesc.Size != (blockDesc.blockSize * 4))
  169. {
  170. CM_EXCEPT(InternalErrorException, "Calculated param block size and size returned by DirectX don't match. Calculated size is: " + toString(constantBufferDesc.Size) +
  171. " and DirectX size is: " + toString(blockDesc.blockSize * 4));
  172. }
  173. #endif
  174. }
  175. void D3D11HLSLParamParser::parseVariable(D3D11_SHADER_TYPE_DESC& varTypeDesc, D3D11_SHADER_VARIABLE_DESC& varDesc, GpuParamDesc& desc, GpuParamBlockDesc& paramBlock)
  176. {
  177. GpuParamMemberDesc memberDesc;
  178. memberDesc.name = varDesc.Name;
  179. memberDesc.paramBlockSlot = paramBlock.slot;
  180. memberDesc.arraySize = varTypeDesc.Elements == 0 ? 1 : varTypeDesc.Elements;
  181. memberDesc.elementSize = varDesc.Size / 4; // Stored in multiples of 4
  182. memberDesc.gpuMemOffset = varDesc.StartOffset;
  183. memberDesc.cpuMemOffset = paramBlock.blockSize;
  184. paramBlock.blockSize += memberDesc.arraySize * memberDesc.elementSize;
  185. switch(varTypeDesc.Class)
  186. {
  187. case D3D_SVC_SCALAR:
  188. {
  189. switch(varTypeDesc.Type)
  190. {
  191. case D3D_SVT_BOOL:
  192. memberDesc.type = GMT_BOOL;
  193. break;
  194. case D3D_SVT_INT:
  195. memberDesc.type = GMT_INT1;
  196. break;
  197. case D3D_SVT_FLOAT:
  198. memberDesc.type = GMT_FLOAT1;
  199. break;
  200. default:
  201. LOGWRN("Skipping variable because it has unsupported type: " + toString(varTypeDesc.Type));
  202. }
  203. }
  204. break;
  205. case D3D_SVC_VECTOR:
  206. {
  207. switch(varTypeDesc.Type)
  208. {
  209. case D3D_SVT_INT:
  210. {
  211. switch(varTypeDesc.Columns)
  212. {
  213. case 1:
  214. memberDesc.type = GMT_INT1;
  215. break;
  216. case 2:
  217. memberDesc.type = GMT_INT2;
  218. break;
  219. case 3:
  220. memberDesc.type = GMT_INT3;
  221. break;
  222. case 4:
  223. memberDesc.type = GMT_INT4;
  224. break;
  225. }
  226. }
  227. break;
  228. case D3D_SVT_FLOAT:
  229. {
  230. switch(varTypeDesc.Columns)
  231. {
  232. case 1:
  233. memberDesc.type = GMT_FLOAT1;
  234. break;
  235. case 2:
  236. memberDesc.type = GMT_FLOAT2;
  237. break;
  238. case 3:
  239. memberDesc.type = GMT_FLOAT3;
  240. break;
  241. case 4:
  242. memberDesc.type = GMT_FLOAT4;
  243. break;
  244. }
  245. }
  246. break;
  247. }
  248. }
  249. break;
  250. case D3D_SVC_MATRIX_COLUMNS:
  251. case D3D_SVC_MATRIX_ROWS:
  252. switch(varTypeDesc.Rows)
  253. {
  254. case 2:
  255. switch(varTypeDesc.Columns)
  256. {
  257. case 2:
  258. memberDesc.type = GMT_MATRIX_2X2;
  259. break;
  260. case 3:
  261. memberDesc.type = GMT_MATRIX_2X3;
  262. break;
  263. case 4:
  264. memberDesc.type = GMT_MATRIX_2X4;
  265. break;
  266. }
  267. break;
  268. case 3:
  269. switch(varTypeDesc.Columns)
  270. {
  271. case 2:
  272. memberDesc.type = GMT_MATRIX_3X2;
  273. break;
  274. case 3:
  275. memberDesc.type = GMT_MATRIX_3X3;
  276. break;
  277. case 4:
  278. memberDesc.type = GMT_MATRIX_3X4;
  279. break;
  280. }
  281. break;
  282. case 4:
  283. switch(varTypeDesc.Columns)
  284. {
  285. case 2:
  286. memberDesc.type = GMT_MATRIX_4X2;
  287. break;
  288. case 3:
  289. memberDesc.type = GMT_MATRIX_4X3;
  290. break;
  291. case 4:
  292. memberDesc.type = GMT_MATRIX_4X4;
  293. break;
  294. }
  295. break;
  296. }
  297. break;
  298. case D3D_SVC_STRUCT:
  299. memberDesc.type = GMT_STRUCT;
  300. break;
  301. default:
  302. LOGWRN("Skipping variable because it has unsupported class: " + toString(varTypeDesc.Class));
  303. }
  304. desc.params.insert(std::make_pair(memberDesc.name, memberDesc));
  305. }
  306. }