Dxc.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/ShaderCompiler/Dxc.h>
  6. #include <AnKi/Util/Process.h>
  7. #include <AnKi/Util/Filesystem.h>
  8. #include <AnKi/Util/File.h>
  9. #include <AnKi/Util/HighRezTimer.h>
  10. #include <AnKi/Util/StringList.h>
  11. #include <string>
  12. #if ANKI_OS_WINDOWS
  13. # include <windows.h>
  14. # include <wrl/client.h>
  15. # include <ThirdParty/Dxc/Include/d3d12shader.h>
  16. # define CComPtr Microsoft::WRL::ComPtr
  17. #else
  18. # pragma GCC diagnostic push
  19. # pragma GCC diagnostic ignored "-Wimplicit-int-conversion"
  20. # pragma GCC diagnostic ignored "-Wambiguous-reversed-operator"
  21. # define __EMULATE_UUID
  22. # include <ThirdParty/Dxc/Include/WinAdapter.h>
  23. # pragma GCC diagnostic pop
  24. #endif
  25. #include <ThirdParty/Dxc/Include/dxcapi.h>
  26. namespace anki {
  27. static Atomic<U32> g_nextFileId = {1};
  28. #if ANKI_OS_WINDOWS
  29. static HMODULE g_dxilLib = 0;
  30. #endif
  31. static HMODULE g_dxcLib = 0;
  32. static DxcCreateInstanceProc g_DxcCreateInstance = nullptr;
  33. static Mutex g_dxcLibMtx;
  34. #define ANKI_DXC_CHECK(x) \
  35. do \
  36. { \
  37. HRESULT rez; \
  38. if((rez = (x)) < 0) [[unlikely]] \
  39. { \
  40. errorMessage.sprintf("DXC function failed (HRESULT: %d): %s", rez, #x); \
  41. return Error::kFunctionFailed; \
  42. } \
  43. } while(0)
  44. static Error lazyDxcInit(ShaderCompilerString& errorMessage)
  45. {
  46. LockGuard lock(g_dxcLibMtx);
  47. if(g_dxcLib == 0)
  48. {
  49. // Init DXC
  50. #if ANKI_OS_WINDOWS
  51. # if ANKI_CPU_ARCH_X86
  52. g_dxilLib = LoadLibraryA(ANKI_SOURCE_DIRECTORY "/ThirdParty/Dxc/Lib/WinX64/dxil.dll");
  53. # else
  54. g_dxilLib = LoadLibraryA(ANKI_SOURCE_DIRECTORY "/ThirdParty/Dxc/Lib/WinArm64/dxil.dll");
  55. # endif
  56. if(g_dxilLib == 0)
  57. {
  58. errorMessage = "dxil.dll missing or wrong architecture";
  59. return Error::kFunctionFailed;
  60. }
  61. # if ANKI_CPU_ARCH_X86
  62. g_dxcLib = LoadLibraryA(ANKI_SOURCE_DIRECTORY "/ThirdParty/Dxc/Lib/WinX64/dxcompiler.dll");
  63. # else
  64. g_dxcLib = LoadLibraryA(ANKI_SOURCE_DIRECTORY "/ThirdParty/Dxc/Lib/WinArm64/dxcompiler.dll");
  65. # endif
  66. #else
  67. g_dxcLib = dlopen(ANKI_SOURCE_DIRECTORY "/ThirdParty/Dxc/Lib/LinuxX64/libdxcompiler.so", RTLD_LAZY);
  68. #endif
  69. if(g_dxcLib == 0)
  70. {
  71. errorMessage = "dxcompiler.dll/libdxcompiler.so missing or wrong architecture";
  72. return Error::kFunctionFailed;
  73. }
  74. #if ANKI_OS_WINDOWS
  75. g_DxcCreateInstance = reinterpret_cast<DxcCreateInstanceProc>(GetProcAddress(g_dxcLib, "DxcCreateInstance"));
  76. #else
  77. g_DxcCreateInstance = reinterpret_cast<DxcCreateInstanceProc>(dlsym(g_dxcLib, "DxcCreateInstance"));
  78. #endif
  79. if(g_DxcCreateInstance == nullptr)
  80. {
  81. errorMessage = "DxcCreateInstance was not found in the dxcompiler.dll/libdxcompiler.so";
  82. return Error::kFunctionFailed;
  83. }
  84. }
  85. return Error::kNone;
  86. }
  87. static const WChar* profile(ShaderType shaderType, ShaderModel sm)
  88. {
  89. #define ANKI_SM(stage) out = (sm == ShaderModel::k6_7) ? L"" #stage "_6_7" : L"" #stage "_6_8"
  90. const WChar* out = L"";
  91. switch(shaderType)
  92. {
  93. case ShaderType::kVertex:
  94. ANKI_SM(vs);
  95. break;
  96. case ShaderType::kPixel:
  97. ANKI_SM(ps);
  98. break;
  99. case ShaderType::kDomain:
  100. ANKI_SM(ds);
  101. break;
  102. case ShaderType::kHull:
  103. ANKI_SM(hs);
  104. break;
  105. case ShaderType::kGeometry:
  106. ANKI_SM(gs);
  107. break;
  108. case ShaderType::kAmplification:
  109. ANKI_SM(as);
  110. break;
  111. case ShaderType::kMesh:
  112. ANKI_SM(ms);
  113. break;
  114. case ShaderType::kCompute:
  115. ANKI_SM(cs);
  116. break;
  117. case ShaderType::kRayGen:
  118. case ShaderType::kAnyHit:
  119. case ShaderType::kClosestHit:
  120. case ShaderType::kMiss:
  121. case ShaderType::kIntersection:
  122. case ShaderType::kCallable:
  123. case ShaderType::kWorkGraph:
  124. ANKI_SM(lib);
  125. break;
  126. default:
  127. ANKI_ASSERT(0);
  128. };
  129. return out;
  130. #undef ANKI_SM
  131. }
  132. static Error compileHlsl(CString src, ShaderType shaderType, Bool compileWith16bitTypes, Bool debugInfo, ShaderModel sm,
  133. ConstWeakArray<CString> compilerArgs, Bool spirv, ShaderCompilerDynamicArray<U8>& bin, ShaderCompilerString& errorMessage)
  134. {
  135. ANKI_CHECK(lazyDxcInit(errorMessage));
  136. // Call DXC
  137. std::vector<std::wstring> dxcArgs;
  138. dxcArgs.push_back(L"-Fo");
  139. dxcArgs.push_back(L"-Wall");
  140. dxcArgs.push_back(L"-Wextra");
  141. dxcArgs.push_back(L"-Wno-conversion");
  142. dxcArgs.push_back(L"-Werror");
  143. dxcArgs.push_back(L"-Wfatal-errors");
  144. dxcArgs.push_back(L"-Wundef");
  145. dxcArgs.push_back(L"-Wno-unused-const-variable");
  146. dxcArgs.push_back(L"-Wno-unused-parameter");
  147. dxcArgs.push_back(L"-Wno-unneeded-internal-declaration");
  148. dxcArgs.push_back(L"-Wno-payload-access-perf"); // Doesn't always work
  149. dxcArgs.push_back(L"-HV");
  150. dxcArgs.push_back(L"2021");
  151. dxcArgs.push_back(L"-E");
  152. dxcArgs.push_back(L"main");
  153. dxcArgs.push_back(L"-T");
  154. dxcArgs.push_back(profile(shaderType, sm));
  155. if(ANKI_COMPILER_MSVC)
  156. {
  157. dxcArgs.push_back(L"-fdiagnostics-format=msvc"); // Make errors clickable in visual studio
  158. }
  159. if(spirv)
  160. {
  161. dxcArgs.push_back(L"-spirv");
  162. dxcArgs.push_back(L"-fspv-target-env=vulkan1.1spirv1.4");
  163. // dxcArgs.push_back(L"-fvk-support-nonzero-base-instance"); // Match DX12's behavior, SV_INSTANCEID starts from zero
  164. // Shift the bindings in order to identify the registers when doing reflection
  165. for(U32 ds = 0; ds < kMaxRegisterSpaces; ++ds)
  166. {
  167. dxcArgs.push_back(L"-fvk-b-shift");
  168. dxcArgs.push_back(std::to_wstring(kDxcVkBindingShifts[ds][HlslResourceType::kCbv]));
  169. dxcArgs.push_back(std::to_wstring(ds));
  170. dxcArgs.push_back(L"-fvk-t-shift");
  171. dxcArgs.push_back(std::to_wstring(kDxcVkBindingShifts[ds][HlslResourceType::kSrv]));
  172. dxcArgs.push_back(std::to_wstring(ds));
  173. dxcArgs.push_back(L"-fvk-u-shift");
  174. dxcArgs.push_back(std::to_wstring(kDxcVkBindingShifts[ds][HlslResourceType::kUav]));
  175. dxcArgs.push_back(std::to_wstring(ds));
  176. dxcArgs.push_back(L"-fvk-s-shift");
  177. dxcArgs.push_back(std::to_wstring(kDxcVkBindingShifts[ds][HlslResourceType::kSampler]));
  178. dxcArgs.push_back(std::to_wstring(ds));
  179. }
  180. }
  181. else
  182. {
  183. dxcArgs.push_back(L"-Wno-ignored-attributes"); // TODO remove that at some point
  184. dxcArgs.push_back(L"-Wno-inline-asm"); // Workaround a DXC bug
  185. }
  186. if(debugInfo)
  187. {
  188. dxcArgs.push_back(L"-Zi");
  189. }
  190. if(compileWith16bitTypes)
  191. {
  192. dxcArgs.push_back(L"-enable-16bit-types");
  193. }
  194. for(CString extraArg : compilerArgs)
  195. {
  196. WChar wstr[128];
  197. extraArg.toWideChars(wstr, 128);
  198. dxcArgs.push_back(wstr);
  199. }
  200. std::vector<const WChar*> dxcArgsRaw;
  201. dxcArgsRaw.reserve(dxcArgs.size());
  202. for(const auto& x : dxcArgs)
  203. {
  204. dxcArgsRaw.push_back(x.c_str());
  205. }
  206. // Compile
  207. CComPtr<IDxcCompiler3> dxcCompiler;
  208. ANKI_DXC_CHECK(g_DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxcCompiler)));
  209. const DxcBuffer buff = {src.getBegin(), src.getLength(), 0};
  210. CComPtr<IDxcResult> pResults;
  211. ANKI_DXC_CHECK(dxcCompiler->Compile(&buff, dxcArgsRaw.data(), U32(dxcArgsRaw.size()), nullptr, IID_PPV_ARGS(&pResults)));
  212. CComPtr<IDxcBlobUtf8> pErrors = nullptr;
  213. ANKI_DXC_CHECK(pResults->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&pErrors), nullptr));
  214. if(pErrors != nullptr && pErrors->GetStringLength() != 0)
  215. {
  216. errorMessage = pErrors->GetStringPointer();
  217. }
  218. HRESULT hrStatus;
  219. ANKI_DXC_CHECK(pResults->GetStatus(&hrStatus));
  220. if(FAILED(hrStatus))
  221. {
  222. return Error::kFunctionFailed;
  223. }
  224. CComPtr<IDxcBlob> pShader = nullptr;
  225. ANKI_DXC_CHECK(pResults->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&pShader), nullptr));
  226. if(pShader != nullptr && pShader->GetBufferSize() > 0)
  227. {
  228. bin.resize(U32(pShader->GetBufferSize()));
  229. memcpy(bin.getBegin(), pShader->GetBufferPointer(), pShader->GetBufferSize());
  230. }
  231. else
  232. {
  233. ANKI_SHADER_COMPILER_LOGE("DXC returned an empty binary blob");
  234. return Error::kFunctionFailed;
  235. }
  236. return Error::kNone;
  237. }
  238. Error compileHlslToSpirv(CString src, ShaderType shaderType, Bool compileWith16bitTypes, Bool debugInfo, ShaderModel sm,
  239. ConstWeakArray<CString> compilerArgs, ShaderCompilerDynamicArray<U8>& spirv, ShaderCompilerString& errorMessage)
  240. {
  241. return compileHlsl(src, shaderType, compileWith16bitTypes, debugInfo, sm, compilerArgs, true, spirv, errorMessage);
  242. }
  243. Error compileHlslToDxil(CString src, ShaderType shaderType, Bool compileWith16bitTypes, Bool debugInfo, ShaderModel sm,
  244. ConstWeakArray<CString> compilerArgs, ShaderCompilerDynamicArray<U8>& dxil, ShaderCompilerString& errorMessage)
  245. {
  246. return compileHlsl(src, shaderType, compileWith16bitTypes, debugInfo, sm, compilerArgs, false, dxil, errorMessage);
  247. }
  248. #if ANKI_OS_WINDOWS
  249. Error doReflectionDxil(ConstWeakArray<U8> dxil, ShaderType type, ShaderReflection& refl, ShaderCompilerString& errorMessage)
  250. {
  251. using Microsoft::WRL::ComPtr;
  252. // Lazyly load the DXC DLL
  253. {
  254. LockGuard lock(g_dxcLibMtx);
  255. if(g_dxcLib == 0)
  256. {
  257. // Init DXC
  258. g_dxcLib = LoadLibraryA(ANKI_SOURCE_DIRECTORY "/ThirdParty/Bin/Windows64/dxcompiler.dll");
  259. if(g_dxcLib == 0)
  260. {
  261. ANKI_SHADER_COMPILER_LOGE("dxcompiler.dll missing or wrong architecture");
  262. return Error::kFunctionFailed;
  263. }
  264. g_DxcCreateInstance = reinterpret_cast<DxcCreateInstanceProc>(GetProcAddress(g_dxcLib, "DxcCreateInstance"));
  265. if(g_DxcCreateInstance == nullptr)
  266. {
  267. ANKI_SHADER_COMPILER_LOGE("DxcCreateInstance was not found in the dxcompiler.dll");
  268. return Error::kFunctionFailed;
  269. }
  270. }
  271. }
  272. const Bool isLib = (type >= ShaderType::kFirstRayTracing && type <= ShaderType::kLastRayTracing) || type == ShaderType::kWorkGraph;
  273. ComPtr<IDxcUtils> utils;
  274. ANKI_DXC_CHECK(g_DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&utils)));
  275. ComPtr<ID3D12ShaderReflection> dxRefl;
  276. ComPtr<ID3D12LibraryReflection> libRefl;
  277. ShaderCompilerDynamicArray<ID3D12FunctionReflection*> funcReflections;
  278. D3D12_SHADER_DESC shaderDesc = {};
  279. if(isLib)
  280. {
  281. const DxcBuffer buff = {dxil.getBegin(), dxil.getSizeInBytes(), 0};
  282. ANKI_DXC_CHECK(utils->CreateReflection(&buff, IID_PPV_ARGS(&libRefl)));
  283. D3D12_LIBRARY_DESC libDesc = {};
  284. libRefl->GetDesc(&libDesc);
  285. if(libDesc.FunctionCount == 0)
  286. {
  287. errorMessage.sprintf("Expecting at least 1 in D3D12_LIBRARY_DESC::FunctionCount");
  288. return Error::kUserData;
  289. }
  290. funcReflections.resize(libDesc.FunctionCount);
  291. for(U32 i = 0; i < libDesc.FunctionCount; ++i)
  292. {
  293. funcReflections[i] = libRefl->GetFunctionByIndex(i);
  294. }
  295. }
  296. else
  297. {
  298. const DxcBuffer buff = {dxil.getBegin(), dxil.getSizeInBytes(), 0};
  299. ANKI_DXC_CHECK(utils->CreateReflection(&buff, IID_PPV_ARGS(&dxRefl)));
  300. ANKI_DXC_CHECK(dxRefl->GetDesc(&shaderDesc));
  301. }
  302. for(U32 ifunc = 0; ifunc < ((isLib) ? funcReflections.getSize() : 1); ++ifunc)
  303. {
  304. U32 bindingCount;
  305. if(isLib)
  306. {
  307. D3D12_FUNCTION_DESC funcDesc;
  308. ANKI_DXC_CHECK(funcReflections[ifunc]->GetDesc(&funcDesc));
  309. bindingCount = funcDesc.BoundResources;
  310. }
  311. else
  312. {
  313. bindingCount = shaderDesc.BoundResources;
  314. }
  315. for(U32 i = 0; i < bindingCount; ++i)
  316. {
  317. D3D12_SHADER_INPUT_BIND_DESC bindDesc;
  318. if(isLib)
  319. {
  320. ANKI_DXC_CHECK(funcReflections[ifunc]->GetResourceBindingDesc(i, &bindDesc));
  321. }
  322. else
  323. {
  324. ANKI_DXC_CHECK(dxRefl->GetResourceBindingDesc(i, &bindDesc));
  325. }
  326. ShaderReflectionBinding akBinding;
  327. akBinding.m_type = DescriptorType::kCount;
  328. akBinding.m_arraySize = U16(bindDesc.BindCount);
  329. akBinding.m_registerBindingPoint = bindDesc.BindPoint;
  330. if(bindDesc.Type == D3D_SIT_CBUFFER)
  331. {
  332. // ConstantBuffer
  333. if(bindDesc.Space == ANKI_D3D_FAST_CONSTANTS_SPACE && bindDesc.BindPoint == 0)
  334. {
  335. // It's push/root constants
  336. ID3D12ShaderReflectionConstantBuffer* cbuffer =
  337. (isLib) ? funcReflections[ifunc]->GetConstantBufferByName(bindDesc.Name) : dxRefl->GetConstantBufferByName(bindDesc.Name);
  338. D3D12_SHADER_BUFFER_DESC desc;
  339. ANKI_DXC_CHECK(cbuffer->GetDesc(&desc));
  340. refl.m_descriptor.m_fastConstantsSize = desc.Size;
  341. continue;
  342. }
  343. else if(bindDesc.Space == ANKI_D3D_SHADER_RECORD_CONSTANTS_SPACE && bindDesc.BindPoint == 0)
  344. {
  345. // It's SBT consts
  346. if(!isLib)
  347. {
  348. // Ignore
  349. continue;
  350. }
  351. ID3D12ShaderReflectionConstantBuffer* cbuffer = funcReflections[ifunc]->GetConstantBufferByName(bindDesc.Name);
  352. D3D12_SHADER_BUFFER_DESC desc;
  353. ANKI_DXC_CHECK(cbuffer->GetDesc(&desc));
  354. refl.m_descriptor.m_d3dShaderBindingTableRecordConstantsSize = desc.Size;
  355. continue;
  356. }
  357. else if(bindDesc.Space == ANKI_D3D_DRAW_ID_CONSTANT_SPACE && bindDesc.BindPoint == 0)
  358. {
  359. // It's DrawID
  360. refl.m_descriptor.m_d3dHasDrawId = true;
  361. continue;
  362. }
  363. akBinding.m_type = DescriptorType::kConstantBuffer;
  364. }
  365. else if(bindDesc.Type == D3D_SIT_TEXTURE && bindDesc.Dimension != D3D_SRV_DIMENSION_BUFFER)
  366. {
  367. // Texture2D etc
  368. akBinding.m_type = DescriptorType::kSrvTexture;
  369. }
  370. else if(bindDesc.Type == D3D_SIT_TEXTURE && bindDesc.Dimension == D3D_SRV_DIMENSION_BUFFER)
  371. {
  372. // Buffer
  373. akBinding.m_type = DescriptorType::kSrvTexelBuffer;
  374. }
  375. else if(bindDesc.Type == D3D_SIT_SAMPLER)
  376. {
  377. // SamplerState
  378. akBinding.m_type = DescriptorType::kSampler;
  379. }
  380. else if(bindDesc.Type == D3D_SIT_UAV_RWTYPED && bindDesc.Dimension == D3D_SRV_DIMENSION_BUFFER)
  381. {
  382. // RWBuffer
  383. akBinding.m_type = DescriptorType::kUavTexelBuffer;
  384. }
  385. else if(bindDesc.Type == D3D_SIT_UAV_RWTYPED && bindDesc.Dimension != D3D_SRV_DIMENSION_BUFFER)
  386. {
  387. // RWTexture2D etc
  388. akBinding.m_type = DescriptorType::kUavTexture;
  389. }
  390. else if(bindDesc.Type == D3D_SIT_BYTEADDRESS)
  391. {
  392. // ByteAddressBuffer
  393. akBinding.m_type = DescriptorType::kSrvByteAddressBuffer;
  394. akBinding.m_d3dStructuredBufferStride = sizeof(U32);
  395. }
  396. else if(bindDesc.Type == D3D_SIT_UAV_RWBYTEADDRESS)
  397. {
  398. // RWByteAddressBuffer
  399. akBinding.m_type = DescriptorType::kUavByteAddressBuffer;
  400. akBinding.m_d3dStructuredBufferStride = sizeof(U32);
  401. }
  402. else if(bindDesc.Type == D3D_SIT_RTACCELERATIONSTRUCTURE)
  403. {
  404. // RaytracingAccelerationStructure
  405. akBinding.m_type = DescriptorType::kAccelerationStructure;
  406. }
  407. else if(bindDesc.Type == D3D_SIT_STRUCTURED)
  408. {
  409. // StructuredBuffer
  410. akBinding.m_type = DescriptorType::kSrvStructuredBuffer;
  411. akBinding.m_d3dStructuredBufferStride = U16(bindDesc.NumSamples);
  412. }
  413. else if(bindDesc.Type == D3D_SIT_UAV_RWSTRUCTURED)
  414. {
  415. // RWStructuredBuffer
  416. akBinding.m_type = DescriptorType::kUavStructuredBuffer;
  417. akBinding.m_d3dStructuredBufferStride = U16(bindDesc.NumSamples);
  418. }
  419. else
  420. {
  421. errorMessage.sprintf("Unrecognized type for binding: %s", bindDesc.Name);
  422. return Error::kUserData;
  423. }
  424. Bool skip = false;
  425. if(isLib)
  426. {
  427. // Search if the binding exists because it may repeat
  428. for(U32 i = 0; i < refl.m_descriptor.m_bindingCounts[bindDesc.Space]; ++i)
  429. {
  430. if(refl.m_descriptor.m_bindings[bindDesc.Space][i] == akBinding)
  431. {
  432. skip = true;
  433. break;
  434. }
  435. }
  436. }
  437. if(!skip)
  438. {
  439. refl.m_descriptor.m_bindings[bindDesc.Space][refl.m_descriptor.m_bindingCounts[bindDesc.Space]] = akBinding;
  440. ++refl.m_descriptor.m_bindingCounts[bindDesc.Space];
  441. }
  442. }
  443. }
  444. for(U32 i = 0; i < kMaxRegisterSpaces; ++i)
  445. {
  446. std::sort(refl.m_descriptor.m_bindings[i].getBegin(), refl.m_descriptor.m_bindings[i].getBegin() + refl.m_descriptor.m_bindingCounts[i]);
  447. }
  448. if(type == ShaderType::kVertex)
  449. {
  450. for(U32 i = 0; i < shaderDesc.InputParameters; ++i)
  451. {
  452. D3D12_SIGNATURE_PARAMETER_DESC in;
  453. ANKI_DXC_CHECK(dxRefl->GetInputParameterDesc(i, &in));
  454. VertexAttributeSemantic a = VertexAttributeSemantic::kCount;
  455. # define ANKI_ATTRIB_NAME(x, idx) CString(in.SemanticName) == # x&& in.SemanticIndex == idx
  456. if(ANKI_ATTRIB_NAME(POSITION, 0))
  457. {
  458. a = VertexAttributeSemantic::kPosition;
  459. }
  460. else if(ANKI_ATTRIB_NAME(NORMAL, 0))
  461. {
  462. a = VertexAttributeSemantic::kNormal;
  463. }
  464. else if(ANKI_ATTRIB_NAME(TEXCOORD, 0))
  465. {
  466. a = VertexAttributeSemantic::kTexCoord;
  467. }
  468. else if(ANKI_ATTRIB_NAME(COLOR, 0))
  469. {
  470. a = VertexAttributeSemantic::kColor;
  471. }
  472. else if(ANKI_ATTRIB_NAME(MISC, 0))
  473. {
  474. a = VertexAttributeSemantic::kMisc0;
  475. }
  476. else if(ANKI_ATTRIB_NAME(MISC, 1))
  477. {
  478. a = VertexAttributeSemantic::kMisc1;
  479. }
  480. else if(ANKI_ATTRIB_NAME(MISC, 2))
  481. {
  482. a = VertexAttributeSemantic::kMisc2;
  483. }
  484. else if(ANKI_ATTRIB_NAME(MISC, 3))
  485. {
  486. a = VertexAttributeSemantic::kMisc3;
  487. }
  488. else if(ANKI_ATTRIB_NAME(SV_VERTEXID, 0) || ANKI_ATTRIB_NAME(SV_INSTANCEID, 0))
  489. {
  490. // Ignore
  491. continue;
  492. }
  493. else
  494. {
  495. errorMessage.sprintf("Unexpected attribute name: %s", in.SemanticName);
  496. return Error::kUserData;
  497. }
  498. # undef ANKI_ATTRIB_NAME
  499. refl.m_vertex.m_vertexAttributeMask |= VertexAttributeSemanticBit(1 << a);
  500. refl.m_vertex.m_vkVertexAttributeLocations[a] = U8(i); // Just set something
  501. }
  502. }
  503. if(type == ShaderType::kPixel)
  504. {
  505. for(U32 i = 0; i < shaderDesc.OutputParameters; ++i)
  506. {
  507. D3D12_SIGNATURE_PARAMETER_DESC desc;
  508. ANKI_DXC_CHECK(dxRefl->GetOutputParameterDesc(i, &desc));
  509. if(CString(desc.SemanticName) == "SV_TARGET")
  510. {
  511. refl.m_pixel.m_colorRenderTargetWritemask.set(desc.SemanticIndex);
  512. }
  513. }
  514. }
  515. return Error::kNone;
  516. }
  517. #endif
  518. } // end namespace anki