shaderc_hlsl.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /*
  2. * Copyright 2011-2026 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
  4. */
  5. #include "shaderc.h"
  6. #if SHADERC_CONFIG_HLSL
  7. #if defined(__MINGW32__)
  8. # define __REQUIRED_RPCNDR_H_VERSION__ 475
  9. # define __in
  10. # define __out
  11. #endif // defined(__MINGW32__)
  12. #define COM_NO_WINDOWS_H
  13. #include <d3dcompiler.h>
  14. #include <d3d11shader.h>
  15. #include <bx/os.h>
  16. #ifndef D3D_SVF_USED
  17. # define D3D_SVF_USED 2
  18. #endif // D3D_SVF_USED
  19. namespace bgfx { namespace hlsl
  20. {
  21. typedef HRESULT(WINAPI* PFN_D3D_COMPILE)(_In_reads_bytes_(SrcDataSize) LPCVOID pSrcData
  22. , _In_ SIZE_T SrcDataSize
  23. , _In_opt_ LPCSTR pSourceName
  24. , _In_reads_opt_(_Inexpressible_(pDefines->Name != NULL) ) CONST D3D_SHADER_MACRO* pDefines
  25. , _In_opt_ ID3DInclude* pInclude
  26. , _In_opt_ LPCSTR pEntrypoint
  27. , _In_ LPCSTR pTarget
  28. , _In_ UINT Flags1
  29. , _In_ UINT Flags2
  30. , _Out_ ID3DBlob** ppCode
  31. , _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorMsgs
  32. );
  33. typedef HRESULT(WINAPI* PFN_D3D_DISASSEMBLE)(_In_reads_bytes_(SrcDataSize) LPCVOID pSrcData
  34. , _In_ SIZE_T SrcDataSize
  35. , _In_ UINT Flags
  36. , _In_opt_ LPCSTR szComments
  37. , _Out_ ID3DBlob** ppDisassembly
  38. );
  39. typedef HRESULT(WINAPI* PFN_D3D_REFLECT)(_In_reads_bytes_(SrcDataSize) LPCVOID pSrcData
  40. , _In_ SIZE_T SrcDataSize
  41. , _In_ REFIID pInterface
  42. , _Out_ void** ppReflector
  43. );
  44. typedef HRESULT(WINAPI* PFN_D3D_STRIP_SHADER)(_In_reads_bytes_(BytecodeLength) LPCVOID pShaderBytecode
  45. , _In_ SIZE_T BytecodeLength
  46. , _In_ UINT uStripFlags
  47. , _Out_ ID3DBlob** ppStrippedBlob
  48. );
  49. PFN_D3D_COMPILE D3DCompile;
  50. PFN_D3D_DISASSEMBLE D3DDisassemble;
  51. PFN_D3D_REFLECT D3DReflect;
  52. PFN_D3D_STRIP_SHADER D3DStripShader;
  53. struct D3DCompiler
  54. {
  55. const char* fileName;
  56. const GUID IID_ID3D11ShaderReflection;
  57. };
  58. static const D3DCompiler s_d3dcompiler[] =
  59. { // BK - the only different method in interface is GetRequiresFlags at the end
  60. // of IID_ID3D11ShaderReflection47 (which is not used anyway).
  61. { "D3DCompiler_47.dll", { 0x8d536ca1, 0x0cca, 0x4956, { 0xa8, 0x37, 0x78, 0x69, 0x63, 0x75, 0x55, 0x84 } } },
  62. { "D3DCompiler_46.dll", { 0x0a233719, 0x3960, 0x4578, { 0x9d, 0x7c, 0x20, 0x3b, 0x8b, 0x1d, 0x9c, 0xc1 } } },
  63. { "D3DCompiler_45.dll", { 0x0a233719, 0x3960, 0x4578, { 0x9d, 0x7c, 0x20, 0x3b, 0x8b, 0x1d, 0x9c, 0xc1 } } },
  64. { "D3DCompiler_44.dll", { 0x0a233719, 0x3960, 0x4578, { 0x9d, 0x7c, 0x20, 0x3b, 0x8b, 0x1d, 0x9c, 0xc1 } } },
  65. { "D3DCompiler_43.dll", { 0x0a233719, 0x3960, 0x4578, { 0x9d, 0x7c, 0x20, 0x3b, 0x8b, 0x1d, 0x9c, 0xc1 } } },
  66. };
  67. static const D3DCompiler* s_compiler = NULL;
  68. static void* s_d3dcompilerdll = NULL;
  69. const D3DCompiler* load(bx::WriterI* _messageWriter)
  70. {
  71. if (NULL != s_d3dcompilerdll)
  72. {
  73. return s_compiler;
  74. }
  75. bx::Error messageErr;
  76. for (uint32_t ii = 0; ii < BX_COUNTOF(s_d3dcompiler); ++ii)
  77. {
  78. const D3DCompiler* compiler = &s_d3dcompiler[ii];
  79. s_d3dcompilerdll = bx::dlopen(compiler->fileName);
  80. if (NULL == s_d3dcompilerdll)
  81. {
  82. continue;
  83. }
  84. D3DCompile = (PFN_D3D_COMPILE )bx::dlsym(s_d3dcompilerdll, "D3DCompile");
  85. D3DDisassemble = (PFN_D3D_DISASSEMBLE )bx::dlsym(s_d3dcompilerdll, "D3DDisassemble");
  86. D3DReflect = (PFN_D3D_REFLECT )bx::dlsym(s_d3dcompilerdll, "D3DReflect");
  87. D3DStripShader = (PFN_D3D_STRIP_SHADER)bx::dlsym(s_d3dcompilerdll, "D3DStripShader");
  88. if (NULL == D3DCompile
  89. || NULL == D3DDisassemble
  90. || NULL == D3DReflect
  91. || NULL == D3DStripShader)
  92. {
  93. bx::dlclose(s_d3dcompilerdll);
  94. continue;
  95. }
  96. if (g_verbose)
  97. {
  98. char filePath[bx::kMaxFilePath];
  99. GetModuleFileNameA( (HMODULE)s_d3dcompilerdll, filePath, sizeof(filePath) );
  100. BX_TRACE("Loaded %s compiler (%s).", compiler->fileName, filePath);
  101. }
  102. return compiler;
  103. }
  104. bx::write(_messageWriter, &messageErr, "Error: Unable to open D3DCompiler_*.dll shader compiler.\n");
  105. return NULL;
  106. }
  107. void unload()
  108. {
  109. if (NULL != s_d3dcompilerdll)
  110. {
  111. bx::dlclose(s_d3dcompilerdll);
  112. s_d3dcompilerdll = NULL;
  113. }
  114. s_compiler = NULL;
  115. D3DCompile = NULL;
  116. D3DDisassemble = NULL;
  117. D3DReflect = NULL;
  118. D3DStripShader = NULL;
  119. }
  120. struct RemapInputSemantic
  121. {
  122. bgfx::Attrib::Enum m_attr;
  123. const char* m_name;
  124. uint8_t m_index;
  125. };
  126. static const RemapInputSemantic s_remapInputSemantic[bgfx::Attrib::Count + 1] =
  127. {
  128. { bgfx::Attrib::Position, "POSITION", 0 },
  129. { bgfx::Attrib::Normal, "NORMAL", 0 },
  130. { bgfx::Attrib::Tangent, "TANGENT", 0 },
  131. { bgfx::Attrib::Bitangent, "BITANGENT", 0 },
  132. { bgfx::Attrib::Color0, "COLOR", 0 },
  133. { bgfx::Attrib::Color1, "COLOR", 1 },
  134. { bgfx::Attrib::Color2, "COLOR", 2 },
  135. { bgfx::Attrib::Color3, "COLOR", 3 },
  136. { bgfx::Attrib::Indices, "BLENDINDICES", 0 },
  137. { bgfx::Attrib::Weight, "BLENDWEIGHT", 0 },
  138. { bgfx::Attrib::TexCoord0, "TEXCOORD", 0 },
  139. { bgfx::Attrib::TexCoord1, "TEXCOORD", 1 },
  140. { bgfx::Attrib::TexCoord2, "TEXCOORD", 2 },
  141. { bgfx::Attrib::TexCoord3, "TEXCOORD", 3 },
  142. { bgfx::Attrib::TexCoord4, "TEXCOORD", 4 },
  143. { bgfx::Attrib::TexCoord5, "TEXCOORD", 5 },
  144. { bgfx::Attrib::TexCoord6, "TEXCOORD", 6 },
  145. { bgfx::Attrib::TexCoord7, "TEXCOORD", 7 },
  146. { bgfx::Attrib::Count, "", 0 },
  147. };
  148. const RemapInputSemantic& findInputSemantic(const char* _name, uint8_t _index)
  149. {
  150. for (uint32_t ii = 0; ii < bgfx::Attrib::Count; ++ii)
  151. {
  152. const RemapInputSemantic& ris = s_remapInputSemantic[ii];
  153. if (0 == bx::strCmp(ris.m_name, _name)
  154. && ris.m_index == _index)
  155. {
  156. return ris;
  157. }
  158. }
  159. return s_remapInputSemantic[bgfx::Attrib::Count];
  160. }
  161. struct UniformRemap
  162. {
  163. UniformType::Enum id;
  164. D3D_SHADER_VARIABLE_CLASS paramClass;
  165. D3D_SHADER_VARIABLE_TYPE paramType;
  166. uint8_t columns;
  167. uint8_t rows;
  168. };
  169. static const UniformRemap s_uniformRemap[] =
  170. {
  171. { UniformType::Sampler, D3D_SVC_SCALAR, D3D_SVT_INT, 0, 0 },
  172. { UniformType::Vec4, D3D_SVC_VECTOR, D3D_SVT_FLOAT, 0, 0 },
  173. { UniformType::Mat3, D3D_SVC_MATRIX_COLUMNS, D3D_SVT_FLOAT, 3, 3 },
  174. { UniformType::Mat4, D3D_SVC_MATRIX_COLUMNS, D3D_SVT_FLOAT, 4, 4 },
  175. { UniformType::Sampler, D3D_SVC_OBJECT, D3D_SVT_SAMPLER, 0, 0 },
  176. { UniformType::Sampler, D3D_SVC_OBJECT, D3D_SVT_SAMPLER2D, 0, 0 },
  177. { UniformType::Sampler, D3D_SVC_OBJECT, D3D_SVT_SAMPLER3D, 0, 0 },
  178. { UniformType::Sampler, D3D_SVC_OBJECT, D3D_SVT_SAMPLERCUBE, 0, 0 },
  179. };
  180. UniformType::Enum findUniformType(const D3D11_SHADER_TYPE_DESC& constDesc)
  181. {
  182. for (uint32_t ii = 0; ii < BX_COUNTOF(s_uniformRemap); ++ii)
  183. {
  184. const UniformRemap& remap = s_uniformRemap[ii];
  185. if (remap.paramClass == constDesc.Class
  186. && remap.paramType == constDesc.Type)
  187. {
  188. if (D3D_SVC_MATRIX_COLUMNS != constDesc.Class)
  189. {
  190. return remap.id;
  191. }
  192. if (remap.columns == constDesc.Columns
  193. && remap.rows == constDesc.Rows)
  194. {
  195. return remap.id;
  196. }
  197. }
  198. }
  199. return UniformType::Count;
  200. }
  201. static uint32_t s_optimizationLevelD3D11[] =
  202. {
  203. D3DCOMPILE_OPTIMIZATION_LEVEL0,
  204. D3DCOMPILE_OPTIMIZATION_LEVEL1,
  205. D3DCOMPILE_OPTIMIZATION_LEVEL2,
  206. D3DCOMPILE_OPTIMIZATION_LEVEL3,
  207. };
  208. typedef std::vector<std::string> UniformNameList;
  209. bool getReflectionDataD3D11(ID3DBlob* _code, bool _vshader, UniformArray& _uniforms, uint8_t& _numAttrs, uint16_t* _attrs, uint16_t& _size, UniformNameList& unusedUniforms, bx::WriterI* _messageWriter)
  210. {
  211. bx::Error messageErr;
  212. ID3D11ShaderReflection* reflect = NULL;
  213. HRESULT hr = D3DReflect(_code->GetBufferPointer()
  214. , _code->GetBufferSize()
  215. , s_compiler->IID_ID3D11ShaderReflection
  216. , (void**)&reflect
  217. );
  218. if (FAILED(hr) )
  219. {
  220. bx::write(_messageWriter, &messageErr, "Error: D3DReflect failed 0x%08x\n", (uint32_t)hr);
  221. return false;
  222. }
  223. D3D11_SHADER_DESC desc;
  224. hr = reflect->GetDesc(&desc);
  225. if (FAILED(hr) )
  226. {
  227. bx::write(_messageWriter, &messageErr, "Error: ID3D11ShaderReflection::GetDesc failed 0x%08x\n", (uint32_t)hr);
  228. return false;
  229. }
  230. BX_TRACE("Creator: %s 0x%08x", desc.Creator, desc.Version);
  231. BX_TRACE("Num constant buffers: %d", desc.ConstantBuffers);
  232. BX_TRACE("Input:");
  233. if (_vshader) // Only care about input semantic on vertex shaders
  234. {
  235. for (uint32_t ii = 0; ii < desc.InputParameters; ++ii)
  236. {
  237. D3D11_SIGNATURE_PARAMETER_DESC spd;
  238. reflect->GetInputParameterDesc(ii, &spd);
  239. BX_TRACE("\t%2d: %s%d, vt %d, ct %d, mask %x, reg %d"
  240. , ii
  241. , spd.SemanticName
  242. , spd.SemanticIndex
  243. , spd.SystemValueType
  244. , spd.ComponentType
  245. , spd.Mask
  246. , spd.Register
  247. );
  248. const RemapInputSemantic& ris = findInputSemantic(spd.SemanticName, uint8_t(spd.SemanticIndex) );
  249. if (ris.m_attr != bgfx::Attrib::Count)
  250. {
  251. _attrs[_numAttrs] = bgfx::attribToId(ris.m_attr);
  252. ++_numAttrs;
  253. }
  254. }
  255. }
  256. BX_TRACE("Output:");
  257. for (uint32_t ii = 0; ii < desc.OutputParameters; ++ii)
  258. {
  259. D3D11_SIGNATURE_PARAMETER_DESC spd;
  260. reflect->GetOutputParameterDesc(ii, &spd);
  261. BX_TRACE("\t%2d: %s%d, %d, %d", ii, spd.SemanticName, spd.SemanticIndex, spd.SystemValueType, spd.ComponentType);
  262. }
  263. for (uint32_t ii = 0, num = bx::uint32_min(1, desc.ConstantBuffers); ii < num; ++ii)
  264. {
  265. ID3D11ShaderReflectionConstantBuffer* cbuffer = reflect->GetConstantBufferByIndex(ii);
  266. D3D11_SHADER_BUFFER_DESC bufferDesc;
  267. hr = cbuffer->GetDesc(&bufferDesc);
  268. _size = (uint16_t)bufferDesc.Size;
  269. if (SUCCEEDED(hr) )
  270. {
  271. BX_TRACE("%s, %d, vars %d, size %d"
  272. , bufferDesc.Name
  273. , bufferDesc.Type
  274. , bufferDesc.Variables
  275. , bufferDesc.Size
  276. );
  277. for (uint32_t jj = 0; jj < bufferDesc.Variables; ++jj)
  278. {
  279. ID3D11ShaderReflectionVariable* var = cbuffer->GetVariableByIndex(jj);
  280. ID3D11ShaderReflectionType* type = var->GetType();
  281. D3D11_SHADER_VARIABLE_DESC varDesc;
  282. hr = var->GetDesc(&varDesc);
  283. if (SUCCEEDED(hr) )
  284. {
  285. D3D11_SHADER_TYPE_DESC constDesc;
  286. hr = type->GetDesc(&constDesc);
  287. if (SUCCEEDED(hr) )
  288. {
  289. UniformType::Enum uniformType = findUniformType(constDesc);
  290. if (UniformType::Count != uniformType
  291. && 0 != (varDesc.uFlags & D3D_SVF_USED) )
  292. {
  293. Uniform un;
  294. un.name = varDesc.Name;
  295. un.type = uniformType;
  296. un.num = uint8_t(constDesc.Elements);
  297. un.regIndex = uint16_t(varDesc.StartOffset);
  298. un.regCount = uint16_t(bx::alignUp(varDesc.Size, 16) / 16);
  299. _uniforms.push_back(un);
  300. BX_TRACE("\t%s, %d, size %d, flags 0x%08x, %d (used)"
  301. , varDesc.Name
  302. , varDesc.StartOffset
  303. , varDesc.Size
  304. , varDesc.uFlags
  305. , uniformType
  306. );
  307. }
  308. else
  309. {
  310. if (0 == (varDesc.uFlags & D3D_SVF_USED) )
  311. {
  312. unusedUniforms.push_back(varDesc.Name);
  313. }
  314. BX_TRACE("\t%s, unknown type", varDesc.Name);
  315. }
  316. }
  317. }
  318. }
  319. }
  320. }
  321. BX_TRACE("Bound:");
  322. for (uint32_t ii = 0; ii < desc.BoundResources; ++ii)
  323. {
  324. D3D11_SHADER_INPUT_BIND_DESC bindDesc;
  325. hr = reflect->GetResourceBindingDesc(ii, &bindDesc);
  326. if (SUCCEEDED(hr) )
  327. {
  328. if (D3D_SIT_SAMPLER == bindDesc.Type)
  329. {
  330. BX_TRACE("\t%s, %d, %d, %d"
  331. , bindDesc.Name
  332. , bindDesc.Type
  333. , bindDesc.BindPoint
  334. , bindDesc.BindCount
  335. );
  336. bx::StringView end = bx::strFind(bindDesc.Name, "Sampler");
  337. if (!end.isEmpty() )
  338. {
  339. Uniform un;
  340. un.name.assign(bindDesc.Name, (end.getPtr() - bindDesc.Name) );
  341. un.type = UniformType::Enum(kUniformSamplerBit | UniformType::Sampler);
  342. un.num = 1;
  343. un.regIndex = uint16_t(bindDesc.BindPoint);
  344. un.regCount = uint16_t(bindDesc.BindCount);
  345. _uniforms.push_back(un);
  346. }
  347. }
  348. }
  349. }
  350. if (NULL != reflect)
  351. {
  352. reflect->Release();
  353. }
  354. return true;
  355. }
  356. static bool compile(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _shaderWriter, bx::WriterI* _messageWriter, bool _firstPass)
  357. {
  358. bx::Error messageErr;
  359. const char* profile = _options.profile.c_str();
  360. if (profile[0] == '\0')
  361. {
  362. bx::write(_messageWriter, &messageErr, "Error: Shader profile must be specified.\n");
  363. return false;
  364. }
  365. char profileAndType[8] = {};
  366. profileAndType[0] = (_options.shaderType == 'f') ? 'p' : _options.shaderType;
  367. bx::strCat(profileAndType, BX_COUNTOF(profileAndType), profile);
  368. s_compiler = load(_messageWriter);
  369. bool result = false;
  370. bool debug = _options.debugInformation;
  371. uint32_t flags = D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
  372. flags |= debug ? D3DCOMPILE_DEBUG : 0;
  373. flags |= _options.avoidFlowControl ? D3DCOMPILE_AVOID_FLOW_CONTROL : 0;
  374. flags |= _options.noPreshader ? D3DCOMPILE_NO_PRESHADER : 0;
  375. flags |= _options.partialPrecision ? D3DCOMPILE_PARTIAL_PRECISION : 0;
  376. flags |= _options.preferFlowControl ? D3DCOMPILE_PREFER_FLOW_CONTROL : 0;
  377. flags |= _options.backwardsCompatibility ? D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY : 0;
  378. bool werror = _options.warningsAreErrors;
  379. if (werror)
  380. {
  381. flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;
  382. }
  383. if (_options.optimize )
  384. {
  385. const uint32_t optimization = bx::uint32_min(_options.optimizationLevel, BX_COUNTOF(s_optimizationLevelD3D11) - 1);
  386. flags |= s_optimizationLevelD3D11[optimization];
  387. }
  388. else
  389. {
  390. flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
  391. }
  392. BX_TRACE("Profile: %s", profile);
  393. BX_TRACE("Flags: 0x%08x", flags);
  394. ID3DBlob* code;
  395. ID3DBlob* errorMsg;
  396. // Output preprocessed shader so that HLSL can be debugged via GPA
  397. // or PIX. Compiling through memory won't embed preprocessed shader
  398. // file path.
  399. std::string hlslfp;
  400. if (debug)
  401. {
  402. hlslfp = _options.outputFilePath + ".hlsl";
  403. writeFile(hlslfp.c_str(), _code.c_str(), (int32_t)_code.size() );
  404. }
  405. bx::ErrorAssert err;
  406. HRESULT hr = D3DCompile(_code.c_str()
  407. , _code.size()
  408. , hlslfp.c_str()
  409. , NULL
  410. , NULL
  411. , "main"
  412. , profileAndType
  413. , flags
  414. , 0
  415. , &code
  416. , &errorMsg
  417. );
  418. if (FAILED(hr)
  419. || (werror && NULL != errorMsg) )
  420. {
  421. const char* log = (char*)errorMsg->GetBufferPointer();
  422. int32_t line = 0;
  423. int32_t column = 0;
  424. int32_t start = 0;
  425. int32_t end = INT32_MAX;
  426. if (!hlslfp.empty())
  427. {
  428. bx::StringView logfp = bx::strFind(log, hlslfp.c_str() );
  429. if (!logfp.isEmpty() )
  430. {
  431. log = logfp.getPtr() + hlslfp.length();
  432. }
  433. }
  434. bool found = false
  435. || 2 == sscanf(log, "(%u,%u", &line, &column)
  436. || 2 == sscanf(log, " :%u:%u: ", &line, &column)
  437. ;
  438. if (found
  439. && 0 != line)
  440. {
  441. start = bx::uint32_imax(1, line - 10);
  442. end = start + 20;
  443. }
  444. printCode(_code.c_str(), line, start, end, column);
  445. bx::write(_messageWriter, &messageErr, "Error: D3DCompile failed 0x%08x %s\n", (uint32_t)hr, log);
  446. errorMsg->Release();
  447. return false;
  448. }
  449. UniformArray uniforms;
  450. uint8_t numAttrs = 0;
  451. uint16_t attrs[bgfx::Attrib::Count];
  452. uint16_t size = 0;
  453. {
  454. UniformNameList unusedUniforms;
  455. if (!getReflectionDataD3D11(code, profileAndType[0] == 'v', uniforms, numAttrs, attrs, size, unusedUniforms, _messageWriter) )
  456. {
  457. bx::write(_messageWriter, &messageErr, "Error: Unable to get D3D11 reflection data.\n");
  458. goto error;
  459. }
  460. if (_firstPass
  461. && unusedUniforms.size() > 0)
  462. {
  463. // first time through, we just find unused uniforms and get rid of them
  464. std::string output;
  465. bx::LineReader reader(_code.c_str() );
  466. while (!reader.isDone() )
  467. {
  468. bx::StringView strLine = reader.next();
  469. bool found = false;
  470. for (UniformNameList::iterator it = unusedUniforms.begin(), itEnd = unusedUniforms.end(); it != itEnd; ++it)
  471. {
  472. bx::StringView str = strFind(strLine, "uniform ");
  473. if (str.isEmpty() )
  474. {
  475. continue;
  476. }
  477. // matching lines like: uniform u_name;
  478. // we want to replace "uniform" with "static" so that it's no longer
  479. // included in the uniform blob that the application must upload
  480. // we can't just remove them, because unused functions might still reference
  481. // them and cause a compile error when they're gone
  482. if (!bx::findIdentifierMatch(strLine, it->c_str() ).isEmpty() )
  483. {
  484. output.append(strLine.getPtr(), str.getPtr() );
  485. output += "static ";
  486. output.append(str.getTerm(), strLine.getTerm() );
  487. output += "\n";
  488. found = true;
  489. unusedUniforms.erase(it);
  490. break;
  491. }
  492. }
  493. if (!found)
  494. {
  495. output.append(strLine.getPtr(), strLine.getTerm() );
  496. output += "\n";
  497. }
  498. }
  499. // recompile with the unused uniforms converted to statics
  500. return compile(_options, _version, output.c_str(), _shaderWriter, _messageWriter, false);
  501. }
  502. }
  503. {
  504. uint16_t count = (uint16_t)uniforms.size();
  505. bx::write(_shaderWriter, count, &err);
  506. uint32_t fragmentBit = profileAndType[0] == 'p' ? kUniformFragmentBit : 0;
  507. for (UniformArray::const_iterator it = uniforms.begin(); it != uniforms.end(); ++it)
  508. {
  509. const Uniform& un = *it;
  510. uint8_t nameSize = (uint8_t)un.name.size();
  511. bx::write(_shaderWriter, nameSize, &err);
  512. bx::write(_shaderWriter, un.name.c_str(), nameSize, &err);
  513. uint8_t type = uint8_t(un.type | fragmentBit);
  514. bx::write(_shaderWriter, type, &err);
  515. bx::write(_shaderWriter, un.num, &err);
  516. bx::write(_shaderWriter, un.regIndex, &err);
  517. bx::write(_shaderWriter, un.regCount, &err);
  518. bx::write(_shaderWriter, un.texComponent, &err);
  519. bx::write(_shaderWriter, un.texDimension, &err);
  520. bx::write(_shaderWriter, un.texFormat, &err);
  521. BX_TRACE("%s, %s, %d, %d, %d"
  522. , un.name.c_str()
  523. , getUniformTypeName(UniformType::Enum(un.type & ~kUniformMask))
  524. , un.num
  525. , un.regIndex
  526. , un.regCount
  527. );
  528. }
  529. }
  530. {
  531. ID3DBlob* stripped;
  532. hr = D3DStripShader(code->GetBufferPointer()
  533. , code->GetBufferSize()
  534. , D3DCOMPILER_STRIP_REFLECTION_DATA
  535. | D3DCOMPILER_STRIP_TEST_BLOBS
  536. , &stripped
  537. );
  538. if (SUCCEEDED(hr) )
  539. {
  540. code->Release();
  541. code = stripped;
  542. }
  543. }
  544. {
  545. uint32_t shaderSize = uint32_t(code->GetBufferSize() );
  546. bx::write(_shaderWriter, shaderSize, &err);
  547. bx::write(_shaderWriter, code->GetBufferPointer(), shaderSize, &err);
  548. uint8_t nul = 0;
  549. bx::write(_shaderWriter, nul, &err);
  550. }
  551. if (_version >= 400)
  552. {
  553. bx::write(_shaderWriter, numAttrs, &err);
  554. bx::write(_shaderWriter, attrs, numAttrs*sizeof(uint16_t), &err);
  555. bx::write(_shaderWriter, size, &err);
  556. }
  557. if (_options.disasm)
  558. {
  559. ID3DBlob* disasm;
  560. D3DDisassemble(code->GetBufferPointer()
  561. , code->GetBufferSize()
  562. , 0
  563. , NULL
  564. , &disasm
  565. );
  566. if (NULL != disasm)
  567. {
  568. std::string disasmfp = _options.outputFilePath + ".disasm";
  569. writeFile(disasmfp.c_str(), disasm->GetBufferPointer(), (uint32_t)disasm->GetBufferSize() );
  570. disasm->Release();
  571. }
  572. }
  573. if (NULL != errorMsg)
  574. {
  575. errorMsg->Release();
  576. }
  577. result = true;
  578. error:
  579. code->Release();
  580. unload();
  581. return result;
  582. }
  583. } // namespace hlsl
  584. bool compileHLSLShader(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _shaderWriter, bx::WriterI* _messageWriter)
  585. {
  586. return hlsl::compile(_options, _version, _code, _shaderWriter, _messageWriter, true);
  587. }
  588. } // namespace bgfx
  589. #else
  590. namespace bgfx
  591. {
  592. bool compileHLSLShader(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _shaderWriter, bx::WriterI* _messageWriter)
  593. {
  594. BX_UNUSED(_options, _version, _code, _shaderWriter);
  595. bx::Error messageErr;
  596. bx::write(_messageWriter, &messageErr, "HLSL compiler is not supported on this platform.\n");
  597. return false;
  598. }
  599. } // namespace bgfx
  600. #endif // SHADERC_CONFIG_HLSL