Skip to content

Commit 7a39c38

Browse files
authored
Merge pull request #642 from Devsh-Graphics-Programming/nahim_ndt
Nabla Shader Compiler Tool
2 parents 64cbb65 + 4a7a7f6 commit 7a39c38

File tree

14 files changed

+515
-67
lines changed

14 files changed

+515
-67
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@ android-sample/bin/*
2929
preprocessed.hlsl
3030
compiled.spv
3131
.vs/*
32+
tools/ndt/__main__.py
33+
tools/ndt/.vscode/settings.json
34+
tools/ndt/.vscode/launch.json
35+
tools/ndt/.profiles/0.json

CMakeLists.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -352,10 +352,8 @@ add_subdirectory(${THIRD_PARTY_SOURCE_DIR})
352352

353353
add_subdirectory(src/nbl)
354354
add_subdirectory("${NBL_PYTHON_MODULE_ROOT_PATH}" tests) # Python Framework
355-
356-
if(NBL_BUILD_EXAMPLES)
357-
add_subdirectory(examples_tests)
358-
endif()
355+
add_subdirectory(examples_tests)
356+
add_subdirectory(tools)
359357

360358
if(NBL_BUILD_DOCS)
361359
add_subdirectory(docs)

include/nbl/asset/utils/CHLSLCompiler.h

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

11+
12+
1113
#ifdef _NBL_PLATFORM_WINDOWS_
1214

1315
namespace nbl::asset::impl
@@ -21,6 +23,8 @@ namespace nbl::asset
2123
class NBL_API2 CHLSLCompiler final : public IShaderCompiler
2224
{
2325
public:
26+
27+
2428
IShader::E_CONTENT_TYPE getCodeContentType() const override { return IShader::E_CONTENT_TYPE::ECT_HLSL; };
2529

2630
CHLSLCompiler(core::smart_refctd_ptr<system::ISystem>&& system);
@@ -47,9 +51,17 @@ class NBL_API2 CHLSLCompiler final : public IShaderCompiler
4751
//}
4852

4953
std::string preprocessShader(std::string&& code, IShader::E_SHADER_STAGE& stage, const SPreprocessorOptions& preprocessOptions) const override;
50-
54+
std::string preprocessShader(std::string&& code, IShader::E_SHADER_STAGE& stage, std::vector<std::string>& dxc_compile_flags_override, const SPreprocessorOptions& preprocessOptions) const;
55+
5156
void insertIntoStart(std::string& code, std::ostringstream&& ins) const override;
57+
58+
struct SdxcCompileResult {
59+
uint8_t *begin;
60+
size_t size;
61+
};
62+
SdxcCompileResult dxcCompile(std::string& source, LPCWSTR* args, uint32_t argCount, const CHLSLCompiler::SOptions& options) const;
5263
protected:
64+
5365

5466
// This can't be a unique_ptr due to it being an undefined type
5567
// when Nabla is used as a lib

include/nbl/system/ISystem.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ class NBL_API2 ISystem : public core::IReferenceCounted
149149
m_cachedArchiveFiles.removeObject(dummy,pathAlias);
150150
}
151151

152+
void unmountBuiltins();
153+
152154
//
153155
struct SystemInfo
154156
{

src/nbl/asset/utils/CHLSLCompiler.cpp

Lines changed: 86 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,20 @@
33
// For conditions of distribution and use, see copyright notice in nabla.h
44
#include "nbl/asset/utils/CHLSLCompiler.h"
55
#include "nbl/asset/utils/shadercUtils.h"
6-
// TODO: review
76
#ifdef NBL_EMBED_BUILTIN_RESOURCES
87
#include "nbl/builtin/CArchive.h"
98
#include "spirv/builtin/CArchive.h"
109
#endif // NBL_EMBED_BUILTIN_RESOURCES
1110

1211
#ifdef _NBL_PLATFORM_WINDOWS_
1312

14-
#include <wrl.h>
15-
#include <combaseapi.h>
16-
17-
#include <dxc/dxcapi.h>
18-
19-
#include <sstream>
2013
#include <regex>
2114
#include <iterator>
2215
#include <codecvt>
16+
#include <wrl.h>
17+
#include <combaseapi.h>
18+
#include <sstream>
19+
#include <dxc/dxcapi.h>
2320

2421

2522
using namespace nbl;
@@ -38,6 +35,19 @@ struct DXC
3835
};
3936
}
4037

38+
struct DxcCompilationResult
39+
{
40+
Microsoft::WRL::ComPtr<IDxcBlobEncoding> errorMessages;
41+
Microsoft::WRL::ComPtr<IDxcBlob> objectBlob;
42+
Microsoft::WRL::ComPtr<IDxcResult> compileResult;
43+
44+
std::string GetErrorMessagesString()
45+
{
46+
return std::string(reinterpret_cast<char*>(errorMessages->GetBufferPointer()), errorMessages->GetBufferSize());
47+
}
48+
};
49+
50+
4151
CHLSLCompiler::CHLSLCompiler(core::smart_refctd_ptr<system::ISystem>&& system)
4252
: IShaderCompiler(std::move(system))
4353
{
@@ -60,20 +70,7 @@ CHLSLCompiler::~CHLSLCompiler()
6070
delete m_dxcCompilerTypes;
6171
}
6272

63-
64-
struct DxcCompilationResult
65-
{
66-
ComPtr<IDxcBlobEncoding> errorMessages;
67-
ComPtr<IDxcBlob> objectBlob;
68-
ComPtr<IDxcResult> compileResult;
69-
70-
std::string GetErrorMessagesString()
71-
{
72-
return std::string(reinterpret_cast<char*>(errorMessages->GetBufferPointer()), errorMessages->GetBufferSize());
73-
}
74-
};
75-
76-
DxcCompilationResult dxcCompile(const CHLSLCompiler* compiler, nbl::asset::impl::DXC* dxc, std::string& source, LPCWSTR* args, uint32_t argCount, const CHLSLCompiler::SOptions& options)
73+
CHLSLCompiler::SdxcCompileResult CHLSLCompiler::dxcCompile(std::string& source, LPCWSTR* args, uint32_t argCount, const CHLSLCompiler::SOptions& options) const
7774
{
7875
// Append Commandline options into source only if debugInfoFlags will emit source
7976
auto sourceEmittingFlags =
@@ -83,7 +80,7 @@ DxcCompilationResult dxcCompile(const CHLSLCompiler* compiler, nbl::asset::impl:
8380
if ((options.debugInfoFlags.value & sourceEmittingFlags) != CHLSLCompiler::E_DEBUG_INFO_FLAGS::EDIF_NONE)
8481
{
8582
std::ostringstream insertion;
86-
insertion << "//#pragma compile_flags ";
83+
insertion << "#pragma wave dxc_compile_flags( ";
8784

8885
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> conv;
8986
for (uint32_t arg = 0; arg < argCount; arg ++)
@@ -92,10 +89,10 @@ DxcCompilationResult dxcCompile(const CHLSLCompiler* compiler, nbl::asset::impl:
9289
insertion << str.c_str() << " ";
9390
}
9491

95-
insertion << "\n";
96-
compiler->insertIntoStart(source, std::move(insertion));
92+
insertion << ")\n";
93+
insertIntoStart(source, std::move(insertion));
9794
}
98-
95+
nbl::asset::impl::DXC* dxc = m_dxcCompilerTypes;
9996
ComPtr<IDxcBlobEncoding> src;
10097
auto res = dxc->m_dxcUtils->CreateBlob(reinterpret_cast<const void*>(source.data()), source.size(), CP_UTF8, &src);
10198
assert(SUCCEEDED(res));
@@ -134,7 +131,7 @@ DxcCompilationResult dxcCompile(const CHLSLCompiler* compiler, nbl::asset::impl:
134131
else
135132
{
136133
options.preprocessorOptions.logger.log("DXC Compilation Failed:\n%s", system::ILogger::ELL_ERROR, errorMessagesString.c_str());
137-
return result;
134+
return { nullptr, 0 };
138135
}
139136

140137
ComPtr<IDxcBlob> resultingBlob;
@@ -143,18 +140,19 @@ DxcCompilationResult dxcCompile(const CHLSLCompiler* compiler, nbl::asset::impl:
143140

144141
result.objectBlob = resultingBlob;
145142

146-
return result;
143+
return { (uint8_t*)result.objectBlob->GetBufferPointer(), result.objectBlob->GetBufferSize() };
147144
}
148145

149146

150147
#include "nbl/asset/utils/waveContext.h"
151148

152-
std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADER_STAGE& stage, const SPreprocessorOptions& preprocessOptions) const
149+
150+
std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADER_STAGE& stage, std::vector<std::string>& dxc_compile_flags_override, const SPreprocessorOptions& preprocessOptions) const
153151
{
154152
nbl::wave::context context(code.begin(),code.end(),preprocessOptions.sourceIdentifier.data(),{preprocessOptions});
155153
context.add_macro_definition("__HLSL_VERSION");
156154

157-
// instead of defining extraDefines as "NBL_GLSL_LIMIT_MAX_IMAGE_DIMENSION_1D 32768",
155+
// instead of defining extraDefines as "NBL_GLSL_LIMIT_MAX_IMAGE_DIMENSION_1D 32768",
158156
// now define them as "NBL_GLSL_LIMIT_MAX_IMAGE_DIMENSION_1D=32768"
159157
// to match boost wave syntax
160158
// https://www.boost.org/doc/libs/1_82_0/libs/wave/doc/class_reference_context.html#:~:text=Maintain%20defined%20macros-,add_macro_definition,-bool%20add_macro_definition
@@ -192,12 +190,22 @@ std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADE
192190
}
193191
}
194192

193+
if (context.get_hooks().m_dxc_compile_flags_override.size() != 0)
194+
dxc_compile_flags_override = context.get_hooks().m_dxc_compile_flags_override;
195+
195196
if(context.get_hooks().m_pragmaStage != IShader::ESS_UNKNOWN)
196197
stage = context.get_hooks().m_pragmaStage;
197198

199+
200+
198201
return resolvedString;
199202
}
200203

204+
std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADER_STAGE& stage, const SPreprocessorOptions& preprocessOptions) const
205+
{
206+
std::vector<std::string> extra_dxc_compile_flags = {};
207+
return preprocessShader(std::move(code), stage, extra_dxc_compile_flags, preprocessOptions);
208+
}
201209

202210
core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* code, const IShaderCompiler::SCompilerOptions& options) const
203211
{
@@ -208,9 +216,9 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
208216
hlslOptions.preprocessorOptions.logger.log("code is nullptr", system::ILogger::ELL_ERROR);
209217
return nullptr;
210218
}
211-
219+
std::vector<std::string> dxc_compile_flags = {};
212220
auto stage = hlslOptions.stage;
213-
auto newCode = preprocessShader(code, stage, hlslOptions.preprocessorOptions);
221+
auto newCode = preprocessShader(code, stage, dxc_compile_flags, hlslOptions.preprocessorOptions);
214222

215223
// Suffix is the shader model version
216224
// TODO: Figure out a way to get the shader model version automatically
@@ -256,7 +264,21 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
256264
return nullptr;
257265
};
258266

259-
std::vector<LPCWSTR> arguments = {
267+
std::wstring* arg_storage = NULL;
268+
std::vector<LPCWSTR> arguments;
269+
270+
if (dxc_compile_flags.size()) { // #pragma wave overrides compile flags
271+
size_t arg_size = dxc_compile_flags.size();
272+
arguments = {};
273+
arguments.reserve(arg_size);
274+
arg_storage = new std::wstring[arg_size]; // prevent deallocation before shader compilation
275+
for (size_t i = 0; i < dxc_compile_flags.size(); i++) {
276+
arg_storage[i] = std::wstring(dxc_compile_flags[i].begin(), dxc_compile_flags[i].end());
277+
arguments.push_back(arg_storage[i].c_str());
278+
}
279+
}
280+
else {
281+
arguments = {
260282
L"-spirv",
261283
L"-HV", L"202x",
262284
L"-T", targetProfile.c_str(),
@@ -267,47 +289,48 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
267289
L"-Wno-c++1z-extensions",
268290
L"-Wno-gnu-static-float-init",
269291
L"-fspv-target-env=vulkan1.3"
270-
};
292+
};
293+
// If a custom SPIR-V optimizer is specified, use that instead of DXC's spirv-opt.
294+
// This is how we can get more optimizer options.
295+
//
296+
// Optimization is also delegated to SPIRV-Tools. Right now there are no difference between
297+
// optimization levels greater than zero; they will all invoke the same optimization recipe.
298+
// https://github.com/Microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#optimization
299+
if (hlslOptions.spirvOptimizer)
300+
{
301+
arguments.push_back(L"-O0");
302+
}
271303

272-
// If a custom SPIR-V optimizer is specified, use that instead of DXC's spirv-opt.
273-
// This is how we can get more optimizer options.
274-
//
275-
// Optimization is also delegated to SPIRV-Tools. Right now there are no difference between
276-
// optimization levels greater than zero; they will all invoke the same optimization recipe.
277-
// https://github.com/Microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#optimization
278-
if (hlslOptions.spirvOptimizer)
279-
{
280-
arguments.push_back(L"-O0");
304+
// Debug only values
305+
if (hlslOptions.debugInfoFlags.hasFlags(E_DEBUG_INFO_FLAGS::EDIF_FILE_BIT))
306+
arguments.push_back(L"-fspv-debug=file");
307+
if (hlslOptions.debugInfoFlags.hasFlags(E_DEBUG_INFO_FLAGS::EDIF_SOURCE_BIT))
308+
arguments.push_back(L"-fspv-debug=source");
309+
if (hlslOptions.debugInfoFlags.hasFlags(E_DEBUG_INFO_FLAGS::EDIF_LINE_BIT))
310+
arguments.push_back(L"-fspv-debug=line");
311+
if (hlslOptions.debugInfoFlags.hasFlags(E_DEBUG_INFO_FLAGS::EDIF_TOOL_BIT))
312+
arguments.push_back(L"-fspv-debug=tool");
313+
if (hlslOptions.debugInfoFlags.hasFlags(E_DEBUG_INFO_FLAGS::EDIF_NON_SEMANTIC_BIT))
314+
arguments.push_back(L"-fspv-debug=vulkan-with-source");
281315
}
282316

283-
// Debug only values
284-
if (hlslOptions.debugInfoFlags.hasFlags(E_DEBUG_INFO_FLAGS::EDIF_FILE_BIT))
285-
arguments.push_back(L"-fspv-debug=file");
286-
if (hlslOptions.debugInfoFlags.hasFlags(E_DEBUG_INFO_FLAGS::EDIF_SOURCE_BIT))
287-
arguments.push_back(L"-fspv-debug=source");
288-
if (hlslOptions.debugInfoFlags.hasFlags(E_DEBUG_INFO_FLAGS::EDIF_LINE_BIT))
289-
arguments.push_back(L"-fspv-debug=line");
290-
if (hlslOptions.debugInfoFlags.hasFlags(E_DEBUG_INFO_FLAGS::EDIF_TOOL_BIT))
291-
arguments.push_back(L"-fspv-debug=tool");
292-
if (hlslOptions.debugInfoFlags.hasFlags(E_DEBUG_INFO_FLAGS::EDIF_NON_SEMANTIC_BIT))
293-
arguments.push_back(L"-fspv-debug=vulkan-with-source");
294-
295-
auto compileResult = dxcCompile(
296-
this,
297-
m_dxcCompilerTypes,
317+
auto compileResult = dxcCompile(
298318
newCode,
299-
&arguments[0],
319+
arguments.data(),
300320
arguments.size(),
301321
hlslOptions
302322
);
303323

304-
if (!compileResult.objectBlob)
324+
if (arg_storage)
325+
delete[] arg_storage;
326+
327+
if (!compileResult.begin)
305328
{
306329
return nullptr;
307330
}
308331

309-
auto outSpirv = core::make_smart_refctd_ptr<ICPUBuffer>(compileResult.objectBlob->GetBufferSize());
310-
memcpy(outSpirv->getPointer(), compileResult.objectBlob->GetBufferPointer(), compileResult.objectBlob->GetBufferSize());
332+
auto outSpirv = core::make_smart_refctd_ptr<ICPUBuffer>(compileResult.size);
333+
memcpy(outSpirv->getPointer(), compileResult.begin, compileResult.size);
311334

312335
// Optimizer step
313336
if (hlslOptions.spirvOptimizer)
@@ -322,4 +345,6 @@ void CHLSLCompiler::insertIntoStart(std::string& code, std::ostringstream&& ins)
322345
{
323346
code.insert(0u, ins.str());
324347
}
348+
349+
325350
#endif

0 commit comments

Comments
 (0)