Skip to content

Commit 5f64a71

Browse files
committed
Base impl for DXC HLSL compiler
1 parent ba164d2 commit 5f64a71

File tree

2 files changed

+107
-4
lines changed

2 files changed

+107
-4
lines changed

include/nbl/asset/utils/CHLSLCompiler.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include "nbl/asset/utils/ISPIRVOptimizer.h"
99
#include "nbl/asset/utils/IShaderCompiler.h"
1010

11+
#include <dxc/dxcapi.h>
12+
#include <combaseapi.h>
13+
1114
namespace nbl::asset
1215
{
1316

@@ -42,6 +45,10 @@ class NBL_API2 CHLSLCompiler final : public IShaderCompiler
4245

4346
void insertExtraDefines(std::string& str, const core::SRange<const char* const>& defines) const override;
4447

48+
// TODO do we want to use ComPtr?
49+
std::unique_ptr<IDxcUtils> m_dxcUtils;
50+
std::unique_ptr<IDxcCompiler3> m_dxcCompiler;
51+
4552
static CHLSLCompiler::SOptions option_cast(const IShaderCompiler::SCompilerOptions& options)
4653
{
4754
CHLSLCompiler::SOptions ret = {};
@@ -51,8 +58,23 @@ class NBL_API2 CHLSLCompiler final : public IShaderCompiler
5158
ret.setCommonData(options);
5259
return ret;
5360
}
61+
62+
class DxcCompilationResult
63+
{
64+
public:
65+
std::unique_ptr<IDxcBlobEncoding> errorMessages;
66+
std::unique_ptr<IDxcBlob> objectBlob;
67+
std::unique_ptr<IDxcResult> compileResult;
68+
69+
char* GetErrorMessagesString()
70+
{
71+
return reinterpret_cast<char*>(errorMessages->GetBufferPointer());
72+
}
73+
};
74+
75+
DxcCompilationResult dxcCompile(asset::ICPUShader* source, LPCWSTR* args, uint32_t argCount, const SOptions& options);
5476
};
5577

5678
}
5779

58-
#endif
80+
#endif

src/nbl/asset/utils/CHLSLCompiler.cpp

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <regex>
99
#include <iterator>
1010

11+
#include <dxc/dxcapi.h>
12+
#include <combaseapi.h>
1113

1214
using namespace nbl;
1315
using namespace nbl::asset;
@@ -16,6 +18,56 @@ using namespace nbl::asset;
1618
CHLSLCompiler::CHLSLCompiler(core::smart_refctd_ptr<system::ISystem>&& system)
1719
: IShaderCompiler(std::move(system))
1820
{
21+
IDxcUtils* utils;
22+
auto res = DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&utils));
23+
assert(SUCCEEDED(res));
24+
25+
IDxcCompiler3* compiler;
26+
res = DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler));
27+
assert(SUCCEEDED(res));
28+
29+
m_dxcUtils = std::unique_ptr<IDxcUtils>(utils);
30+
m_dxcCompiler = std::unique_ptr<IDxcCompiler3>(compiler);
31+
}
32+
33+
CHLSLCompiler::DxcCompilationResult CHLSLCompiler::dxcCompile(asset::ICPUShader* source, LPCWSTR* args, uint32_t argCount, const SOptions& options)
34+
{
35+
DxcBuffer sourceBuffer;
36+
sourceBuffer.Ptr = source->getContent()->getPointer();
37+
sourceBuffer.Size = source->getContent()->getSize();
38+
sourceBuffer.Encoding = 0;
39+
40+
IDxcResult* compileResult;
41+
auto res = m_dxcCompiler->Compile(&sourceBuffer, args, argCount, nullptr, IID_PPV_ARGS(&compileResult));
42+
// If the compilation failed, this should still be a successful result
43+
assert(SUCCEEDED(res));
44+
45+
HRESULT compilationStatus = 0;
46+
res = compileResult->GetStatus(&compilationStatus);
47+
assert(SUCCEEDED(res));
48+
49+
IDxcBlobEncoding* errorBuffer;
50+
res = compileResult->GetErrorBuffer(&errorBuffer);
51+
assert(SUCCEEDED(res));
52+
53+
DxcCompilationResult result;
54+
result.errorMessages = std::unique_ptr<IDxcBlobEncoding>(errorBuffer);
55+
result.compileResult = std::unique_ptr<IDxcResult>(compileResult);
56+
result.objectBlob = nullptr;
57+
58+
if (!SUCCEEDED(compilationStatus))
59+
{
60+
options.logger.log(result.GetErrorMessagesString(), system::ILogger::ELL_ERROR);
61+
return result;
62+
}
63+
64+
IDxcBlob* resultingBlob;
65+
res = compileResult->GetResult(&resultingBlob);
66+
assert(SUCCEEDED(res));
67+
68+
result.objectBlob = std::unique_ptr<IDxcBlob>(resultingBlob);
69+
70+
return result;
1971
}
2072

2173
core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* code, const IShaderCompiler::SCompilerOptions& options) const
@@ -28,9 +80,38 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
2880
return nullptr;
2981
}
3082

31-
core::smart_refctd_ptr<ICPUBuffer> spirv = nullptr;
32-
// TODO: Use DXC
33-
return core::make_smart_refctd_ptr<asset::ICPUShader>(std::move(spirv), options.stage, IShader::E_CONTENT_TYPE::ECT_SPIRV, options.preprocessorOptions.sourceIdentifier.data());
83+
core::smart_refctd_ptr<asset::ICPUShader> includesResolved;
84+
if (hlslOptions.includeFinder != nullptr)
85+
{
86+
includesResolved = resolveIncludeDirectives(code, hlslOptions.stage, hlslOptions.sourceIdentifier.data(), hlslOptions.maxSelfInclusionCount, hlslOptions.logger);
87+
if (includesResolved)
88+
{
89+
code = reinterpret_cast<const char*>(includesResolved->getContent()->getPointer());
90+
}
91+
}
92+
93+
LPCWSTR arguments[] = {
94+
// These will always be present
95+
L"-spirv",
96+
97+
// These are debug only
98+
L"-DPARTI",
99+
L"-DBOY"
100+
};
101+
const uint32_t allArgs = 3;
102+
const uint32_t nonDebugArgs = 1;
103+
104+
DxcCompilationResult compileResult = dxcCompile(includesResolved.get(), &arguments[0], hlslOptions.genDebugInfo ? allArgs : nonDebugArgs, hlslOptions);
105+
106+
if (!compileResult.objectBlob)
107+
{
108+
return nullptr;
109+
}
110+
111+
auto outSpirv = core::make_smart_refctd_ptr<ICPUBuffer>(compileResult.objectBlob->GetBufferSize());
112+
memcpy(outSpirv->getPointer(), compileResult.objectBlob->GetBufferPointer(), compileResult.objectBlob->GetBufferSize());
113+
114+
return core::make_smart_refctd_ptr<asset::ICPUShader>(std::move(outSpirv), hlslOptions.stage, IShader::E_CONTENT_TYPE::ECT_SPIRV, hlslOptions.sourceIdentifier.data());
34115
}
35116

36117
void CHLSLCompiler::insertExtraDefines(std::string& code, const core::SRange<const char* const>& defines) const

0 commit comments

Comments
 (0)