2020#include < combaseapi.h>
2121#include < sstream>
2222#include < dxc/dxcapi.h>
23- #include < boost/algorithm/string/predicate.hpp>
24- #include < boost/algorithm/string/trim.hpp>
2523
2624using namespace nbl ;
2725using namespace nbl ::asset;
@@ -363,7 +361,98 @@ namespace nbl::wave
363361 extern nbl::core::string preprocess (std::string& code, const IShaderCompiler::SPreprocessorOptions& preprocessOptions, bool withCaching, std::function<void (nbl::wave::context&)> post);
364362}
365363
366- std::string CHLSLCompiler::preprocessShader (std::string&& code, IShader::E_SHADER_STAGE& stage, const SPreprocessorOptions& preprocessOptions, std::vector<std::string>& dxc_compile_flags_override, std::vector<CCache::SEntry::SPreprocessingDependency>* dependencies) const
364+ static bool isHorizontalWhitespace (const char c)
365+ {
366+ return c == ' ' || c == ' \t ' || c == ' \r ' || c == ' \v ' || c == ' \f ' ;
367+ }
368+
369+ static bool consumeIdentifier (std::string_view line, size_t & pos, const std::string_view identifier)
370+ {
371+ if (line.substr (pos, identifier.size ()) != identifier)
372+ return false ;
373+
374+ const size_t end = pos + identifier.size ();
375+ if (end < line.size ())
376+ {
377+ const char next = line[end];
378+ if ((next >= ' a' && next <= ' z' ) || (next >= ' A' && next <= ' Z' ) || (next >= ' 0' && next <= ' 9' ) || next == ' _' )
379+ return false ;
380+ }
381+
382+ pos = end;
383+ return true ;
384+ }
385+
386+ static void normalizeLegacyShaderStagePragmas (std::string& code)
387+ {
388+ std::string normalized;
389+ normalized.reserve (code.size ());
390+
391+ size_t lineStart = 0u ;
392+ while (lineStart < code.size ())
393+ {
394+ const size_t lineEnd = code.find (' \n ' , lineStart);
395+ const bool hasNewline = lineEnd != std::string::npos;
396+ const size_t lineSize = hasNewline ? (lineEnd - lineStart) : (code.size () - lineStart);
397+ const std::string_view line (code.data () + lineStart, lineSize);
398+
399+ size_t pos = 0u ;
400+ while (pos < line.size () && isHorizontalWhitespace (line[pos]))
401+ ++pos;
402+
403+ bool normalizedLegacyPragma = false ;
404+ if (pos < line.size () && line[pos] == ' #' )
405+ {
406+ ++pos;
407+ while (pos < line.size () && isHorizontalWhitespace (line[pos]))
408+ ++pos;
409+
410+ if (consumeIdentifier (line, pos, " pragma" ))
411+ {
412+ while (pos < line.size () && isHorizontalWhitespace (line[pos]))
413+ ++pos;
414+
415+ const size_t pragmaArgumentPos = pos;
416+ if (consumeIdentifier (line, pos, " shader_stage" ))
417+ normalizedLegacyPragma = true ;
418+ else
419+ pos = pragmaArgumentPos;
420+ }
421+ }
422+
423+ if (normalizedLegacyPragma)
424+ {
425+ normalized.append (line.substr (0u , pos - std::string_view (" shader_stage" ).size ()));
426+ normalized += " wave " ;
427+ normalized.append (line.substr (pos - std::string_view (" shader_stage" ).size ()));
428+ }
429+ else
430+ {
431+ normalized.append (line);
432+ }
433+
434+ if (hasNewline)
435+ normalized.push_back (' \n ' );
436+
437+ lineStart = hasNewline ? (lineEnd + 1u ) : code.size ();
438+ }
439+
440+ code = std::move (normalized);
441+ }
442+
443+ static void ensureTrailingNewline (std::string& code)
444+ {
445+ if (!code.empty () && code.back () != ' \n ' && code.back () != ' \r ' )
446+ code.push_back (' \n ' );
447+ }
448+
449+ static std::string preprocessShaderImpl (
450+ std::string&& code,
451+ IShader::E_SHADER_STAGE& stage,
452+ const CHLSLCompiler::SPreprocessorOptions& preprocessOptions,
453+ std::vector<std::string>& dxc_compile_flags_override,
454+ std::vector<IShaderCompiler::CCache::SEntry::SPreprocessingDependency>* dependencies,
455+ system::ISystem* system)
367456{
368457 const bool depfileEnabled = preprocessOptions.depfile ;
369458 if (depfileEnabled)
@@ -375,23 +464,13 @@ std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADE
375464 }
376465 }
377466
378- std::vector<CCache::SEntry::SPreprocessingDependency> localDependencies;
467+ std::vector<IShaderCompiler:: CCache::SEntry::SPreprocessingDependency> localDependencies;
379468 auto * dependenciesOut = dependencies;
380469 if (depfileEnabled && !dependenciesOut)
381470 dependenciesOut = &localDependencies;
382471
383- // HACK: we do a pre-pre-process here to add \n after every #pragma to neutralize boost::wave's actions
384- // See https://github.com/Devsh-Graphics-Programming/Nabla/issues/746
385- size_t line_index = 0 ;
386- for (size_t i = 0 ; i < code.size (); i++) {
387- if (code[i] == ' \n ' ) {
388- auto line = code.substr (line_index, i - line_index);
389- boost::trim (line);
390- if (boost::starts_with (line, " #pragma" ))
391- code.insert (i++, 1 , ' \n ' );
392- line_index = i;
393- }
394- }
472+ normalizeLegacyShaderStagePragmas (code);
473+ ensureTrailingNewline (code);
395474
396475 // preprocess
397476 core::string resolvedString = nbl::wave::preprocess (code, preprocessOptions, bool (dependenciesOut),
@@ -409,19 +488,6 @@ std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADE
409488 }
410489 );
411490
412- // for debugging cause MSVC doesn't like to show more than 21k LoC in TextVisualizer
413- if constexpr (false )
414- {
415- system::ISystem::future_t <core::smart_refctd_ptr<system::IFile>> future;
416- m_system->createFile (future,system::path (preprocessOptions.sourceIdentifier ).parent_path ()/" preprocessed.hlsl" ,system::IFileBase::ECF_WRITE);
417- if (auto file=future.acquire (); file&&bool (*file))
418- {
419- system::IFile::success_t succ;
420- (*file)->write (succ,resolvedString.data (),0 ,resolvedString.size ()+1 );
421- succ.getBytesProcessed (true );
422- }
423- }
424-
425491 if (resolvedString.empty ())
426492 return resolvedString;
427493
@@ -433,14 +499,19 @@ std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADE
433499 params.sourceIdentifier = preprocessOptions.sourceIdentifier ;
434500 if (!params.sourceIdentifier .empty ())
435501 params.workingDirectory = std::filesystem::path (std::string (params.sourceIdentifier )).parent_path ();
436- params.system = m_system. get () ;
502+ params.system = system ;
437503 if (!IShaderCompiler::writeDepfile (params, *dependenciesOut, preprocessOptions.includeFinder , preprocessOptions.logger ))
438504 return {};
439505 }
440506
441507 return resolvedString;
442508}
443509
510+ std::string CHLSLCompiler::preprocessShader (std::string&& code, IShader::E_SHADER_STAGE& stage, const SPreprocessorOptions& preprocessOptions, std::vector<std::string>& dxc_compile_flags_override, std::vector<CCache::SEntry::SPreprocessingDependency>* dependencies) const
511+ {
512+ return preprocessShaderImpl (std::move (code), stage, preprocessOptions, dxc_compile_flags_override, dependencies, m_system.get ());
513+ }
514+
444515std::string CHLSLCompiler::preprocessShader (std::string&& code, IShader::E_SHADER_STAGE& stage, const SPreprocessorOptions& preprocessOptions, std::vector<CCache::SEntry::SPreprocessingDependency>* dependencies) const
445516{
446517 std::vector<std::string> extra_dxc_compile_flags = {};
0 commit comments