From 886d9c255b3e2ff67539297c6a3ac69e0013ef3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 25 May 2026 21:27:32 +0200 Subject: [PATCH] D3D11: Improve compilation error reporting --- GPU/D3D11/D3D11Util.cpp | 41 ++++++++++++++++++++++++------- GPU/D3D11/D3D11Util.h | 2 +- unittest/TestShaderGenerators.cpp | 14 ++++++++--- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/GPU/D3D11/D3D11Util.cpp b/GPU/D3D11/D3D11Util.cpp index d2cc4c5556..aa68dc7709 100644 --- a/GPU/D3D11/D3D11Util.cpp +++ b/GPU/D3D11/D3D11Util.cpp @@ -22,7 +22,7 @@ using namespace Microsoft::WRL; -std::vector CompileShaderToBytecodeD3D11(const char *code, size_t codeSize, const char *target, UINT flags) { +std::vector CompileShaderToBytecodeD3D11(const char *code, size_t codeSize, const char *target, UINT flags, std::string *errorMessage) { ComPtr compiledCode; ComPtr errorMsgs; HRESULT result = ptr_D3DCompile(code, codeSize, nullptr, nullptr, nullptr, "main", target, flags, 0, &compiledCode, &errorMsgs); @@ -45,6 +45,9 @@ std::vector CompileShaderToBytecodeD3D11(const char *code, size_t codeS } } else { ERROR_LOG(Log::G3D, "%s: %s\n\n%s", "errors", errors.c_str(), numberedCode.c_str()); + if (errorMessage) { + *errorMessage = errors; + } OutputDebugStringA(errors.c_str()); OutputDebugStringA(numberedCode.c_str()); } @@ -63,9 +66,14 @@ HRESULT CreateVertexShaderD3D11(ID3D11Device *device, const char *code, size_t c if (ppVertexShader) *ppVertexShader = nullptr; const char *profile = featureLevel <= D3D_FEATURE_LEVEL_9_3 ? "vs_4_0_level_9_1" : "vs_4_0"; - std::vector byteCode = CompileShaderToBytecodeD3D11(code, codeSize, profile, flags); - if (byteCode.empty()) + std::string errorMessage; + std::vector byteCode = CompileShaderToBytecodeD3D11(code, codeSize, profile, flags, &errorMessage); + if (byteCode.empty()) { + if (!errorMessage.empty()) { + ERROR_LOG(Log::G3D, "%s", errorMessage.c_str()); + } return S_FALSE; + } auto hr = device->CreateVertexShader(byteCode.data(), byteCode.size(), nullptr, ppVertexShader); if (byteCodeOut) @@ -77,9 +85,14 @@ HRESULT CreatePixelShaderD3D11(ID3D11Device *device, const char *code, size_t co if (ppPixelShader) *ppPixelShader = nullptr; const char *profile = featureLevel <= D3D_FEATURE_LEVEL_9_3 ? "ps_4_0_level_9_1" : "ps_4_0"; - std::vector byteCode = CompileShaderToBytecodeD3D11(code, codeSize, profile, flags); - if (byteCode.empty()) + std::string errorMessage; + std::vector byteCode = CompileShaderToBytecodeD3D11(code, codeSize, profile, flags, &errorMessage); + if (byteCode.empty()) { + if (!errorMessage.empty()) { + ERROR_LOG(Log::G3D, "%s", errorMessage.c_str()); + } return S_FALSE; + } return device->CreatePixelShader(byteCode.data(), byteCode.size(), nullptr, ppPixelShader); } @@ -89,9 +102,14 @@ HRESULT CreateComputeShaderD3D11(ID3D11Device *device, const char *code, size_t *ppComputeShader = nullptr; if (featureLevel <= D3D_FEATURE_LEVEL_9_3) return S_FALSE; - std::vector byteCode = CompileShaderToBytecodeD3D11(code, codeSize, "cs_4_0", flags); - if (byteCode.empty()) + std::string errorMessage; + std::vector byteCode = CompileShaderToBytecodeD3D11(code, codeSize, "cs_4_0", flags, &errorMessage); + if (byteCode.empty()) { + if (!errorMessage.empty()) { + ERROR_LOG(Log::G3D, "%s", errorMessage.c_str()); + } return S_FALSE; + } return device->CreateComputeShader(byteCode.data(), byteCode.size(), nullptr, ppComputeShader); } @@ -101,9 +119,14 @@ HRESULT CreateGeometryShaderD3D11(ID3D11Device *device, const char *code, size_t *ppGeometryShader = nullptr; if (featureLevel <= D3D_FEATURE_LEVEL_9_3) return S_FALSE; - std::vector byteCode = CompileShaderToBytecodeD3D11(code, codeSize, "gs_5_0", flags); - if (byteCode.empty()) + std::string errorMessage; + std::vector byteCode = CompileShaderToBytecodeD3D11(code, codeSize, "gs_5_0", flags, &errorMessage); + if (byteCode.empty()) { + if (!errorMessage.empty()) { + ERROR_LOG(Log::G3D, "%s", errorMessage.c_str()); + } return S_FALSE; + } return device->CreateGeometryShader(byteCode.data(), byteCode.size(), nullptr, ppGeometryShader); } diff --git a/GPU/D3D11/D3D11Util.h b/GPU/D3D11/D3D11Util.h index d5d52b9fef..04f0cc20d2 100644 --- a/GPU/D3D11/D3D11Util.h +++ b/GPU/D3D11/D3D11Util.h @@ -73,7 +73,7 @@ private: bool nextMapDiscard_ = false; }; -std::vector CompileShaderToBytecodeD3D11(const char *code, size_t codeSize, const char *target, UINT flags); +std::vector CompileShaderToBytecodeD3D11(const char *code, size_t codeSize, const char *target, UINT flags, std::string *errorMessage = nullptr); HRESULT CreateVertexShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, std::vector *byteCodeOut, D3D_FEATURE_LEVEL featureLevel, UINT flags, ID3D11VertexShader **); HRESULT CreatePixelShaderD3D11(ID3D11Device *device, const char *code, size_t codeSize, D3D_FEATURE_LEVEL featureLevel, UINT flags, ID3D11PixelShader **); diff --git a/unittest/TestShaderGenerators.cpp b/unittest/TestShaderGenerators.cpp index c4978484be..ccfc9afaa4 100644 --- a/unittest/TestShaderGenerators.cpp +++ b/unittest/TestShaderGenerators.cpp @@ -139,9 +139,14 @@ bool TestCompileShader(const char *buffer, ShaderLanguage lang, ShaderStage stag case ShaderStage::Vertex: programType = "vs_4_0"; break; case ShaderStage::Fragment: programType = "ps_4_0"; break; case ShaderStage::Geometry: programType = "gs_4_0"; break; - default: return false; + default: + *errorMessage = "Unknown shader stage"; + return false; + } + auto output = CompileShaderToBytecodeD3D11(buffer, strlen(buffer), programType, 0, errorMessage); + if (output.empty() && errorMessage->empty()) { + *errorMessage = "Error compiling HLSL shader: bytecode empty"; } - auto output = CompileShaderToBytecodeD3D11(buffer, strlen(buffer), programType, 0); return !output.empty(); } #endif @@ -153,6 +158,7 @@ bool TestCompileShader(const char *buffer, ShaderLanguage lang, ShaderStage stag case ShaderLanguage::GLSL_3xx: return GLSLtoSPV(StageToVulkan(stage), buffer, GLSLVariant::GLES300, spirv, errorMessage); default: + *errorMessage = "Unknown shader language"; return false; } } @@ -422,7 +428,7 @@ bool TestVertexShaders() { if (generateSuccess[j]) { std::string errorMessage; if (!TestCompileShader(buffer[j], languages[j], ShaderStage::Vertex, &errorMessage)) { - printf("Error compiling vertex shader %d:\n\n%s\n\n%s\n", (int)j, LineNumberString(buffer[j]).c_str(), errorMessage.c_str()); + printf("Error compiling vertex shader %d:\n\n%s\n\nERROR: %s\n\n(end of error)\n\n", (int)j, LineNumberString(buffer[j]).c_str(), errorMessage.c_str()); for (int i = 0; i < numLanguages; i++) { delete[] buffer[i]; } @@ -496,7 +502,7 @@ bool TestFragmentShaders() { if (generateSuccess[j]) { std::string errorMessage; if (!TestCompileShader(buffer[j], languages[j], ShaderStage::Fragment, &errorMessage)) { - printf("Error compiling fragment shader:\n\n%s\n\n%s\n", LineNumberString(buffer[j]).c_str(), errorMessage.c_str()); + printf("Error compiling fragment shader %d:\n\n%s\n\nERROR: %s\n\n(end of error)\n\n", (int)j, LineNumberString(buffer[j]).c_str(), errorMessage.c_str()); for (int i = 0; i < numLanguages; i++) { delete[] buffer[i]; }