d3d12.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include "d3d12.h"
  2. #include "../errors.h"
  3. #ifdef _WIN32
  4. #include "../log.h"
  5. #ifdef noreturn
  6. #undef noreturn
  7. #endif
  8. #include <atlbase.h>
  9. #include <dxcapi.h>
  10. #endif
  11. #ifdef _WIN32
  12. static const wchar_t *shader_string(shader_stage stage) {
  13. switch (stage) {
  14. case SHADER_STAGE_VERTEX:
  15. return L"vs_6_0";
  16. case SHADER_STAGE_FRAGMENT:
  17. return L"ps_6_0";
  18. case SHADER_STAGE_COMPUTE:
  19. return L"cs_6_0";
  20. case SHADER_STAGE_RAY_GENERATION:
  21. return L"lib_6_3";
  22. case SHADER_STAGE_AMPLIFICATION:
  23. return L"as_6_5";
  24. case SHADER_STAGE_MESH:
  25. return L"ms_6_5";
  26. default: {
  27. debug_context context = {0};
  28. error(context, "Unsupported shader stage/version combination");
  29. return L"unsupported";
  30. }
  31. }
  32. }
  33. #endif
  34. int compile_hlsl_to_d3d12(const char *source, uint8_t **output, size_t *outputlength, shader_stage stage, bool debug) {
  35. #ifdef _WIN32
  36. CComPtr<IDxcCompiler3> compiler;
  37. DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler));
  38. LPCWSTR compiler_args[] = {
  39. L"-E", L"main", // entry point
  40. L"-T", shader_string(stage), // target
  41. // L"-Qstrip_reflect", // strip reflection into a seperate blob
  42. };
  43. LPCWSTR debug_compiler_args[] = {
  44. L"-E", L"main", // entry point
  45. L"-T", shader_string(stage), // target
  46. L"-Zi", // enable debug info
  47. // L"-Fd", L"myshader.pdb", // the file name of the pdb. This must either be supplied or the auto generated file name must be used
  48. // L"myshader.hlsl", // optional shader source file name for error reporting and for PIX shader source view
  49. // L"-Qstrip_reflect", // strip reflection into a seperate blob
  50. };
  51. DxcBuffer source_buffer;
  52. source_buffer.Ptr = source;
  53. source_buffer.Size = strlen(source);
  54. source_buffer.Encoding = DXC_CP_ACP; // assume BOM says UTF8 or UTF16 or this is ANSI text
  55. CComPtr<IDxcResult> compiler_result;
  56. compiler->Compile(&source_buffer, // source buffer
  57. debug ? debug_compiler_args : compiler_args, // Array of pointers to arguments
  58. debug ? _countof(debug_compiler_args) : _countof(compiler_args), // Number of arguments
  59. NULL, // user-provided interface to handle #include directives (optional)
  60. IID_PPV_ARGS(&compiler_result) // Compiler output status, buffer, and errors
  61. );
  62. CComPtr<IDxcBlobUtf8> errors = nullptr;
  63. compiler_result->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&errors), nullptr);
  64. // note that d3dcompiler would return null if no errors or warnings are present.
  65. // IDxcCompiler3::Compile will always return an error buffer but it's length will be zero if there are no warnings or errors
  66. if (errors != nullptr && errors->GetStringLength() != 0) {
  67. kong_log(LOG_LEVEL_INFO, "Warnings and Errors:\n%s", errors->GetStringPointer());
  68. }
  69. HRESULT result;
  70. compiler_result->GetStatus(&result);
  71. if (result == S_OK) {
  72. CComPtr<IDxcBlob> shader_buffer = nullptr;
  73. CComPtr<IDxcBlobUtf16> shader_name = nullptr;
  74. compiler_result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&shader_buffer), &shader_name);
  75. if (shader_buffer == nullptr) {
  76. return 1;
  77. }
  78. else {
  79. *outputlength = shader_buffer->GetBufferSize();
  80. *output = (uint8_t *)malloc(*outputlength);
  81. memcpy(*output, shader_buffer->GetBufferPointer(), shader_buffer->GetBufferSize());
  82. }
  83. /*
  84. //
  85. // save pdb
  86. //
  87. CComPtr<IDxcBlob> pPDB = nullptr;
  88. CComPtr<IDxcBlobUtf16> pPDBName = nullptr;
  89. pResults->GetOutput(DXC_OUT_PDB, IID_PPV_ARGS(&pPDB), &pPDBName);
  90. {
  91. FILE* fp = NULL;
  92. // note that if you do not specifiy -Fd a pdb name will be automatically generated. Use this filename to save the pdb so that PIX can find
  93. it quickly _wfopen_s(&fp, pPDBName->GetStringPointer(), L"wb"); fwrite(pPDB->GetBufferPointer(), pPDB->GetBufferSize(), 1, fp); fclose(fp);
  94. }
  95. //
  96. // print hash
  97. //
  98. CComPtr<IDxcBlob> pHash = nullptr;
  99. pResults->GetOutput(DXC_OUT_SHADER_HASH, IID_PPV_ARGS(&pHash), nullptr);
  100. if (pHash != nullptr)
  101. {
  102. wprintf(L"Hash: ");
  103. DxcShaderHash* pHashBuf = (DxcShaderHash*)pHash->GetBufferPointer();
  104. for (int i = 0; i < _countof(pHashBuf->HashDigest); i++)
  105. wprintf(L"%x", pHashBuf->HashDigest[i]);
  106. wprintf(L"\n");
  107. }
  108. */
  109. return 0;
  110. }
  111. else {
  112. return 1;
  113. }
  114. #else
  115. return 1;
  116. #endif
  117. }