22// This file is part of the "Nabla Engine".
33// For conditions of distribution and use, see copyright notice in nabla.h
44#include " nbl/asset/utils/CHLSLCompiler.h"
5- #include " nbl/asset/utils/waveContext.h"
65#include " nbl/asset/utils/shadercUtils.h"
76// TODO: review
87#ifdef NBL_EMBED_BUILTIN_RESOURCES
@@ -29,140 +28,14 @@ using Microsoft::WRL::ComPtr;
2928
3029static constexpr const wchar_t * SHADER_MODEL_PROFILE = L" XX_6_7" ;
3130
31+
3232namespace nbl ::asset::impl
3333{
34- struct DXC
35- {
36- ComPtr<IDxcUtils> m_dxcUtils;
37- ComPtr<IDxcCompiler3> m_dxcCompiler;
38- };
39-
40-
41- // for including builtins
42- struct load_file_or_builtin_to_string
43- {
44- template <typename IterContextT>
45- class inner
46- {
47- public:
48- template <typename PositionT>
49- static void init_iterators (IterContextT& iter_ctx, PositionT const & act_pos, boost::wave::language_support language)
50- {
51- using iterator_type = typename IterContextT::iterator_type;
52-
53- std::string filepath (iter_ctx.filename .begin (), iter_ctx.filename .end ());
54- auto inclFinder = iter_ctx.ctx .get_hooks ().m_includeFinder ;
55- if (inclFinder)
56- {
57- std::optional<std::string> result;
58- system::path requestingSourceDir (iter_ctx.ctx .get_current_directory ().string ());
59- if (iter_ctx.type == IterContextT::base_type::file_type::system_header) // is it a sys include (#include <...>)?
60- result = inclFinder->getIncludeStandard (requestingSourceDir, filepath);
61- else // regular #include "..."
62- result = inclFinder->getIncludeRelative (requestingSourceDir, filepath);
63-
64- if (!result)
65- BOOST_WAVE_THROW_CTX (iter_ctx.ctx , boost::wave::preprocess_exception,
66- bad_include_file, iter_ctx.filename .c_str (), act_pos);
67- auto & res_str = *result;
68- iter_ctx.instring = res_str;
69- }
70- iter_ctx.first = iterator_type (
71- iter_ctx.instring .begin (), iter_ctx.instring .end (),
72- PositionT (iter_ctx.filename ), language);
73- iter_ctx.last = iterator_type ();
74- }
75-
76- private:
77- std::string instring;
78- };
79- };
80-
81-
82- struct custom_preprocessing_hooks : public boost ::wave::context_policies::default_preprocessing_hooks
83- {
84-
85- custom_preprocessing_hooks (const IShaderCompiler::SPreprocessorOptions& _preprocessOptions)
86- : m_includeFinder(_preprocessOptions.includeFinder), m_logger(_preprocessOptions.logger), m_pragmaStage(IShader::ESS_UNKNOWN) {}
87-
88- const IShaderCompiler::CIncludeFinder* m_includeFinder;
89- system::logger_opt_ptr m_logger;
90- IShader::E_SHADER_STAGE m_pragmaStage;
91-
92-
93- template <typename ContextT>
94- bool locate_include_file (ContextT& ctx, std::string& file_path, bool is_system, char const * current_name, std::string& dir_path, std::string& native_name)
95- {
96- // on builtin return true
97- dir_path = ctx.get_current_directory ().string ();
98- std::optional<std::string> result;
99- if (is_system) {
100- result = m_includeFinder->getIncludeStandard (dir_path, file_path);
101- dir_path = " " ;
102- }
103- else
104- result = m_includeFinder->getIncludeRelative (dir_path, file_path);
105- if (!result)
106- {
107- m_logger.log (" Pre-processor error: Bad include file.\n '%s' does not exist." , nbl::system::ILogger::ELL_ERROR, file_path.c_str ());
108- return false ;
109- }
110- native_name = file_path;
111- return true ;
112- }
113-
114-
115- // interpretation of #pragma's of the form 'wave option[(value)]'
116- template <typename ContextT, typename ContainerT>
117- bool
118- interpret_pragma (ContextT const & ctx, ContainerT& pending,
119- typename ContextT::token_type const & option, ContainerT const & values,
120- typename ContextT::token_type const & act_token)
121- {
122- auto optionStr = option.get_value ().c_str ();
123- if (strcmp (optionStr, " shader_stage" ) == 0 )
124- {
125- auto valueIter = values.begin ();
126- if (valueIter == values.end ()) {
127- m_logger.log (" Pre-processor error:\n Malformed shader_stage pragma. No shaderstage option given" , nbl::system::ILogger::ELL_ERROR);
128- return false ;
129- }
130- auto shaderStageIdentifier = std::string (valueIter->get_value ().c_str ());
131- core::unordered_map<std::string, IShader::E_SHADER_STAGE> stageFromIdent = {
132- { " vertex" , IShader::ESS_VERTEX },
133- { " fragment" , IShader::ESS_FRAGMENT },
134- { " tesscontrol" , IShader::ESS_TESSELLATION_CONTROL },
135- { " tesseval" , IShader::ESS_TESSELLATION_EVALUATION },
136- { " geometry" , IShader::ESS_GEOMETRY },
137- { " compute" , IShader::ESS_COMPUTE }
138- };
139- auto found = stageFromIdent.find (shaderStageIdentifier);
140- if (found == stageFromIdent.end ())
141- {
142- m_logger.log (" Pre-processor error:\n Malformed shader_stage pragma. Unknown stage '%s'" , nbl::system::ILogger::ELL_ERROR, shaderStageIdentifier);
143- return false ;
144- }
145- valueIter++;
146- if (valueIter != values.end ()) {
147- m_logger.log (" Pre-processor error:\n Malformed shader_stage pragma. Too many arguments" , nbl::system::ILogger::ELL_ERROR);
148- return false ;
149- }
150- m_pragmaStage = found->second ;
151- return true ;
152- }
153- return false ;
154- }
155-
156-
157- template <typename ContextT, typename ContainerT>
158- bool found_error_directive (ContextT const & ctx, ContainerT const & message) {
159- m_logger.log (" Pre-processor error:\n %s" , nbl::system::ILogger::ELL_ERROR, message);
160- return true ;
161- }
162-
163- };
164-
165-
34+ struct DXC
35+ {
36+ ComPtr<IDxcUtils> m_dxcUtils;
37+ ComPtr<IDxcCompiler3> m_dxcCompiler;
38+ };
16639}
16740
16841CHLSLCompiler::CHLSLCompiler (core::smart_refctd_ptr<system::ISystem>&& system)
@@ -182,15 +55,14 @@ CHLSLCompiler::CHLSLCompiler(core::smart_refctd_ptr<system::ISystem>&& system)
18255 };
18356}
18457
185-
18658CHLSLCompiler::~CHLSLCompiler ()
18759{
18860 delete m_dxcCompilerTypes;
18961}
19062
191- class DxcCompilationResult
63+
64+ struct DxcCompilationResult
19265{
193- public:
19466 ComPtr<IDxcBlobEncoding> errorMessages;
19567 ComPtr<IDxcBlob> objectBlob;
19668 ComPtr<IDxcResult> compileResult;
@@ -201,7 +73,6 @@ class DxcCompilationResult
20173 }
20274};
20375
204-
20576DxcCompilationResult dxcCompile (const CHLSLCompiler* compiler, nbl::asset::impl::DXC* dxc, std::string& source, LPCWSTR* args, uint32_t argCount, const CHLSLCompiler::SOptions& options)
20677{
20778 // Append Commandline options into source only if debugInfoFlags will emit source
@@ -276,13 +147,12 @@ DxcCompilationResult dxcCompile(const CHLSLCompiler* compiler, nbl::asset::impl:
276147}
277148
278149
279- using lex_token_t = boost::wave::cpplexer::lex_token<>;
280- using lex_iterator_t = boost::wave::cpplexer::lex_iterator<lex_token_t >;
150+ #include " nbl/asset/utils/waveContext.h"
281151using wave_context_t = nbl::wave::context<std::string::iterator>;
282152
283153std::string CHLSLCompiler::preprocessShader (std::string&& code, IShader::E_SHADER_STAGE& stage, const SPreprocessorOptions& preprocessOptions) const
284154{
285- impl ::custom_preprocessing_hooks hooks (preprocessOptions);
155+ wave ::custom_preprocessing_hooks hooks (preprocessOptions);
286156 wave_context_t context (code.begin (), code.end (), preprocessOptions.sourceIdentifier .data (), hooks);
287157 auto language = boost::wave::support_cpp20 | boost::wave::support_option_preserve_comments | boost::wave::support_option_emit_line_directives;
288158 context.set_language (static_cast <boost::wave::language_support>(language));
@@ -297,9 +167,8 @@ std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADE
297167
298168 // preprocess
299169 std::stringstream stream = std::stringstream ();
300- for (auto i = context.begin (); i != context.end (); i++) {
170+ for (auto i= context.begin (); i!= context.end (); i++)
301171 stream << i->get_value ();
302- }
303172 core::string resolvedString = stream.str ();
304173
305174 // for debugging cause MSVC doesn't like to show more than 21k LoC in TextVisualizer
@@ -314,8 +183,10 @@ std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADE
314183 succ.getBytesProcessed (true );
315184 }
316185 }
186+
317187 if (context.get_hooks ().m_pragmaStage != IShader::ESS_UNKNOWN)
318188 stage = context.get_hooks ().m_pragmaStage ;
189+
319190 return resolvedString;
320191}
321192
@@ -442,84 +313,4 @@ void CHLSLCompiler::insertIntoStart(std::string& code, std::ostringstream&& ins)
442313{
443314 code.insert (0u , ins.str ());
444315}
445-
446-
447-
448-
449- template <> inline bool boost::wave::impl::pp_iterator_functor<wave_context_t >::on_include_helper(char const * f, char const * s,
450- bool is_system, bool include_next)
451- {
452- namespace fs = boost::filesystem;
453-
454- // try to locate the given file, searching through the include path lists
455- std::string file_path (s);
456- std::string dir_path;
457- #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
458- char const * current_name = include_next ? iter_ctx->real_filename .c_str () : 0 ;
459- #else
460- char const * current_name = 0 ; // never try to match current file name
461- #endif
462-
463- // call the 'found_include_directive' hook function
464- if (ctx.get_hooks ().found_include_directive (ctx.derived (), f, include_next))
465- return true ; // client returned false: skip file to include
466-
467- file_path = util::impl::unescape_lit (file_path);
468- std::string native_path_str;
469-
470- if (!ctx.get_hooks ().locate_include_file (ctx, file_path, is_system,
471- current_name, dir_path, native_path_str))
472- {
473- BOOST_WAVE_THROW_CTX (ctx, preprocess_exception, bad_include_file,
474- file_path.c_str (), act_pos);
475- return false ;
476- }
477-
478- // test, if this file is known through a #pragma once directive
479- #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
480- if (!ctx.has_pragma_once (native_path_str))
481- #endif
482- {
483- // the new include file determines the actual current directory
484- ctx.set_current_directory (native_path_str.c_str ());
485-
486- // preprocess the opened file
487- boost::shared_ptr<base_iteration_context_type> new_iter_ctx (
488- new iteration_context_type (ctx, native_path_str.c_str (), act_pos,
489- boost::wave::enable_prefer_pp_numbers (ctx.get_language ()),
490- is_system ? base_iteration_context_type::system_header :
491- base_iteration_context_type::user_header));
492-
493- // call the include policy trace function
494- ctx.get_hooks ().opened_include_file (ctx.derived (), dir_path, file_path,
495- is_system);
496-
497- // store current file position
498- iter_ctx->real_relative_filename = ctx.get_current_relative_filename ().c_str ();
499- iter_ctx->filename = act_pos.get_file ();
500- iter_ctx->line = act_pos.get_line ();
501- iter_ctx->if_block_depth = ctx.get_if_block_depth ();
502- iter_ctx->emitted_lines = (unsigned int )(-1 ); // force #line directive
503-
504- // push the old iteration context onto the stack and continue with the new
505- ctx.push_iteration_context (act_pos, iter_ctx);
506- iter_ctx = new_iter_ctx;
507- seen_newline = true ; // fake a newline to trigger pp_directive
508- must_emit_line_directive = true ;
509-
510- act_pos.set_file (iter_ctx->filename ); // initialize file position
511- #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
512- fs::path rfp (iter_ctx->real_filename .c_str ());
513- std::string real_filename (rfp.string ());
514- ctx.set_current_filename (real_filename.c_str ());
515- #endif
516-
517- ctx.set_current_relative_filename (dir_path.c_str ());
518- iter_ctx->real_relative_filename = dir_path.c_str ();
519-
520- act_pos.set_line (iter_ctx->line );
521- act_pos.set_column (0 );
522- }
523- return true ;
524- }
525- #endif
316+ #endif
0 commit comments