11
11
#include < dxc/dxcapi.h>
12
12
#include < combaseapi.h>
13
13
14
+ #define TCPP_IMPLEMENTATION
15
+ #include < tcpp/source/tcppLibrary.hpp>
16
+ #undef TCPP_IMPLEMENTATION
17
+
14
18
using namespace nbl ;
15
19
using namespace nbl ::asset;
16
20
@@ -36,6 +40,49 @@ CHLSLCompiler::~CHLSLCompiler()
36
40
m_dxcCompiler->Release ();
37
41
}
38
42
43
+ static tcpp::IInputStream* getInputStreamInclude (
44
+ const IShaderCompiler::CIncludeFinder* _inclFinder,
45
+ const system::ISystem* _fs,
46
+ uint32_t _maxInclCnt,
47
+ const char * _requesting_source,
48
+ bool _type // true for #include "string"; false for #include <string>
49
+ )
50
+ {
51
+ std::string res_str;
52
+
53
+ std::filesystem::path relDir;
54
+ const bool reqFromBuiltin = builtin::hasPathPrefix (_requesting_source);
55
+ const bool reqBuiltin = builtin::hasPathPrefix (_requesting_source);
56
+ if (!reqFromBuiltin && !reqBuiltin)
57
+ {
58
+ // While #includ'ing a builtin, one must specify its full path (starting with "nbl/builtin" or "/nbl/builtin").
59
+ // This rule applies also while a builtin is #includ`ing another builtin.
60
+ // While including a filesystem file it must be either absolute path (or relative to any search dir added to asset::iIncludeHandler; <>-type),
61
+ // or path relative to executable's working directory (""-type).
62
+ relDir = std::filesystem::path (_requesting_source).parent_path ();
63
+ }
64
+ std::filesystem::path name = _type ? (relDir / _requesting_source) : (_requesting_source);
65
+
66
+ if (std::filesystem::exists (name) && !reqBuiltin)
67
+ name = std::filesystem::absolute (name);
68
+
69
+ if (_type)
70
+ res_str = _inclFinder->getIncludeRelative (relDir, _requesting_source);
71
+ else // shaderc_include_type_standard
72
+ res_str = _inclFinder->getIncludeStandard (relDir, _requesting_source);
73
+
74
+ if (!res_str.size ()) {
75
+ return nullptr ;
76
+ }
77
+ else {
78
+ // employ encloseWithinExtraInclGuards() in order to prevent infinite loop of (not necesarilly direct) self-inclusions while other # directives (incl guards among them) are disabled
79
+ IShaderCompiler::disableAllDirectivesExceptIncludes (res_str);
80
+ res_str = IShaderCompiler::encloseWithinExtraInclGuards (std::move (res_str), _maxInclCnt, name.string ().c_str ());
81
+ }
82
+
83
+ return new tcpp::StringInputStream (std::move (res_str));
84
+ }
85
+
39
86
CHLSLCompiler::DxcCompilationResult CHLSLCompiler::dxcCompile (std::string& source, LPCWSTR* args, uint32_t argCount, const SOptions& options) const
40
87
{
41
88
if (options.genDebugInfo )
@@ -77,8 +124,8 @@ CHLSLCompiler::DxcCompilationResult CHLSLCompiler::dxcCompile(std::string& sourc
77
124
assert (SUCCEEDED (res));
78
125
79
126
DxcCompilationResult result;
80
- result.errorMessages = std::unique_ptr<IDxcBlobEncoding>( errorBuffer) ;
81
- result.compileResult = std::unique_ptr<IDxcResult>( compileResult) ;
127
+ result.errorMessages = errorBuffer;
128
+ result.compileResult = compileResult;
82
129
result.objectBlob = nullptr ;
83
130
84
131
if (!SUCCEEDED (compilationStatus))
@@ -91,11 +138,42 @@ CHLSLCompiler::DxcCompilationResult CHLSLCompiler::dxcCompile(std::string& sourc
91
138
res = compileResult->GetResult (&resultingBlob);
92
139
assert (SUCCEEDED (res));
93
140
94
- result.objectBlob = std::unique_ptr<IDxcBlob>( resultingBlob) ;
141
+ result.objectBlob = resultingBlob;
95
142
96
143
return result;
97
144
}
98
145
146
+ std::string CHLSLCompiler::preprocessShader (std::string&& code, IShader::E_SHADER_STAGE stage, const SPreprocessorOptions& preprocessOptions) const
147
+ {
148
+ if (preprocessOptions.extraDefines .size ())
149
+ {
150
+ insertExtraDefines (code, preprocessOptions.extraDefines );
151
+ }
152
+ if (preprocessOptions.includeFinder != nullptr )
153
+ {
154
+ tcpp::StringInputStream codeIs = tcpp::StringInputStream (code);
155
+ tcpp::Lexer lexer (codeIs);
156
+ tcpp::Preprocessor proc (
157
+ lexer,
158
+ [](auto errorInfo) {
159
+
160
+ },
161
+ [&](auto path, auto isSystemPath) {
162
+ return getInputStreamInclude (
163
+ preprocessOptions.includeFinder , m_system.get (), preprocessOptions.maxSelfInclusionCount ,
164
+ path.c_str (), !isSystemPath
165
+ );
166
+ }
167
+ );
168
+
169
+ return proc.Process ();
170
+ }
171
+ else
172
+ {
173
+ return code;
174
+ }
175
+ }
176
+
99
177
core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV (const char * code, const IShaderCompiler::SCompilerOptions& options) const
100
178
{
101
179
auto hlslOptions = option_cast (options);
@@ -105,8 +183,8 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
105
183
hlslOptions.preprocessorOptions .logger .log (" code is nullptr" , system::ILogger::ELL_ERROR);
106
184
return nullptr ;
107
185
}
108
-
109
- auto newCode = std::string (code); // preprocessShader(code, hlslOptions.stage, hlslOptions.preprocessorOptions);
186
+
187
+ auto newCode = preprocessShader (code, hlslOptions.stage , hlslOptions.preprocessorOptions );
110
188
111
189
// Suffix is the shader model version
112
190
std::wstring targetProfile (L" XX_6_2" );
@@ -156,7 +234,7 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
156
234
const uint32_t nonDebugArgs = 5 ;
157
235
const uint32_t allArgs = nonDebugArgs + 2 ;
158
236
159
- DxcCompilationResult compileResult = dxcCompile (newCode, &arguments[0 ], hlslOptions.genDebugInfo ? allArgs : nonDebugArgs, hlslOptions);
237
+ auto compileResult = dxcCompile (newCode, &arguments[0 ], hlslOptions.genDebugInfo ? allArgs : nonDebugArgs, hlslOptions);
160
238
161
239
if (!compileResult.objectBlob )
162
240
{
0 commit comments