@@ -95,109 +95,118 @@ CHLSLCompiler::~CHLSLCompiler()
9595static void try_upgrade_hlsl_version (std::vector<std::wstring>& arguments, system::logger_opt_ptr& logger)
9696{
9797 auto stageArgumentPos = std::find (arguments.begin (), arguments.end (), L" -HV" );
98- if (stageArgumentPos != arguments.end ()) {
99- auto index = stageArgumentPos - arguments.begin () + 1 ; // -HV XXXXX, get index of second
100- std::wstring version = arguments[index];
101- if (!isalpha (version.back ()) && version.length () >= 4 && std::stoi (version) < 2021 )
102- arguments[index] = L" 2021" ;
98+ if (stageArgumentPos != arguments.end () && stageArgumentPos + 1 != arguments.end ())
99+ {
100+ std::wstring version = *(++stageArgumentPos);
101+ if (!isalpha (version.back ()))
102+ {
103+ try
104+ {
105+ if (version.length () != 4 )
106+ throw std::invalid_argument (" -HV argument is of incorrect length, expeciting 4. Fallign back to 2021" );
107+ if (std::stoi (version) < 2021 )
108+ throw std::invalid_argument (" -HV argument is too low" );
109+ }
110+ catch (const std::exception& ex)
111+ {
112+ version = L" 2021" ;
113+ }
114+ }
115+ *stageArgumentPos = version;
103116 }
104- else {
117+ else
118+ {
105119 logger.log (" Compile flag error: Required compile flag not found -HV. Force enabling -HV 202x, as it is required by Nabla." , system::ILogger::ELL_WARNING);
106120 arguments.push_back (L" -HV" );
107121 arguments.push_back (L" 202x" );
108122 }
109123}
110124
111-
112125static void try_upgrade_shader_stage (std::vector<std::wstring>& arguments, asset::IShader::E_SHADER_STAGE shaderStageOverrideFromPragma, system::logger_opt_ptr& logger) {
113-
114- constexpr int MajorReqVersion = 6 ,
115- MinorReqVersion = 7 ;
126+
127+ constexpr int MajorReqVersion = 6 , MinorReqVersion = 7 ;
116128 auto overrideStageStr = ShaderStageToString (shaderStageOverrideFromPragma);
117- auto foundShaderStageArgument = std::find (arguments.begin (), arguments.end (), L" -T" );
118- if (foundShaderStageArgument != arguments.end () && foundShaderStageArgument + 1 != arguments.end ()) {
119- auto foundShaderStageArgumentValueIdx = foundShaderStageArgument - arguments.begin () + 1 ;
120- std::wstring s = arguments[foundShaderStageArgumentValueIdx];
129+ if (shaderStageOverrideFromPragma != IShader::ESS_UNKNOWN && !overrideStageStr)
130+ {
131+ logger.log (" Invalid shader stage with int value '%i'.\n This value does not have a known string representation." ,
132+ system::ILogger::ELL_ERROR, shaderStageOverrideFromPragma);
133+ return ;
134+ }
135+ bool setDefaultValue = true ;
136+ auto foundShaderStageArgument = std::find (arguments.begin (), arguments.end (), L" -T" );
137+ if (foundShaderStageArgument != arguments.end () && foundShaderStageArgument +1 != arguments.end ()) {
138+ auto foundShaderStageArgumentValueIdx = foundShaderStageArgument - arguments.begin () + 1 ;
139+ std::wstring stageStr;
140+ std::wstring s = arguments[foundShaderStageArgumentValueIdx];
121141 if (s.length () >= 6 ) {
122- std::wstring stageStr, majorVersionString, minorVersionString;
123142 std::vector<std::wstring::iterator> underscorePositions = {};
124143 auto it = std::find (s.begin (), s.end (), ' _' );
125144 while (it != s.end ()) {
126145 underscorePositions.push_back (it);
127146 it = std::find (it + 1 , s.end (), ' _' );
128147 }
129148
130- // Bad input check
131- if (underscorePositions.size () < 2 )
132- {
133- logger.log (" Incorrect -T argument value.\n Expecting string with at least 2 '_' delimiters: between shader stage, version major and version minor." ,
134- system::ILogger::ELL_ERROR);
135- return ;
136- }
137-
138- // Stage
139- stageStr = std::wstring (s.begin (), underscorePositions[0 ]);
140- if (shaderStageOverrideFromPragma != IShader::ESS_UNKNOWN) // replace first 2 characters if shaderStageOverrideFromPragma != Unknown
141- {
142- if (!overrideStageStr) {
143- logger.log (" Invalid shader stage with int value '%i'.\n This value does not have a known string representation." ,
144- system::ILogger::ELL_ERROR, shaderStageOverrideFromPragma);
149+ if (underscorePositions.size () == 2 )
150+ {
151+ stageStr = shaderStageOverrideFromPragma != IShader::ESS_UNKNOWN ? std::wstring (overrideStageStr) : std::wstring (s.begin (), underscorePositions[0 ]);
152+ // Version
153+ std::wstring majorVersionString, minorVersionString;
154+ int size = underscorePositions.size ();
155+ auto secondLastUnderscore = underscorePositions[size - 2 ];
156+ auto lastUnderscore = underscorePositions[size - 1 ];
157+ majorVersionString = std::wstring (secondLastUnderscore + 1 , lastUnderscore);
158+ minorVersionString = std::wstring (lastUnderscore + 1 , s.end ());
159+ try
160+ {
161+ int major = std::stoi (majorVersionString);
162+ int minor = std::stoi (minorVersionString);
163+ if (major < MajorReqVersion || (major == MajorReqVersion && minor < MinorReqVersion))
164+ {
165+ // Overwrite the version
166+ logger.log (" Upgrading shader stage version number to %i %i" , system::ILogger::ELL_DEBUG, MajorReqVersion, MinorReqVersion);
167+ arguments[foundShaderStageArgumentValueIdx] = stageStr + L" _" + std::to_wstring (MajorReqVersion) + L" _" + std::to_wstring (MinorReqVersion);
168+ }
169+ else
170+ {
171+ // keep the version as it was
172+ arguments[foundShaderStageArgumentValueIdx] = stageStr + L" _" + majorVersionString + L" _" + minorVersionString;
173+ }
145174 return ;
146175 }
147- stageStr = std::wstring (overrideStageStr);
148- }
149-
150- // Version
151- int size = underscorePositions.size ();
152- auto secondLastUnderscore = underscorePositions[size - 2 ];
153- auto lastUnderscore = underscorePositions[size - 1 ];
154- majorVersionString = std::wstring (secondLastUnderscore + 1 , lastUnderscore);
155- minorVersionString = std::wstring (lastUnderscore + 1 , s.end ());
156- try
157- {
158- int major = std::stoi (majorVersionString);
159- int minor = std::stoi (minorVersionString);
160- if (major < MajorReqVersion || (major == MajorReqVersion && minor < MinorReqVersion))
176+ catch (const std::invalid_argument& e)
161177 {
162- // Overwrite the version
163- logger.log (" Upgrading shader stage version number to %i %i" , system::ILogger::ELL_DEBUG, MajorReqVersion, MinorReqVersion);
164- arguments[foundShaderStageArgumentValueIdx] = stageStr + L" _" + std::to_wstring (MajorReqVersion) + L" _" + std::to_wstring (MinorReqVersion);
178+ logger.log (" Parsing shader version failed, invalid argument exception: %s" , system::ILogger::ELL_ERROR, e.what ());
165179 }
166- else
180+ catch ( const std::out_of_range& e)
167181 {
168- // keep the version as it was
169- arguments[foundShaderStageArgumentValueIdx] = stageStr + L" _" + majorVersionString + L" _" + minorVersionString;
182+ logger.log (" Parsing shader version failed, out of range exception: %s" , system::ILogger::ELL_ERROR, e.what ());
170183 }
171- return ;
172- }
173- catch (const std::invalid_argument& e) {
174- logger.log (" Parsing shader version failed, invalid argument exception: %s" , system::ILogger::ELL_ERROR, e.what ());
175-
176184 }
177- catch (const std::out_of_range& e) {
178- logger.log (" Parsing shader version failed, out of range exception: %s" , system::ILogger::ELL_ERROR, e.what ());
185+ else
186+ {
187+ logger.log (" Incorrect -T argument value.\n Expecting string with exactly 2 '_' delimiters: between shader stage, version major and version minor." ,
188+ system::ILogger::ELL_ERROR);
179189 }
180-
181- // In case of an exception
182- arguments[foundShaderStageArgumentValueIdx] = stageStr + L" _" + std::to_wstring (MajorReqVersion) + L" _" + std::to_wstring (MinorReqVersion);
183- return ;
184190 }
185- else {
191+ else
192+ {
186193 logger.log (" invalid shader stage '%s' argument, expecting a string of length >= 6 " , system::ILogger::ELL_ERROR, s);
187- }
188- }
189- else if (overrideStageStr) { // in case of no -T
194+ }
195+ // In case of an exception or str < 6
196+ arguments[foundShaderStageArgumentValueIdx] = stageStr + L" _" + std::to_wstring (MajorReqVersion) + L" _" + std::to_wstring (MinorReqVersion);
197+ setDefaultValue = false ;
198+ }
199+ if (setDefaultValue)
200+ {
201+ // in case of no -T
190202 // push back default values for -T argument
191203 // can be safely pushed to the back of argument list as output files should be evicted from args before passing to this func
192204 // leaving only compiler flags
193205 arguments.push_back (L" -T" );
194206 arguments.push_back (std::wstring (overrideStageStr) + L" _" + std::to_wstring (MajorReqVersion) + L" _" + std::to_wstring (MinorReqVersion));
195207 }
196-
197-
198208}
199209
200-
201210static void add_required_arguments_if_not_present (std::vector<std::wstring>& arguments, system::logger_opt_ptr &logger) {
202211 auto set = std::unordered_set<std::wstring>();
203212 for (int i = 0 ; i < arguments.size (); i++)
@@ -384,19 +393,7 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
384393 populate_arguments_with_type_conversion (arguments, hlslOptions.dxcOptions , logger);
385394 }
386395 else { // lastly default arguments
387-
388- // Set profile two letter prefix based on stage
389- auto stageStr = ShaderStageToString (stage);
390- if (!stageStr) {
391- logger.log (" invalid shader stage %i" , system::ILogger::ELL_ERROR, stage);
392- return nullptr ;
393- }
394- targetProfile.replace (0 , 2 , stageStr);
395-
396- arguments = {
397- L" -HV" , L" 202x" ,
398- L" -T" , targetProfile.c_str (),
399- };
396+ arguments = {};
400397 for (size_t i = 0 ; i < RequiredArgumentCount; i++)
401398 arguments.push_back (RequiredArguments[i]);
402399 // If a custom SPIR-V optimizer is specified, use that instead of DXC's spirv-opt.
@@ -406,21 +403,30 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
406403 // optimization levels greater than zero; they will all invoke the same optimization recipe.
407404 // https://github.com/Microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#optimization
408405 if (hlslOptions.spirvOptimizer )
409- {
410406 arguments.push_back (L" -O0" );
411- }
412-
407+ }
408+ if (dxc_compile_flags.empty ())
409+ {
410+ auto set = std::unordered_set<std::wstring>();
411+ for (int i = 0 ; i < arguments.size (); i++)
412+ set.insert (arguments[i]);
413+ auto add_if_missing = [&arguments, &set, logger](std::wstring flag) {
414+ if (set.find (flag) == set.end ()) {
415+ logger.log (" Adding debug flag %ls" , nbl::system::ILogger::ELL_DEBUG, flag.c_str ());
416+ arguments.push_back (flag);
417+ }
418+ };
413419 // Debug only values
414420 if (hlslOptions.debugInfoFlags .hasFlags (E_DEBUG_INFO_FLAGS::EDIF_FILE_BIT))
415- arguments. push_back (L" -fspv-debug=file" );
421+ add_if_missing (L" -fspv-debug=file" );
416422 if (hlslOptions.debugInfoFlags .hasFlags (E_DEBUG_INFO_FLAGS::EDIF_SOURCE_BIT))
417- arguments. push_back (L" -fspv-debug=source" );
423+ add_if_missing (L" -fspv-debug=source" );
418424 if (hlslOptions.debugInfoFlags .hasFlags (E_DEBUG_INFO_FLAGS::EDIF_LINE_BIT))
419- arguments. push_back (L" -fspv-debug=line" );
425+ add_if_missing (L" -fspv-debug=line" );
420426 if (hlslOptions.debugInfoFlags .hasFlags (E_DEBUG_INFO_FLAGS::EDIF_TOOL_BIT))
421- arguments. push_back (L" -fspv-debug=tool" );
427+ add_if_missing (L" -fspv-debug=tool" );
422428 if (hlslOptions.debugInfoFlags .hasFlags (E_DEBUG_INFO_FLAGS::EDIF_NON_SEMANTIC_BIT))
423- arguments. push_back (L" -fspv-debug=vulkan-with-source" );
429+ add_if_missing (L" -fspv-debug=vulkan-with-source" );
424430 }
425431
426432 try_upgrade_shader_stage (arguments, stage, logger);
0 commit comments