@@ -70,7 +70,83 @@ CHLSLCompiler::~CHLSLCompiler()
70
70
delete m_dxcCompilerTypes;
71
71
}
72
72
73
- CHLSLCompiler::SdxcCompileResult CHLSLCompiler::dxcCompile (std::string& source, LPCWSTR* args, uint32_t argCount, const CHLSLCompiler::SOptions& options) const
73
+
74
+ static void try_upgrade_hlsl_version (std::vector<std::wstring>& arguments)
75
+ {
76
+ auto foundShaderStageArgument = std::find (arguments.begin (), arguments.end (), L" -HV" );
77
+ if (foundShaderStageArgument != arguments.end ()) {
78
+ auto foundShaderStageArgumentValueIdx = foundShaderStageArgument - arguments.begin () + 1 ;
79
+ std::wstring version = arguments[foundShaderStageArgumentValueIdx];
80
+ if (version.length () >= 4 && (version[2 ] < ' 2' || (version[2 ] == ' 2' && version[3 ] <= ' 0' )))
81
+ arguments[foundShaderStageArgumentValueIdx] = L" 2021" ;
82
+ }
83
+ }
84
+
85
+
86
+ static void try_upgrade_shader_stage (std::vector<std::wstring> &arguments) {
87
+ auto foundShaderStageArgument = std::find (arguments.begin (), arguments.end (), L" -T" );
88
+ if (foundShaderStageArgument != arguments.end ()) {
89
+ auto foundShaderStageArgumentValueIdx = foundShaderStageArgument - arguments.begin () + 1 ;
90
+ std::wstring targetProfile = arguments[foundShaderStageArgumentValueIdx];
91
+ if (targetProfile.length () >= 6 ) {
92
+ int argument_version = (targetProfile[3 ] - ' 0' ) * 10 + (targetProfile[5 ] - ' 0' );
93
+ if (argument_version < 67 )
94
+ {
95
+ targetProfile.replace (3 , 3 , L" 6_7" );
96
+ arguments[foundShaderStageArgumentValueIdx] = targetProfile;
97
+ }
98
+ }
99
+ }
100
+ }
101
+
102
+
103
+ static void add_required_arguments_if_not_present (std::vector<std::wstring>& arguments, system::logger_opt_ptr &logger) {
104
+ constexpr int required_arg_size = 8 ;
105
+ std::wstring required_arguments[] = {
106
+ L" -spirv" ,
107
+ L" -Zpr" ,
108
+ L" -enable-16bit-types" ,
109
+ L" -fvk-use-scalar-layout" ,
110
+ L" -Wno-c++11-extensions" ,
111
+ L" -Wno-c++1z-extensions" ,
112
+ L" -Wno-gnu-static-float-init" ,
113
+ L" -fspv-target-env=vulkan1.3"
114
+ };
115
+ bool found_arg_flags[required_arg_size]{};
116
+ int argc = arguments.size ();
117
+ for (int i = 0 ; i < argc; i++)
118
+ {
119
+ for (int j = 0 ; j < required_arg_size; j++)
120
+ {
121
+ if (arguments[i] == required_arguments[j]) {
122
+ found_arg_flags[j] = true ;
123
+ break ;
124
+ }
125
+ }
126
+ }
127
+ for (int j = 0 ; j < required_arg_size; j++)
128
+ {
129
+ if (!found_arg_flags[j]) {
130
+ logger.log (" Required compile flag not found %ls. This flag will be force enabled as it is required by Nabla." , system::ILogger::ELL_WARNING, required_arguments[j]);
131
+ arguments.push_back (required_arguments[j]);
132
+ }
133
+ }
134
+ }
135
+
136
+
137
+ template <typename T>
138
+ static void populate_arguments_with_type_conversion (std::vector<std::wstring> &arguments, T &iterable_collection, system::logger_opt_ptr &logger) {
139
+ size_t arg_size = iterable_collection.size ();
140
+ arguments.reserve (arg_size);
141
+ for (auto it = iterable_collection.begin (); it != iterable_collection.end (); it++) {
142
+ auto temp = std::wstring (it->begin (), it->end ()); // *it is string, therefore create wstring
143
+ arguments.push_back (temp);
144
+ }
145
+ add_required_arguments_if_not_present (arguments, logger);
146
+ }
147
+
148
+
149
+ static DxcCompilationResult dxcCompile (const CHLSLCompiler* compiler, nbl::asset::impl::DXC* dxc, std::string& source, LPCWSTR* args, uint32_t argCount, const CHLSLCompiler::SOptions& options)
74
150
{
75
151
// Append Commandline options into source only if debugInfoFlags will emit source
76
152
auto sourceEmittingFlags =
@@ -90,9 +166,8 @@ CHLSLCompiler::SdxcCompileResult CHLSLCompiler::dxcCompile(std::string& source,
90
166
}
91
167
92
168
insertion << " )\n " ;
93
- insertIntoStart (source, std::move (insertion));
169
+ compiler-> insertIntoStart (source, std::move (insertion));
94
170
}
95
- nbl::asset::impl::DXC* dxc = m_dxcCompilerTypes;
96
171
ComPtr<IDxcBlobEncoding> src;
97
172
auto res = dxc->m_dxcUtils ->CreateBlob (reinterpret_cast <const void *>(source.data ()), source.size (), CP_UTF8, &src);
98
173
assert (SUCCEEDED (res));
@@ -131,7 +206,7 @@ CHLSLCompiler::SdxcCompileResult CHLSLCompiler::dxcCompile(std::string& source,
131
206
else
132
207
{
133
208
options.preprocessorOptions .logger .log (" DXC Compilation Failed:\n %s" , system::ILogger::ELL_ERROR, errorMessagesString.c_str ());
134
- return { nullptr , 0 } ;
209
+ return result ;
135
210
}
136
211
137
212
ComPtr<IDxcBlob> resultingBlob;
@@ -140,7 +215,7 @@ CHLSLCompiler::SdxcCompileResult CHLSLCompiler::dxcCompile(std::string& source,
140
215
141
216
result.objectBlob = resultingBlob;
142
217
143
- return { ( uint8_t *) result. objectBlob -> GetBufferPointer (), result. objectBlob -> GetBufferSize () } ;
218
+ return result;
144
219
}
145
220
146
221
@@ -263,21 +338,15 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
263
338
hlslOptions.preprocessorOptions .logger .log (" invalid shader stage %i" , system::ILogger::ELL_ERROR, stage);
264
339
return nullptr ;
265
340
};
266
-
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
- }
341
+
342
+ std::vector<std::wstring> arguments = {};
343
+ if (dxc_compile_flags.size ()) { // #pragma dxc_compile_flags takes priority
344
+ populate_arguments_with_type_conversion (arguments, dxc_compile_flags, hlslOptions.preprocessorOptions .logger );
279
345
}
280
- else {
346
+ else if (hlslOptions.dxcOptions .size ()) { // second in order of priority is command line arguments
347
+ populate_arguments_with_type_conversion (arguments, hlslOptions.dxcOptions , hlslOptions.preprocessorOptions .logger );
348
+ }
349
+ else { // lastly default arguments
281
350
arguments = {
282
351
L" -spirv" ,
283
352
L" -HV" , L" 202x" ,
@@ -314,29 +383,35 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
314
383
arguments.push_back (L" -fspv-debug=vulkan-with-source" );
315
384
}
316
385
386
+ try_upgrade_shader_stage (arguments);
387
+ try_upgrade_hlsl_version (arguments);
388
+
389
+ uint32_t argc = arguments.size ();
390
+ LPCWSTR* argsArray = new LPCWSTR[argc];
391
+ for (size_t i = 0 ; i < argc; i++)
392
+ argsArray[i] = arguments[i].c_str ();
393
+
317
394
auto compileResult = dxcCompile (
395
+ this ,
396
+ m_dxcCompilerTypes,
318
397
newCode,
319
- arguments. data () ,
320
- arguments. size () ,
398
+ argsArray ,
399
+ argc ,
321
400
hlslOptions
322
401
);
323
402
324
- if (arg_storage)
325
- delete[] arg_storage;
326
-
327
- if (!compileResult.begin )
403
+ if (!compileResult.objectBlob )
328
404
{
329
405
return nullptr ;
330
406
}
331
407
332
- auto outSpirv = core::make_smart_refctd_ptr<ICPUBuffer>(compileResult.size );
333
- memcpy (outSpirv->getPointer (), compileResult.begin , compileResult.size );
408
+ auto outSpirv = core::make_smart_refctd_ptr<ICPUBuffer>(compileResult.objectBlob -> GetBufferSize () );
409
+ memcpy (outSpirv->getPointer (), compileResult.objectBlob -> GetBufferPointer () , compileResult.objectBlob -> GetBufferSize () );
334
410
335
411
// Optimizer step
336
412
if (hlslOptions.spirvOptimizer )
337
413
outSpirv = hlslOptions.spirvOptimizer ->optimize (outSpirv.get (), hlslOptions.preprocessorOptions .logger );
338
414
339
-
340
415
return core::make_smart_refctd_ptr<asset::ICPUShader>(std::move (outSpirv), stage, IShader::E_CONTENT_TYPE::ECT_SPIRV, hlslOptions.preprocessorOptions .sourceIdentifier .data ());
341
416
}
342
417
0 commit comments