shaderc_hlsl.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. /*
  2. * Copyright 2011-2016 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "shaderc.h"
  6. #if SHADERC_CONFIG_HLSL
  7. //#define __REQUIRED_RPCNDR_H_VERSION__ 475
  8. //#define __in
  9. //#define __out
  10. #include <d3dcompiler.h>
  11. #include <d3d11shader.h>
  12. #include <bx/os.h>
  13. #ifndef D3D_SVF_USED
  14. # define D3D_SVF_USED 2
  15. #endif // D3D_SVF_USED
  16. namespace bgfx
  17. {
  18. static const GUID IID_ID3D11ShaderReflection = { 0x6e6ffa6a, 0x9bae, 0x4613, { 0xa5, 0x1e, 0x91, 0x65, 0x2d, 0x50, 0x8c, 0x21 } };
  19. typedef HRESULT(WINAPI* PFN_D3D_COMPILE)(_In_reads_bytes_(SrcDataSize) LPCVOID pSrcData
  20. , _In_ SIZE_T SrcDataSize
  21. , _In_opt_ LPCSTR pSourceName
  22. , _In_reads_opt_(_Inexpressible_(pDefines->Name != NULL) ) CONST D3D_SHADER_MACRO* pDefines
  23. , _In_opt_ ID3DInclude* pInclude
  24. , _In_opt_ LPCSTR pEntrypoint
  25. , _In_ LPCSTR pTarget
  26. , _In_ UINT Flags1
  27. , _In_ UINT Flags2
  28. , _Out_ ID3DBlob** ppCode
  29. , _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorMsgs
  30. );
  31. typedef HRESULT(WINAPI* PFN_D3D_DISASSEMBLE)(_In_reads_bytes_(SrcDataSize) LPCVOID pSrcData
  32. , _In_ SIZE_T SrcDataSize
  33. , _In_ UINT Flags
  34. , _In_opt_ LPCSTR szComments
  35. , _Out_ ID3DBlob** ppDisassembly
  36. );
  37. typedef HRESULT(WINAPI* PFN_D3D_REFLECT)(_In_reads_bytes_(SrcDataSize) LPCVOID pSrcData
  38. , _In_ SIZE_T SrcDataSize
  39. , _In_ REFIID pInterface
  40. , _Out_ void** ppReflector
  41. );
  42. typedef HRESULT(WINAPI* PFN_D3D_STRIP_SHADER)(_In_reads_bytes_(BytecodeLength) LPCVOID pShaderBytecode
  43. , _In_ SIZE_T BytecodeLength
  44. , _In_ UINT uStripFlags
  45. , _Out_ ID3DBlob** ppStrippedBlob
  46. );
  47. PFN_D3D_COMPILE D3DCompile;
  48. PFN_D3D_DISASSEMBLE D3DDisassemble;
  49. PFN_D3D_REFLECT D3DReflect;
  50. PFN_D3D_STRIP_SHADER D3DStripShader;
  51. struct CTHeader
  52. {
  53. uint32_t Size;
  54. uint32_t Creator;
  55. uint32_t Version;
  56. uint32_t Constants;
  57. uint32_t ConstantInfo;
  58. uint32_t Flags;
  59. uint32_t Target;
  60. };
  61. struct CTInfo
  62. {
  63. uint32_t Name;
  64. uint16_t RegisterSet;
  65. uint16_t RegisterIndex;
  66. uint16_t RegisterCount;
  67. uint16_t Reserved;
  68. uint32_t TypeInfo;
  69. uint32_t DefaultValue;
  70. };
  71. struct CTType
  72. {
  73. uint16_t Class;
  74. uint16_t Type;
  75. uint16_t Rows;
  76. uint16_t Columns;
  77. uint16_t Elements;
  78. uint16_t StructMembers;
  79. uint32_t StructMemberInfo;
  80. };
  81. struct RemapInputSemantic
  82. {
  83. bgfx::Attrib::Enum m_attr;
  84. const char* m_name;
  85. uint8_t m_index;
  86. };
  87. static const RemapInputSemantic s_remapInputSemantic[bgfx::Attrib::Count + 1] =
  88. {
  89. { bgfx::Attrib::Position, "POSITION", 0 },
  90. { bgfx::Attrib::Normal, "NORMAL", 0 },
  91. { bgfx::Attrib::Tangent, "TANGENT", 0 },
  92. { bgfx::Attrib::Bitangent, "BITANGENT", 0 },
  93. { bgfx::Attrib::Color0, "COLOR", 0 },
  94. { bgfx::Attrib::Color1, "COLOR", 1 },
  95. { bgfx::Attrib::Indices, "BLENDINDICES", 0 },
  96. { bgfx::Attrib::Weight, "BLENDWEIGHT", 0 },
  97. { bgfx::Attrib::TexCoord0, "TEXCOORD", 0 },
  98. { bgfx::Attrib::TexCoord1, "TEXCOORD", 1 },
  99. { bgfx::Attrib::TexCoord2, "TEXCOORD", 2 },
  100. { bgfx::Attrib::TexCoord3, "TEXCOORD", 3 },
  101. { bgfx::Attrib::TexCoord4, "TEXCOORD", 4 },
  102. { bgfx::Attrib::TexCoord5, "TEXCOORD", 5 },
  103. { bgfx::Attrib::TexCoord6, "TEXCOORD", 6 },
  104. { bgfx::Attrib::TexCoord7, "TEXCOORD", 7 },
  105. { bgfx::Attrib::Count, "", 0 },
  106. };
  107. const RemapInputSemantic& findInputSemantic(const char* _name, uint8_t _index)
  108. {
  109. for (uint32_t ii = 0; ii < bgfx::Attrib::Count; ++ii)
  110. {
  111. const RemapInputSemantic& ris = s_remapInputSemantic[ii];
  112. if (0 == strcmp(ris.m_name, _name)
  113. && ris.m_index == _index)
  114. {
  115. return ris;
  116. }
  117. }
  118. return s_remapInputSemantic[bgfx::Attrib::Count];
  119. }
  120. struct UniformRemap
  121. {
  122. UniformType::Enum id;
  123. D3D_SHADER_VARIABLE_CLASS paramClass;
  124. D3D_SHADER_VARIABLE_TYPE paramType;
  125. uint8_t columns;
  126. uint8_t rows;
  127. };
  128. static const UniformRemap s_uniformRemap[] =
  129. {
  130. { UniformType::Int1, D3D_SVC_SCALAR, D3D_SVT_INT, 0, 0 },
  131. { UniformType::Vec4, D3D_SVC_VECTOR, D3D_SVT_FLOAT, 0, 0 },
  132. { UniformType::Mat3, D3D_SVC_MATRIX_COLUMNS, D3D_SVT_FLOAT, 3, 3 },
  133. { UniformType::Mat4, D3D_SVC_MATRIX_COLUMNS, D3D_SVT_FLOAT, 4, 4 },
  134. { UniformType::Int1, D3D_SVC_OBJECT, D3D_SVT_SAMPLER, 0, 0 },
  135. { UniformType::Int1, D3D_SVC_OBJECT, D3D_SVT_SAMPLER2D, 0, 0 },
  136. { UniformType::Int1, D3D_SVC_OBJECT, D3D_SVT_SAMPLER3D, 0, 0 },
  137. { UniformType::Int1, D3D_SVC_OBJECT, D3D_SVT_SAMPLERCUBE, 0, 0 },
  138. };
  139. UniformType::Enum findUniformType(const D3D11_SHADER_TYPE_DESC& constDesc)
  140. {
  141. for (uint32_t ii = 0; ii < BX_COUNTOF(s_uniformRemap); ++ii)
  142. {
  143. const UniformRemap& remap = s_uniformRemap[ii];
  144. if (remap.paramClass == constDesc.Class
  145. && remap.paramType == constDesc.Type)
  146. {
  147. if (D3D_SVC_MATRIX_COLUMNS != constDesc.Class)
  148. {
  149. return remap.id;
  150. }
  151. if (remap.columns == constDesc.Columns
  152. && remap.rows == constDesc.Rows)
  153. {
  154. return remap.id;
  155. }
  156. }
  157. }
  158. return UniformType::Count;
  159. }
  160. static uint32_t s_optimizationLevelD3D11[4] =
  161. {
  162. D3DCOMPILE_OPTIMIZATION_LEVEL0,
  163. D3DCOMPILE_OPTIMIZATION_LEVEL1,
  164. D3DCOMPILE_OPTIMIZATION_LEVEL2,
  165. D3DCOMPILE_OPTIMIZATION_LEVEL3,
  166. };
  167. typedef std::vector<std::string> UniformNameList;
  168. static bool isSampler(D3D_SHADER_VARIABLE_TYPE _svt)
  169. {
  170. switch (_svt)
  171. {
  172. case D3D_SVT_SAMPLER:
  173. case D3D_SVT_SAMPLER1D:
  174. case D3D_SVT_SAMPLER2D:
  175. case D3D_SVT_SAMPLER3D:
  176. case D3D_SVT_SAMPLERCUBE:
  177. return true;
  178. default:
  179. break;
  180. }
  181. return false;
  182. }
  183. bool getReflectionDataD3D9(ID3DBlob* _code, UniformArray& _uniforms)
  184. {
  185. // see reference for magic values: https://msdn.microsoft.com/en-us/library/ff552891(VS.85).aspx
  186. const uint32_t D3DSIO_COMMENT = 0x0000FFFE;
  187. const uint32_t D3DSIO_END = 0x0000FFFF;
  188. const uint32_t D3DSI_OPCODE_MASK = 0x0000FFFF;
  189. const uint32_t D3DSI_COMMENTSIZE_MASK = 0x7FFF0000;
  190. const uint32_t CTAB_CONSTANT = MAKEFOURCC('C', 'T', 'A', 'B');
  191. // parse the shader blob for the constant table
  192. const size_t codeSize = _code->GetBufferSize();
  193. const uint32_t* ptr = (const uint32_t*)_code->GetBufferPointer();
  194. const uint32_t* end = (const uint32_t*)( (const uint8_t*)ptr + codeSize);
  195. const CTHeader* header = NULL;
  196. ptr++; // first byte is shader type / version; skip it since we already know
  197. while (ptr < end && *ptr != D3DSIO_END)
  198. {
  199. uint32_t cur = *ptr++;
  200. if ( (cur & D3DSI_OPCODE_MASK) != D3DSIO_COMMENT)
  201. {
  202. continue;
  203. }
  204. // try to find CTAB comment block
  205. uint32_t commentSize = (cur & D3DSI_COMMENTSIZE_MASK) >> 16;
  206. uint32_t fourcc = *ptr;
  207. if (fourcc == CTAB_CONSTANT)
  208. {
  209. // found the constant table data
  210. header = (const CTHeader*)(ptr + 1);
  211. uint32_t tableSize = (commentSize - 1) * 4;
  212. if (tableSize < sizeof(CTHeader) || header->Size != sizeof(CTHeader) )
  213. {
  214. fprintf(stderr, "Error: Invalid constant table data\n");
  215. return false;
  216. }
  217. break;
  218. }
  219. // this is a different kind of comment section, so skip over it
  220. ptr += commentSize - 1;
  221. }
  222. if (!header)
  223. {
  224. fprintf(stderr, "Error: Could not find constant table data\n");
  225. return false;
  226. }
  227. const uint8_t* headerBytePtr = (const uint8_t*)header;
  228. const char* creator = (const char*)(headerBytePtr + header->Creator);
  229. BX_TRACE("Creator: %s 0x%08x", creator, header->Version);
  230. BX_TRACE("Num constants: %d", header->Constants);
  231. BX_TRACE("# cl ty RxC S By Name");
  232. const CTInfo* ctInfoArray = (const CTInfo*)(headerBytePtr + header->ConstantInfo);
  233. for (uint32_t ii = 0; ii < header->Constants; ++ii)
  234. {
  235. const CTInfo& ctInfo = ctInfoArray[ii];
  236. const CTType& ctType = *(const CTType*)(headerBytePtr + ctInfo.TypeInfo);
  237. const char* name = (const char*)(headerBytePtr + ctInfo.Name);
  238. BX_TRACE("%3d %2d %2d [%dx%d] %d %s[%d] c%d (%d)"
  239. , ii
  240. , ctType.Class
  241. , ctType.Type
  242. , ctType.Rows
  243. , ctType.Columns
  244. , ctType.StructMembers
  245. , name
  246. , ctType.Elements
  247. , ctInfo.RegisterIndex
  248. , ctInfo.RegisterCount
  249. );
  250. D3D11_SHADER_TYPE_DESC desc;
  251. desc.Class = (D3D_SHADER_VARIABLE_CLASS)ctType.Class;
  252. desc.Type = (D3D_SHADER_VARIABLE_TYPE)ctType.Type;
  253. desc.Rows = ctType.Rows;
  254. desc.Columns = ctType.Columns;
  255. UniformType::Enum type = findUniformType(desc);
  256. if (UniformType::Count != type)
  257. {
  258. Uniform un;
  259. un.name = '$' == name[0] ? name + 1 : name;
  260. un.type = isSampler(desc.Type)
  261. ? UniformType::Enum(BGFX_UNIFORM_SAMPLERBIT | type)
  262. : type
  263. ;
  264. un.num = (uint8_t)ctType.Elements;
  265. un.regIndex = ctInfo.RegisterIndex;
  266. un.regCount = ctInfo.RegisterCount;
  267. _uniforms.push_back(un);
  268. }
  269. }
  270. return true;
  271. }
  272. bool getReflectionDataD3D11(ID3DBlob* _code, bool _vshader, UniformArray& _uniforms, uint8_t& _numAttrs, uint16_t* _attrs, uint16_t& _size, UniformNameList& unusedUniforms)
  273. {
  274. ID3D11ShaderReflection* reflect = NULL;
  275. HRESULT hr = D3DReflect(_code->GetBufferPointer()
  276. , _code->GetBufferSize()
  277. , IID_ID3D11ShaderReflection
  278. , (void**)&reflect
  279. );
  280. if (FAILED(hr) )
  281. {
  282. fprintf(stderr, "Error: D3DReflect failed 0x%08x\n", (uint32_t)hr);
  283. return false;
  284. }
  285. D3D11_SHADER_DESC desc;
  286. hr = reflect->GetDesc(&desc);
  287. if (FAILED(hr) )
  288. {
  289. fprintf(stderr, "Error: ID3D11ShaderReflection::GetDesc failed 0x%08x\n", (uint32_t)hr);
  290. return false;
  291. }
  292. BX_TRACE("Creator: %s 0x%08x", desc.Creator, desc.Version);
  293. BX_TRACE("Num constant buffers: %d", desc.ConstantBuffers);
  294. BX_TRACE("Input:");
  295. if (_vshader) // Only care about input semantic on vertex shaders
  296. {
  297. for (uint32_t ii = 0; ii < desc.InputParameters; ++ii)
  298. {
  299. D3D11_SIGNATURE_PARAMETER_DESC spd;
  300. reflect->GetInputParameterDesc(ii, &spd);
  301. BX_TRACE("\t%2d: %s%d, vt %d, ct %d, mask %x, reg %d"
  302. , ii
  303. , spd.SemanticName
  304. , spd.SemanticIndex
  305. , spd.SystemValueType
  306. , spd.ComponentType
  307. , spd.Mask
  308. , spd.Register
  309. );
  310. const RemapInputSemantic& ris = findInputSemantic(spd.SemanticName, spd.SemanticIndex);
  311. if (ris.m_attr != bgfx::Attrib::Count)
  312. {
  313. _attrs[_numAttrs] = bgfx::attribToId(ris.m_attr);
  314. ++_numAttrs;
  315. }
  316. }
  317. }
  318. BX_TRACE("Output:");
  319. for (uint32_t ii = 0; ii < desc.OutputParameters; ++ii)
  320. {
  321. D3D11_SIGNATURE_PARAMETER_DESC spd;
  322. reflect->GetOutputParameterDesc(ii, &spd);
  323. BX_TRACE("\t%2d: %s%d, %d, %d", ii, spd.SemanticName, spd.SemanticIndex, spd.SystemValueType, spd.ComponentType);
  324. }
  325. for (uint32_t ii = 0, num = bx::uint32_min(1, desc.ConstantBuffers); ii < num; ++ii)
  326. {
  327. ID3D11ShaderReflectionConstantBuffer* cbuffer = reflect->GetConstantBufferByIndex(ii);
  328. D3D11_SHADER_BUFFER_DESC bufferDesc;
  329. hr = cbuffer->GetDesc(&bufferDesc);
  330. _size = (uint16_t)bufferDesc.Size;
  331. if (SUCCEEDED(hr) )
  332. {
  333. BX_TRACE("%s, %d, vars %d, size %d"
  334. , bufferDesc.Name
  335. , bufferDesc.Type
  336. , bufferDesc.Variables
  337. , bufferDesc.Size
  338. );
  339. for (uint32_t jj = 0; jj < bufferDesc.Variables; ++jj)
  340. {
  341. ID3D11ShaderReflectionVariable* var = cbuffer->GetVariableByIndex(jj);
  342. ID3D11ShaderReflectionType* type = var->GetType();
  343. D3D11_SHADER_VARIABLE_DESC varDesc;
  344. hr = var->GetDesc(&varDesc);
  345. if (SUCCEEDED(hr) )
  346. {
  347. D3D11_SHADER_TYPE_DESC constDesc;
  348. hr = type->GetDesc(&constDesc);
  349. if (SUCCEEDED(hr) )
  350. {
  351. UniformType::Enum uniformType = findUniformType(constDesc);
  352. if (UniformType::Count != uniformType
  353. && 0 != (varDesc.uFlags & D3D_SVF_USED) )
  354. {
  355. Uniform un;
  356. un.name = varDesc.Name;
  357. un.type = uniformType;
  358. un.num = constDesc.Elements;
  359. un.regIndex = varDesc.StartOffset;
  360. un.regCount = BX_ALIGN_16(varDesc.Size) / 16;
  361. _uniforms.push_back(un);
  362. BX_TRACE("\t%s, %d, size %d, flags 0x%08x, %d (used)"
  363. , varDesc.Name
  364. , varDesc.StartOffset
  365. , varDesc.Size
  366. , varDesc.uFlags
  367. , uniformType
  368. );
  369. }
  370. else
  371. {
  372. if (0 == (varDesc.uFlags & D3D_SVF_USED) )
  373. {
  374. unusedUniforms.push_back(varDesc.Name);
  375. }
  376. BX_TRACE("\t%s, unknown type", varDesc.Name);
  377. }
  378. }
  379. }
  380. }
  381. }
  382. }
  383. BX_TRACE("Bound:");
  384. for (uint32_t ii = 0; ii < desc.BoundResources; ++ii)
  385. {
  386. D3D11_SHADER_INPUT_BIND_DESC bindDesc;
  387. hr = reflect->GetResourceBindingDesc(ii, &bindDesc);
  388. if (SUCCEEDED(hr) )
  389. {
  390. if (D3D_SIT_SAMPLER == bindDesc.Type)
  391. {
  392. BX_TRACE("\t%s, %d, %d, %d"
  393. , bindDesc.Name
  394. , bindDesc.Type
  395. , bindDesc.BindPoint
  396. , bindDesc.BindCount
  397. );
  398. const char * end = strstr(bindDesc.Name, "Sampler");
  399. if (NULL != end)
  400. {
  401. Uniform un;
  402. un.name.assign(bindDesc.Name, (end - bindDesc.Name) );
  403. un.type = UniformType::Enum(BGFX_UNIFORM_SAMPLERBIT | UniformType::Int1);
  404. un.num = 1;
  405. un.regIndex = bindDesc.BindPoint;
  406. un.regCount = bindDesc.BindCount;
  407. _uniforms.push_back(un);
  408. }
  409. }
  410. }
  411. }
  412. if (NULL != reflect)
  413. {
  414. reflect->Release();
  415. }
  416. return true;
  417. }
  418. bool compileHLSLShader(bx::CommandLine& _cmdLine, uint32_t _d3d, const std::string& _code, bx::WriterI* _writer, bool _firstPass)
  419. {
  420. const char* profile = _cmdLine.findOption('p', "profile");
  421. if (NULL == profile)
  422. {
  423. fprintf(stderr, "Error: Shader profile must be specified.\n");
  424. return false;
  425. }
  426. void* d3dcompilerdll = bx::dlopen("D3DCompiler_47.dll");
  427. if (NULL == d3dcompilerdll)
  428. {
  429. fprintf(stderr, "Error: Unable to open D3DCompiler_47.dll shader compiler.\n");
  430. return false;
  431. }
  432. D3DCompile = (PFN_D3D_COMPILE )bx::dlsym(d3dcompilerdll, "D3DCompile");
  433. D3DDisassemble = (PFN_D3D_DISASSEMBLE )bx::dlsym(d3dcompilerdll, "D3DDisassemble");
  434. D3DReflect = (PFN_D3D_REFLECT )bx::dlsym(d3dcompilerdll, "D3DReflect");
  435. D3DStripShader = (PFN_D3D_STRIP_SHADER)bx::dlsym(d3dcompilerdll, "D3DStripShader");
  436. if (NULL == D3DCompile
  437. || NULL == D3DDisassemble
  438. || NULL == D3DReflect
  439. || NULL == D3DStripShader)
  440. {
  441. bx::dlclose(d3dcompilerdll);
  442. return false;
  443. }
  444. bool result = false;
  445. bool debug = _cmdLine.hasArg('\0', "debug");
  446. uint32_t flags = D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
  447. flags |= debug ? D3DCOMPILE_DEBUG : 0;
  448. flags |= _cmdLine.hasArg('\0', "avoid-flow-control") ? D3DCOMPILE_AVOID_FLOW_CONTROL : 0;
  449. flags |= _cmdLine.hasArg('\0', "no-preshader") ? D3DCOMPILE_NO_PRESHADER : 0;
  450. flags |= _cmdLine.hasArg('\0', "partial-precision") ? D3DCOMPILE_PARTIAL_PRECISION : 0;
  451. flags |= _cmdLine.hasArg('\0', "prefer-flow-control") ? D3DCOMPILE_PREFER_FLOW_CONTROL : 0;
  452. flags |= _cmdLine.hasArg('\0', "backwards-compatibility") ? D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY : 0;
  453. bool werror = _cmdLine.hasArg('\0', "Werror");
  454. if (werror)
  455. {
  456. flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;
  457. }
  458. uint32_t optimization = 3;
  459. if (_cmdLine.hasArg(optimization, 'O') )
  460. {
  461. optimization = bx::uint32_min(optimization, BX_COUNTOF(s_optimizationLevelD3D11) - 1);
  462. flags |= s_optimizationLevelD3D11[optimization];
  463. }
  464. else
  465. {
  466. flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
  467. }
  468. BX_TRACE("Profile: %s", profile);
  469. BX_TRACE("Flags: 0x%08x", flags);
  470. ID3DBlob* code;
  471. ID3DBlob* errorMsg;
  472. // Output preprocessed shader so that HLSL can be debugged via GPA
  473. // or PIX. Compiling through memory won't embed preprocessed shader
  474. // file path.
  475. std::string hlslfp;
  476. if (debug)
  477. {
  478. hlslfp = _cmdLine.findOption('o');
  479. hlslfp += ".hlsl";
  480. writeFile(hlslfp.c_str(), _code.c_str(), (int32_t)_code.size() );
  481. }
  482. HRESULT hr = D3DCompile(_code.c_str()
  483. , _code.size()
  484. , hlslfp.c_str()
  485. , NULL
  486. , NULL
  487. , "main"
  488. , profile
  489. , flags
  490. , 0
  491. , &code
  492. , &errorMsg
  493. );
  494. if (FAILED(hr)
  495. || (werror && NULL != errorMsg) )
  496. {
  497. const char* log = (char*)errorMsg->GetBufferPointer();
  498. int32_t line = 0;
  499. int32_t column = 0;
  500. int32_t start = 0;
  501. int32_t end = INT32_MAX;
  502. if (2 == sscanf(log, "(%u,%u):", &line, &column)
  503. && 0 != line)
  504. {
  505. start = bx::uint32_imax(1, line - 10);
  506. end = start + 20;
  507. }
  508. printCode(_code.c_str(), line, start, end);
  509. fprintf(stderr, "Error: D3DCompile failed 0x%08x %s\n", (uint32_t)hr, log);
  510. errorMsg->Release();
  511. return false;
  512. }
  513. UniformArray uniforms;
  514. uint8_t numAttrs = 0;
  515. uint16_t attrs[bgfx::Attrib::Count];
  516. uint16_t size = 0;
  517. if (_d3d == 9)
  518. {
  519. if (!getReflectionDataD3D9(code, uniforms) )
  520. {
  521. fprintf(stderr, "Error: Unable to get D3D9 reflection data.\n");
  522. goto error;
  523. }
  524. }
  525. else
  526. {
  527. UniformNameList unusedUniforms;
  528. if (!getReflectionDataD3D11(code, profile[0] == 'v', uniforms, numAttrs, attrs, size, unusedUniforms) )
  529. {
  530. fprintf(stderr, "Unable to get D3D11 reflection data.\n");
  531. goto error;
  532. }
  533. if (_firstPass
  534. && unusedUniforms.size() > 0)
  535. {
  536. const size_t strLength = strlen("uniform");
  537. // first time through, we just find unused uniforms and get rid of them
  538. std::string output;
  539. LineReader reader(_code.c_str() );
  540. while (!reader.isEof() )
  541. {
  542. std::string line = reader.getLine();
  543. for (UniformNameList::iterator it = unusedUniforms.begin(), itEnd = unusedUniforms.end(); it != itEnd; ++it)
  544. {
  545. size_t index = line.find("uniform ");
  546. if (index == std::string::npos)
  547. {
  548. continue;
  549. }
  550. // matching lines like: uniform u_name;
  551. // we want to replace "uniform" with "static" so that it's no longer
  552. // included in the uniform blob that the application must upload
  553. // we can't just remove them, because unused functions might still reference
  554. // them and cause a compile error when they're gone
  555. if (!!bx::findIdentifierMatch(line.c_str(), it->c_str() ) )
  556. {
  557. line = line.replace(index, strLength, "static");
  558. unusedUniforms.erase(it);
  559. break;
  560. }
  561. }
  562. output += line;
  563. }
  564. // recompile with the unused uniforms converted to statics
  565. return compileHLSLShader(_cmdLine, _d3d, output.c_str(), _writer, false);
  566. }
  567. }
  568. {
  569. uint16_t count = (uint16_t)uniforms.size();
  570. bx::write(_writer, count);
  571. uint32_t fragmentBit = profile[0] == 'p' ? BGFX_UNIFORM_FRAGMENTBIT : 0;
  572. for (UniformArray::const_iterator it = uniforms.begin(); it != uniforms.end(); ++it)
  573. {
  574. const Uniform& un = *it;
  575. uint8_t nameSize = (uint8_t)un.name.size();
  576. bx::write(_writer, nameSize);
  577. bx::write(_writer, un.name.c_str(), nameSize);
  578. uint8_t type = un.type | fragmentBit;
  579. bx::write(_writer, type);
  580. bx::write(_writer, un.num);
  581. bx::write(_writer, un.regIndex);
  582. bx::write(_writer, un.regCount);
  583. BX_TRACE("%s, %s, %d, %d, %d"
  584. , un.name.c_str()
  585. , getUniformTypeName(un.type)
  586. , un.num
  587. , un.regIndex
  588. , un.regCount
  589. );
  590. }
  591. }
  592. {
  593. ID3DBlob* stripped;
  594. hr = D3DStripShader(code->GetBufferPointer()
  595. , code->GetBufferSize()
  596. , D3DCOMPILER_STRIP_REFLECTION_DATA
  597. | D3DCOMPILER_STRIP_TEST_BLOBS
  598. , &stripped
  599. );
  600. if (SUCCEEDED(hr) )
  601. {
  602. code->Release();
  603. code = stripped;
  604. }
  605. }
  606. {
  607. uint16_t shaderSize = (uint16_t)code->GetBufferSize();
  608. bx::write(_writer, shaderSize);
  609. bx::write(_writer, code->GetBufferPointer(), shaderSize);
  610. uint8_t nul = 0;
  611. bx::write(_writer, nul);
  612. }
  613. if (_d3d > 9)
  614. {
  615. bx::write(_writer, numAttrs);
  616. bx::write(_writer, attrs, numAttrs*sizeof(uint16_t) );
  617. bx::write(_writer, size);
  618. }
  619. if (_cmdLine.hasArg('\0', "disasm") )
  620. {
  621. ID3DBlob* disasm;
  622. D3DDisassemble(code->GetBufferPointer()
  623. , code->GetBufferSize()
  624. , 0
  625. , NULL
  626. , &disasm
  627. );
  628. if (NULL != disasm)
  629. {
  630. std::string disasmfp = _cmdLine.findOption('o');
  631. disasmfp += ".disasm";
  632. writeFile(disasmfp.c_str(), disasm->GetBufferPointer(), (uint32_t)disasm->GetBufferSize() );
  633. disasm->Release();
  634. }
  635. }
  636. if (NULL != errorMsg)
  637. {
  638. errorMsg->Release();
  639. }
  640. result = true;
  641. error:
  642. code->Release();
  643. bx::dlclose(d3dcompilerdll);
  644. return result;
  645. }
  646. } // namespace bgfx
  647. #else
  648. namespace bgfx
  649. {
  650. bool compileHLSLShader(bx::CommandLine& _cmdLine, uint32_t _d3d, const std::string& _code, bx::WriterI* _writer, bool _firstPass)
  651. {
  652. BX_UNUSED(_cmdLine, _d3d, _code, _writer, _firstPass);
  653. fprintf(stderr, "HLSL compiler is not supported on this platform.\n");
  654. return false;
  655. }
  656. } // namespace bgfx
  657. #endif // SHADERC_CONFIG_HLSL