shaderc_dxil.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. /*
  2. * Copyright 2011-2025 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
  4. */
  5. #include "shaderc.h"
  6. #include <bx/os.h>
  7. #if SHADERC_CONFIG_DXIL
  8. #if BX_PLATFORM_WINDOWS
  9. # include <windows.h>
  10. #endif // BX_PLATFORM_WINDOWS
  11. #ifndef _Maybenull_
  12. # define _Maybenull_
  13. #endif // _Maybenull_
  14. #ifndef _In_bytecount_
  15. # define _In_bytecount_(size)
  16. #endif // _In_bytecount_
  17. #include <unknwnbase.h>
  18. #include <dxcapi.h>
  19. #include <winapifamily.h>
  20. #include <d3d12shader.h>
  21. namespace bgfx { namespace dxil
  22. {
  23. static const GUID IID_ID3D12ShaderReflection = { 0x5a58797d, 0xa72c, 0x478d, { 0x8b, 0xa2, 0xef, 0xc6, 0xb0, 0xef, 0xe8, 0x8e } };
  24. static const GUID IID_ID3D12ShaderReflectionConstantBuffer = { 0xc59598b4, 0x48b3, 0x4869, { 0xb9, 0xb1, 0xb1, 0x61, 0x8b, 0x14, 0xa8, 0xb7 } };
  25. static const GUID IID_IDxcBlob = { 0x8ba5fb08, 0x5195, 0x40e2, { 0xac, 0x58, 0x0d, 0x98, 0x9c, 0x3a, 0x01, 0x02 } };
  26. static const GUID IID_IDxcBlobEncoding = { 0x7241d424, 0x2646, 0x4191, { 0x97, 0xc0, 0x98, 0xe9, 0x6e, 0x42, 0xfc, 0x68 } };
  27. static const GUID IID_IDxcBlobUtf8 = { 0x3da636c9, 0xba71, 0x4024, { 0xa3, 0x01, 0x30, 0xcb, 0xf1, 0x25, 0x30, 0x5b } };
  28. static const GUID IID_IDxcCompiler3 = { 0x228b4687, 0x5a6a, 0x4730, { 0x90, 0x0c, 0x97, 0x02, 0xb2, 0x20, 0x3f, 0x54 } };
  29. static const GUID IID_IDxcResult = { 0x58346cda, 0xdde7, 0x4497, { 0x94, 0x61, 0x6f, 0x87, 0xaf, 0x5e, 0x06, 0x59 } };
  30. static const GUID IID_IDxcUtils = { 0x4605c4cb, 0x2019, 0x492a, { 0xad, 0xa4, 0x65, 0xf2, 0x0b, 0xb7, 0xd6, 0x7f } };
  31. template<typename Ty>
  32. void dxcRelease(Ty*& _ptr)
  33. {
  34. if (NULL != _ptr)
  35. {
  36. _ptr->Release();
  37. _ptr = NULL;
  38. }
  39. }
  40. struct RemapInputSemantic
  41. {
  42. bgfx::Attrib::Enum m_attr;
  43. const char* m_name;
  44. uint8_t m_index;
  45. };
  46. static const RemapInputSemantic s_remapInputSemantic[bgfx::Attrib::Count + 1] =
  47. {
  48. { bgfx::Attrib::Position, "POSITION", 0 },
  49. { bgfx::Attrib::Normal, "NORMAL", 0 },
  50. { bgfx::Attrib::Tangent, "TANGENT", 0 },
  51. { bgfx::Attrib::Bitangent, "BITANGENT", 0 },
  52. { bgfx::Attrib::Color0, "COLOR", 0 },
  53. { bgfx::Attrib::Color1, "COLOR", 1 },
  54. { bgfx::Attrib::Color2, "COLOR", 2 },
  55. { bgfx::Attrib::Color3, "COLOR", 3 },
  56. { bgfx::Attrib::Indices, "BLENDINDICES", 0 },
  57. { bgfx::Attrib::Weight, "BLENDWEIGHT", 0 },
  58. { bgfx::Attrib::TexCoord0, "TEXCOORD", 0 },
  59. { bgfx::Attrib::TexCoord1, "TEXCOORD", 1 },
  60. { bgfx::Attrib::TexCoord2, "TEXCOORD", 2 },
  61. { bgfx::Attrib::TexCoord3, "TEXCOORD", 3 },
  62. { bgfx::Attrib::TexCoord4, "TEXCOORD", 4 },
  63. { bgfx::Attrib::TexCoord5, "TEXCOORD", 5 },
  64. { bgfx::Attrib::TexCoord6, "TEXCOORD", 6 },
  65. { bgfx::Attrib::TexCoord7, "TEXCOORD", 7 },
  66. { bgfx::Attrib::Count, "", 0 },
  67. };
  68. const RemapInputSemantic& findInputSemantic(const char* _name, uint8_t _index)
  69. {
  70. for (uint32_t ii = 0; ii < bgfx::Attrib::Count; ++ii)
  71. {
  72. const RemapInputSemantic& ris = s_remapInputSemantic[ii];
  73. if (0 == bx::strCmp(ris.m_name, _name)
  74. && ris.m_index == _index)
  75. {
  76. return ris;
  77. }
  78. }
  79. return s_remapInputSemantic[bgfx::Attrib::Count];
  80. }
  81. struct UniformRemap
  82. {
  83. UniformType::Enum id;
  84. D3D_SHADER_VARIABLE_CLASS paramClass;
  85. D3D_SHADER_VARIABLE_TYPE paramType;
  86. uint8_t columns;
  87. uint8_t rows;
  88. };
  89. static const UniformRemap s_uniformRemap[] =
  90. {
  91. { UniformType::Sampler, D3D_SVC_SCALAR, D3D_SVT_INT, 0, 0 },
  92. { UniformType::Vec4, D3D_SVC_VECTOR, D3D_SVT_FLOAT, 0, 0 },
  93. { UniformType::Mat3, D3D_SVC_MATRIX_COLUMNS, D3D_SVT_FLOAT, 3, 3 },
  94. { UniformType::Mat4, D3D_SVC_MATRIX_COLUMNS, D3D_SVT_FLOAT, 4, 4 },
  95. { UniformType::Sampler, D3D_SVC_OBJECT, D3D_SVT_SAMPLER, 0, 0 },
  96. { UniformType::Sampler, D3D_SVC_OBJECT, D3D_SVT_SAMPLER2D, 0, 0 },
  97. { UniformType::Sampler, D3D_SVC_OBJECT, D3D_SVT_SAMPLER3D, 0, 0 },
  98. { UniformType::Sampler, D3D_SVC_OBJECT, D3D_SVT_SAMPLERCUBE, 0, 0 },
  99. };
  100. UniformType::Enum findUniformType(const D3D12_SHADER_TYPE_DESC& constDesc)
  101. {
  102. for (uint32_t ii = 0; ii < BX_COUNTOF(s_uniformRemap); ++ii)
  103. {
  104. const UniformRemap& remap = s_uniformRemap[ii];
  105. if (remap.paramClass == constDesc.Class
  106. && remap.paramType == constDesc.Type)
  107. {
  108. if (D3D_SVC_MATRIX_COLUMNS != constDesc.Class)
  109. {
  110. return remap.id;
  111. }
  112. if (remap.columns == constDesc.Columns
  113. && remap.rows == constDesc.Rows)
  114. {
  115. return remap.id;
  116. }
  117. }
  118. }
  119. return UniformType::Count;
  120. }
  121. static const wchar_t* s_optimizationLevel[] =
  122. {
  123. DXC_ARG_OPTIMIZATION_LEVEL0,
  124. DXC_ARG_OPTIMIZATION_LEVEL1,
  125. DXC_ARG_OPTIMIZATION_LEVEL2,
  126. DXC_ARG_OPTIMIZATION_LEVEL3,
  127. };
  128. typedef std::vector<std::string> UniformNameList;
  129. struct Dxc
  130. {
  131. IDxcCompiler3* compiler3 = NULL;
  132. IDxcUtils* utils = NULL;
  133. void* dll = NULL;
  134. };
  135. void unload(Dxc& _dxc)
  136. {
  137. dxcRelease(_dxc.utils);
  138. dxcRelease(_dxc.compiler3);
  139. bx::dlclose(_dxc.dll);
  140. _dxc.dll = NULL;
  141. }
  142. Dxc load()
  143. {
  144. const char* dxcCompilerDllName =
  145. #if BX_PLATFORM_WINDOWS
  146. "dxcompiler.dll"
  147. #elif BX_PLATFORM_LINUX
  148. "libdxcompiler.so"
  149. #else
  150. "dxcompiler???"
  151. #endif // BX_PLATFORM_
  152. ;
  153. HRESULT hr = E_FAIL;
  154. Dxc dxc;
  155. dxc.dll = bx::dlopen(dxcCompilerDllName);
  156. if (NULL == dxc.dll)
  157. {
  158. BX_TRACE("Error: Unable to open %s shader compiler.\n", dxcCompilerDllName);
  159. return Dxc{};
  160. }
  161. DxcCreateInstanceProc DxcCreateInstance = bx::dlsym<DxcCreateInstanceProc>(dxc.dll, "DxcCreateInstance");
  162. if (NULL == DxcCreateInstance)
  163. {
  164. BX_TRACE("Error: Symbol 'DxcCreateInstance' not found.\n");
  165. unload(dxc);
  166. return Dxc{};
  167. }
  168. hr = DxcCreateInstance(CLSID_DxcCompiler, IID_IDxcCompiler3, (void**)&dxc.compiler3);
  169. if (FAILED(hr) )
  170. {
  171. BX_TRACE("Error: DxcCreateInstance IID_IDxcCompiler3 failed 0x%08x\n", (uint32_t)hr);
  172. unload(dxc);
  173. return Dxc{};
  174. }
  175. hr = DxcCreateInstance(CLSID_DxcUtils, IID_IDxcUtils, (void**)&dxc.utils);
  176. if (FAILED(hr) )
  177. {
  178. BX_TRACE("Error: DxcCreateInstance IID_IDxcUtils failed 0x%08x\n", (uint32_t)hr);
  179. unload(dxc);
  180. return Dxc{};
  181. }
  182. return dxc;
  183. }
  184. bool getReflectionData(ID3D12ShaderReflection* _shaderReflection, bool _vshader, UniformArray& _uniforms, uint8_t& _numAttrs, uint16_t* _attrs, uint16_t& _size, UniformNameList& unusedUniforms, bx::WriterI* _messageWriter)
  185. {
  186. bx::Error messageErr;
  187. HRESULT hr = E_FAIL;
  188. D3D12_SHADER_DESC desc;
  189. hr = _shaderReflection->GetDesc(&desc);
  190. if (FAILED(hr) )
  191. {
  192. bx::write(_messageWriter, &messageErr, "Error: ID3D12ShaderReflection::GetDesc failed 0x%08x\n", (uint32_t)hr);
  193. return false;
  194. }
  195. BX_TRACE("Creator: %s 0x%08x", desc.Creator, desc.Version);
  196. BX_TRACE("Num constant buffers: %d", desc.ConstantBuffers);
  197. BX_TRACE("Input:");
  198. if (_vshader) // Only care about input semantic on vertex shaders
  199. {
  200. for (uint32_t ii = 0; ii < desc.InputParameters; ++ii)
  201. {
  202. D3D12_SIGNATURE_PARAMETER_DESC spd;
  203. _shaderReflection->GetInputParameterDesc(ii, &spd);
  204. BX_TRACE("\t%2d: %s%d, vt %d, ct %d, mask %x, reg %d"
  205. , ii
  206. , spd.SemanticName
  207. , spd.SemanticIndex
  208. , spd.SystemValueType
  209. , spd.ComponentType
  210. , spd.Mask
  211. , spd.Register
  212. );
  213. const RemapInputSemantic& ris = findInputSemantic(spd.SemanticName, uint8_t(spd.SemanticIndex) );
  214. if (ris.m_attr != bgfx::Attrib::Count)
  215. {
  216. _attrs[_numAttrs] = bgfx::attribToId(ris.m_attr);
  217. ++_numAttrs;
  218. }
  219. }
  220. }
  221. BX_TRACE("Output:");
  222. for (uint32_t ii = 0; ii < desc.OutputParameters; ++ii)
  223. {
  224. D3D12_SIGNATURE_PARAMETER_DESC spd;
  225. _shaderReflection->GetOutputParameterDesc(ii, &spd);
  226. BX_TRACE("\t%2d: %s%d, %d, %d", ii, spd.SemanticName, spd.SemanticIndex, spd.SystemValueType, spd.ComponentType);
  227. }
  228. for (uint32_t ii = 0, num = bx::uint32_min(1, desc.ConstantBuffers); ii < num; ++ii)
  229. {
  230. ID3D12ShaderReflectionConstantBuffer* cbuffer = _shaderReflection->GetConstantBufferByIndex(ii);
  231. D3D12_SHADER_BUFFER_DESC bufferDesc;
  232. hr = cbuffer->GetDesc(&bufferDesc);
  233. _size = (uint16_t)bufferDesc.Size;
  234. if (SUCCEEDED(hr) )
  235. {
  236. BX_TRACE("%s, %d, vars %d, size %d"
  237. , bufferDesc.Name
  238. , bufferDesc.Type
  239. , bufferDesc.Variables
  240. , bufferDesc.Size
  241. );
  242. for (uint32_t jj = 0; jj < bufferDesc.Variables; ++jj)
  243. {
  244. ID3D12ShaderReflectionVariable* var = cbuffer->GetVariableByIndex(jj);
  245. ID3D12ShaderReflectionType* type = var->GetType();
  246. D3D12_SHADER_VARIABLE_DESC varDesc;
  247. hr = var->GetDesc(&varDesc);
  248. if (SUCCEEDED(hr) )
  249. {
  250. D3D12_SHADER_TYPE_DESC constDesc;
  251. hr = type->GetDesc(&constDesc);
  252. if (SUCCEEDED(hr) )
  253. {
  254. UniformType::Enum uniformType = findUniformType(constDesc);
  255. if (UniformType::Count != uniformType
  256. && 0 != (varDesc.uFlags & D3D_SVF_USED) )
  257. {
  258. Uniform un;
  259. un.name = varDesc.Name;
  260. un.type = uniformType;
  261. un.num = uint8_t(constDesc.Elements);
  262. un.regIndex = uint16_t(varDesc.StartOffset);
  263. un.regCount = uint16_t(bx::alignUp(varDesc.Size, 16) / 16);
  264. _uniforms.push_back(un);
  265. BX_TRACE("\t%s, %d, size %d, flags 0x%08x, %d (used)"
  266. , varDesc.Name
  267. , varDesc.StartOffset
  268. , varDesc.Size
  269. , varDesc.uFlags
  270. , uniformType
  271. );
  272. }
  273. else
  274. {
  275. if (0 == (varDesc.uFlags & D3D_SVF_USED) )
  276. {
  277. unusedUniforms.push_back(varDesc.Name);
  278. }
  279. BX_TRACE("\t%s, unknown type", varDesc.Name);
  280. }
  281. }
  282. }
  283. }
  284. }
  285. }
  286. BX_TRACE("Bound:");
  287. for (uint32_t ii = 0; ii < desc.BoundResources; ++ii)
  288. {
  289. D3D12_SHADER_INPUT_BIND_DESC bindDesc;
  290. hr = _shaderReflection->GetResourceBindingDesc(ii, &bindDesc);
  291. if (SUCCEEDED(hr) )
  292. {
  293. if (D3D_SIT_SAMPLER == bindDesc.Type)
  294. {
  295. BX_TRACE("\t%s, %d, %d, %d"
  296. , bindDesc.Name
  297. , bindDesc.Type
  298. , bindDesc.BindPoint
  299. , bindDesc.BindCount
  300. );
  301. bx::StringView end = bx::strFind(bindDesc.Name, "Sampler");
  302. if (!end.isEmpty() )
  303. {
  304. Uniform un;
  305. un.name.assign(bindDesc.Name, (end.getPtr() - bindDesc.Name) );
  306. un.type = UniformType::Enum(kUniformSamplerBit | UniformType::Sampler);
  307. un.num = 1;
  308. un.regIndex = uint16_t(bindDesc.BindPoint);
  309. un.regCount = uint16_t(bindDesc.BindCount);
  310. _uniforms.push_back(un);
  311. }
  312. }
  313. }
  314. }
  315. return true;
  316. }
  317. static bool compile(Dxc& _dxc, const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _shaderWriter, bx::WriterI* _messageWriter, bool _firstPass)
  318. {
  319. bx::Error messageErr;
  320. bx::ErrorAssert err;
  321. HRESULT hr = E_FAIL;
  322. {
  323. const DxcBuffer source =
  324. {
  325. .Ptr = _code.c_str(),
  326. .Size = _code.size(),
  327. .Encoding = DXC_CP_UTF8,
  328. };
  329. const wchar_t* args[32];
  330. uint32_t numArgs = 0;
  331. args[numArgs++] = L"-E";
  332. args[numArgs++] = L"main";
  333. args[numArgs++] = L"-T";
  334. if ('c' == _options.shaderType)
  335. {
  336. args[numArgs++] = L"cs_6_0";
  337. }
  338. else if ('f' == _options.shaderType)
  339. {
  340. args[numArgs++] = L"ps_6_0";
  341. }
  342. else if ('v' == _options.shaderType)
  343. {
  344. args[numArgs++] = L"vs_6_0";
  345. }
  346. if (_options.warningsAreErrors)
  347. {
  348. args[numArgs++] = DXC_ARG_WARNINGS_ARE_ERRORS;
  349. }
  350. if (_options.optimize)
  351. {
  352. const uint32_t optimization = bx::uint32_min(_options.optimizationLevel, BX_COUNTOF(s_optimizationLevel) - 1);
  353. args[numArgs++] = s_optimizationLevel[optimization];
  354. }
  355. else
  356. {
  357. args[numArgs++] = DXC_ARG_SKIP_OPTIMIZATIONS;
  358. }
  359. if (_options.debugInformation)
  360. {
  361. args[numArgs++] = DXC_ARG_DEBUG;
  362. }
  363. if (_options.preferFlowControl)
  364. {
  365. args[numArgs++] = DXC_ARG_PREFER_FLOW_CONTROL;
  366. }
  367. if (!_firstPass)
  368. {
  369. args[numArgs++] = L"-Zs";
  370. args[numArgs++] = L"-Qstrip_debug";
  371. args[numArgs++] = L"-Qstrip_priv";
  372. args[numArgs++] = L"-Qstrip_reflect";
  373. args[numArgs++] = L"-Qstrip_rootsignature";
  374. }
  375. BX_ASSERT(numArgs < BX_COUNTOF(args), "");
  376. IDxcResult* dxcResult = NULL;
  377. hr = _dxc.compiler3->Compile(
  378. &source
  379. , args
  380. , numArgs
  381. , NULL
  382. , IID_IDxcResult
  383. , (void**)&dxcResult
  384. );
  385. if (FAILED(hr) )
  386. {
  387. BX_TRACE("Compile failed %x", hr);
  388. return false;
  389. }
  390. dxcResult->GetStatus(&hr);
  391. if (FAILED(hr) )
  392. {
  393. bx::write(_messageWriter, &messageErr, "Status: %x\n", hr);
  394. BX_TRACE("%s\n", _code.c_str() );
  395. IDxcBlobUtf8* dxcErrors = NULL;
  396. dxcResult->GetOutput(DXC_OUT_ERRORS, IID_IDxcBlobUtf8, (void**)&dxcErrors, NULL);
  397. if (NULL != dxcErrors)
  398. {
  399. bx::write(_messageWriter, &messageErr, "Error: %s\n", dxcErrors->GetStringPointer() );
  400. dxcRelease(dxcErrors);
  401. }
  402. return false;
  403. }
  404. IDxcBlob* dxcReflectionBlob = NULL;
  405. hr = dxcResult->GetOutput(DXC_OUT_REFLECTION, IID_IDxcBlob, (void**)&dxcReflectionBlob, NULL);
  406. if (FAILED(hr) )
  407. {
  408. bx::write(_messageWriter, &messageErr, "Error: GetOutput DXC_OUT_REFLECTION 0x%08x\n", (uint32_t)hr);
  409. return false;
  410. }
  411. const DxcBuffer reflection =
  412. {
  413. .Ptr = dxcReflectionBlob->GetBufferPointer(),
  414. .Size = dxcReflectionBlob->GetBufferSize(),
  415. .Encoding = DXC_CP_ACP,
  416. };
  417. ID3D12ShaderReflection* shaderReflection;
  418. hr = _dxc.utils->CreateReflection(&reflection, IID_ID3D12ShaderReflection, (void**)&shaderReflection);
  419. if (FAILED(hr) )
  420. {
  421. bx::write(_messageWriter, &messageErr, "Error: CreateReflection failed 0x%08x\n", (uint32_t)hr);
  422. return false;
  423. }
  424. UniformArray uniforms;
  425. uint8_t numAttrs = 0;
  426. uint16_t attrs[bgfx::Attrib::Count];
  427. uint16_t size = 0;
  428. UniformNameList unusedUniforms;
  429. if (!getReflectionData(shaderReflection, _options.shaderType == 'v', uniforms, numAttrs, attrs, size, unusedUniforms, _messageWriter) )
  430. {
  431. bx::write(_messageWriter, &messageErr, "Error: Unable to get DXC reflection data.\n");
  432. return false;
  433. }
  434. dxcRelease(shaderReflection);
  435. dxcRelease(dxcReflectionBlob);
  436. if (_firstPass
  437. && unusedUniforms.size() > 0)
  438. {
  439. // first time through, we just find unused uniforms and get rid of them
  440. std::string output;
  441. bx::LineReader reader(_code.c_str() );
  442. while (!reader.isDone() )
  443. {
  444. bx::StringView strLine = reader.next();
  445. bool found = false;
  446. for (UniformNameList::iterator it = unusedUniforms.begin(), itEnd = unusedUniforms.end(); it != itEnd; ++it)
  447. {
  448. bx::StringView str = strFind(strLine, "uniform ");
  449. if (str.isEmpty() )
  450. {
  451. continue;
  452. }
  453. // matching lines like: uniform u_name;
  454. // we want to replace "uniform" with "static" so that it's no longer
  455. // included in the uniform blob that the application must upload
  456. // we can't just remove them, because unused functions might still reference
  457. // them and cause a compile error when they're gone
  458. if (!bx::findIdentifierMatch(strLine, it->c_str() ).isEmpty() )
  459. {
  460. output.append(strLine.getPtr(), str.getPtr() );
  461. output += "static ";
  462. output.append(str.getTerm(), strLine.getTerm() );
  463. output += "\n";
  464. found = true;
  465. unusedUniforms.erase(it);
  466. break;
  467. }
  468. }
  469. if (!found)
  470. {
  471. output.append(strLine.getPtr(), strLine.getTerm() );
  472. output += "\n";
  473. }
  474. }
  475. // recompile with the unused uniforms converted to statics
  476. return compile(_dxc, _options, _version, output.c_str(), _shaderWriter, _messageWriter, false);
  477. }
  478. IDxcBlob* dxcShaderBlob = NULL;
  479. hr = dxcResult->GetOutput(DXC_OUT_OBJECT, IID_IDxcBlob, (void**)&dxcShaderBlob, NULL);
  480. if (NULL == dxcShaderBlob)
  481. {
  482. bx::write(_messageWriter, &messageErr, "Error: Unable to obtain shader object 0x%08x\n", (uint32_t)hr);
  483. return false;
  484. }
  485. {
  486. uint16_t count = (uint16_t)uniforms.size();
  487. bx::write(_shaderWriter, count, &err);
  488. uint32_t fragmentBit = _options.shaderType == 'f' ? kUniformFragmentBit : 0;
  489. for (UniformArray::const_iterator it = uniforms.begin(); it != uniforms.end(); ++it)
  490. {
  491. const Uniform& un = *it;
  492. const uint8_t nameSize = (uint8_t)un.name.size();
  493. bx::write(_shaderWriter, nameSize, &err);
  494. bx::write(_shaderWriter, un.name.c_str(), nameSize, &err);
  495. const uint8_t type = uint8_t(un.type | fragmentBit);
  496. bx::write(_shaderWriter, type, &err);
  497. bx::write(_shaderWriter, un.num, &err);
  498. bx::write(_shaderWriter, un.regIndex, &err);
  499. bx::write(_shaderWriter, un.regCount, &err);
  500. bx::write(_shaderWriter, un.texComponent, &err);
  501. bx::write(_shaderWriter, un.texDimension, &err);
  502. bx::write(_shaderWriter, un.texFormat, &err);
  503. BX_TRACE("%s, %s, %d, %d, %d"
  504. , un.name.c_str()
  505. , getUniformTypeName(UniformType::Enum(un.type & ~kUniformMask))
  506. , un.num
  507. , un.regIndex
  508. , un.regCount
  509. );
  510. }
  511. const uint32_t shaderSize = uint32_t(dxcShaderBlob->GetBufferSize() );
  512. bx::write(_shaderWriter, shaderSize, &err);
  513. bx::write(_shaderWriter, dxcShaderBlob->GetBufferPointer(), shaderSize, &err);
  514. bx::write(_shaderWriter, uint8_t(0), &err);
  515. bx::write(_shaderWriter, numAttrs, &err);
  516. bx::write(_shaderWriter, attrs, numAttrs*sizeof(uint16_t), &err);
  517. bx::write(_shaderWriter, size, &err);
  518. }
  519. if (_options.disasm)
  520. {
  521. const DxcBuffer shader =
  522. {
  523. .Ptr = dxcShaderBlob->GetBufferPointer(),
  524. .Size = dxcShaderBlob->GetBufferSize(),
  525. .Encoding = DXC_CP_ACP,
  526. };
  527. IDxcResult* dxcDisassembleResult = NULL;
  528. hr = _dxc.compiler3->Disassemble(&shader, IID_IDxcResult, (void**)&dxcDisassembleResult);
  529. if (NULL == dxcDisassembleResult)
  530. {
  531. bx::write(_messageWriter, &messageErr, "Error: Unable to disassemble shader 0x%08x\n", (uint32_t)hr);
  532. return false;
  533. }
  534. IDxcBlobUtf8* dxcShaderDisassembleBlob = NULL;
  535. hr = dxcDisassembleResult->GetOutput(DXC_OUT_DISASSEMBLY, IID_IDxcBlobUtf8, (void**)&dxcShaderDisassembleBlob, NULL);
  536. if (NULL == dxcShaderDisassembleBlob)
  537. {
  538. bx::write(_messageWriter, &messageErr, "Error: GetOutput DXC_OUT_DISASSEMBLY 0x%08x\n", (uint32_t)hr);
  539. return false;
  540. }
  541. std::string disasmfp = _options.outputFilePath + ".disasm";
  542. writeFile(disasmfp.c_str(), dxcShaderDisassembleBlob->GetBufferPointer(), (uint32_t)dxcShaderDisassembleBlob->GetBufferSize() );
  543. dxcRelease(dxcShaderDisassembleBlob);
  544. dxcRelease(dxcDisassembleResult);
  545. }
  546. dxcRelease(dxcShaderBlob);
  547. dxcRelease(dxcResult);
  548. }
  549. return SUCCEEDED(hr);
  550. }
  551. } // namespace hlsl
  552. bool compileDxilShader(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _shaderWriter, bx::WriterI* _messageWriter)
  553. {
  554. using namespace dxil;
  555. Dxc dxc = load();
  556. if (NULL == dxc.dll)
  557. {
  558. bx::write(_messageWriter, bx::ErrorIgnore{}, "Error: Unable to load DXC compiler.\n");
  559. return false;
  560. }
  561. const bool result = dxil::compile(dxc, _options, _version, _code, _shaderWriter, _messageWriter, true);
  562. unload(dxc);
  563. return result;
  564. }
  565. } // namespace bgfx
  566. #else
  567. namespace bgfx
  568. {
  569. bool compileDxilShader(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _shaderWriter, bx::WriterI* _messageWriter)
  570. {
  571. BX_UNUSED(_options, _version, _code, _shaderWriter);
  572. bx::Error messageErr;
  573. bx::write(_messageWriter, &messageErr, "DXIL compiler is not supported on this platform.\n");
  574. return false;
  575. }
  576. } // namespace bgfx
  577. #endif // SHADERC_CONFIG_DXIL