Skip to content

Commit

Permalink
Fixes to pragma wave dxc_compile_flags for hlsl preprocessor
Browse files Browse the repository at this point in the history
  • Loading branch information
Hazardu authored and AnastaZIuk committed Jan 18, 2024
1 parent f68ad87 commit ffbd843
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 43 deletions.
87 changes: 49 additions & 38 deletions src/nbl/asset/utils/CHLSLCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ DxcCompilationResult dxcCompile(const CHLSLCompiler* compiler, nbl::asset::impl:
if ((options.debugInfoFlags.value & sourceEmittingFlags) != CHLSLCompiler::E_DEBUG_INFO_FLAGS::EDIF_NONE)
{
std::ostringstream insertion;
insertion << "//#pragma compile_flags ";
insertion << "#pragma compile_flags ";

std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> conv;
for (uint32_t arg = 0; arg < argCount; arg ++)
Expand Down Expand Up @@ -204,11 +204,11 @@ std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADE
return resolvedString;
}

//std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADER_STAGE& stage, const SPreprocessorOptions& preprocessOptions) const
//{
// std::vector<LPCWSTR> extra_dxc_compile_flags = {};
// return preprocessShader(code, stage, extra_dxc_compile_flags, preprocessOptions);
//}
std::string CHLSLCompiler::preprocessShader(std::string&& code, IShader::E_SHADER_STAGE& stage, const SPreprocessorOptions& preprocessOptions) const
{
std::vector<std::string> extra_dxc_compile_flags = {};
return preprocessShader(std::move(code), stage, extra_dxc_compile_flags, preprocessOptions);
}

core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* code, const IShaderCompiler::SCompilerOptions& options) const
{
Expand Down Expand Up @@ -238,41 +238,47 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
// Set profile two letter prefix based on stage
switch (stage)
{
case asset::IShader::ESS_VERTEX:
targetProfile.replace(0, 2, L"vs");
break;
case asset::IShader::ESS_TESSELLATION_CONTROL:
targetProfile.replace(0, 2, L"ds");
break;
case asset::IShader::ESS_TESSELLATION_EVALUATION:
targetProfile.replace(0, 2, L"hs");
break;
case asset::IShader::ESS_GEOMETRY:
targetProfile.replace(0, 2, L"gs");
break;
case asset::IShader::ESS_FRAGMENT:
targetProfile.replace(0, 2, L"ps");
break;
case asset::IShader::ESS_COMPUTE:
targetProfile.replace(0, 2, L"cs");
break;
case asset::IShader::ESS_TASK:
targetProfile.replace(0, 2, L"as");
break;
case asset::IShader::ESS_MESH:
targetProfile.replace(0, 2, L"ms");
break;
default:
hlslOptions.preprocessorOptions.logger.log("invalid shader stage %i", system::ILogger::ELL_ERROR, stage);
return nullptr;
case asset::IShader::ESS_VERTEX:
targetProfile.replace(0, 2, L"vs");
break;
case asset::IShader::ESS_TESSELLATION_CONTROL:
targetProfile.replace(0, 2, L"ds");
break;
case asset::IShader::ESS_TESSELLATION_EVALUATION:
targetProfile.replace(0, 2, L"hs");
break;
case asset::IShader::ESS_GEOMETRY:
targetProfile.replace(0, 2, L"gs");
break;
case asset::IShader::ESS_FRAGMENT:
targetProfile.replace(0, 2, L"ps");
break;
case asset::IShader::ESS_COMPUTE:
targetProfile.replace(0, 2, L"cs");
break;
case asset::IShader::ESS_TASK:
targetProfile.replace(0, 2, L"as");
break;
case asset::IShader::ESS_MESH:
targetProfile.replace(0, 2, L"ms");
break;
default:
hlslOptions.preprocessorOptions.logger.log("invalid shader stage %i", system::ILogger::ELL_ERROR, stage);
return nullptr;
};


std::wstring* arg_storage = NULL;
std::vector<LPCWSTR> arguments;
if (dxc_compile_flags.size()) {

if (dxc_compile_flags.size()) { // #pragma wave overrides compile flags
size_t arg_size = dxc_compile_flags.size();
arguments = {};
for (size_t i = 0; i < dxc_compile_flags.size(); i++)
arguments.push_back(LPCWSTR(dxc_compile_flags[i].c_str()));
arguments.reserve(arg_size);
arg_storage = new std::wstring[arg_size]; // prevent deallocation before shader compilation
for (size_t i = 0; i < dxc_compile_flags.size(); i++) {
arg_storage[i] = std::wstring(dxc_compile_flags[i].begin(), dxc_compile_flags[i].end());
arguments.push_back(arg_storage[i].c_str());
}
}
else {
arguments = {
Expand Down Expand Up @@ -315,11 +321,14 @@ core::smart_refctd_ptr<ICPUShader> CHLSLCompiler::compileToSPIRV(const char* cod
this,
m_dxcCompilerTypes,
newCode,
&arguments[0],
arguments.data(),
arguments.size(),
hlslOptions
);

if (arg_storage)
delete[] arg_storage;

if (!compileResult.objectBlob)
{
return nullptr;
Expand All @@ -341,4 +350,6 @@ void CHLSLCompiler::insertIntoStart(std::string& code, std::ostringstream&& ins)
{
code.insert(0u, ins.str());
}


#endif
22 changes: 17 additions & 5 deletions src/nbl/asset/utils/waveContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ struct load_to_string final
struct preprocessing_hooks final : public boost::wave::context_policies::default_preprocessing_hooks
{
preprocessing_hooks(const IShaderCompiler::SPreprocessorOptions& _preprocessOptions)
: m_includeFinder(_preprocessOptions.includeFinder), m_logger(_preprocessOptions.logger), m_pragmaStage(IShader::ESS_UNKNOWN), m_dxc_compile_flags_override() {}
: m_includeFinder(_preprocessOptions.includeFinder), m_logger(_preprocessOptions.logger), m_pragmaStage(IShader::ESS_UNKNOWN), m_dxc_compile_flags_override()
{
hash_token_occurences = 0;
}

template <typename ContextT>
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)
Expand All @@ -56,6 +59,7 @@ struct preprocessing_hooks final : public boost::wave::context_policies::default
return false;
}


// interpretation of #pragma's of the form 'wave option[(value)]'
template <typename ContextT, typename ContainerT>
bool interpret_pragma(
Expand All @@ -64,6 +68,7 @@ struct preprocessing_hooks final : public boost::wave::context_policies::default
typename ContextT::token_type const& act_token
)
{
hash_token_occurences++;
auto optionStr = option.get_value().c_str();
if (strcmp(optionStr,"shader_stage")==0)
{
Expand Down Expand Up @@ -98,15 +103,20 @@ struct preprocessing_hooks final : public boost::wave::context_policies::default
return true;
}

if (strcmp(optionStr, "dxc_compile_flags") == 0) {
if (strcmp(optionStr, "dxc_compile_flags") == 0 && hash_token_occurences == 1) {
m_dxc_compile_flags_override.clear();
for (auto valueIter = values.begin(); valueIter != values.end(); valueIter++) {
std::string compiler_option_s = std::string(valueIter->get_value().c_str());
if (compiler_option_s[0] == '"' && compiler_option_s[compiler_option_s.length() - 1] == '"')
compiler_option_s = compiler_option_s.substr(1, compiler_option_s.length() - 2);
// if this compiler flag is encapsulated in quotation marks, strip them
//if (compiler_option_s[0] == '"' && compiler_option_s[compiler_option_s.length() - 1] == '"')
// compiler_option_s = compiler_option_s.substr(1, compiler_option_s.length() - 2);

// if the compiler flag is a separator that is a comma or whitespace, do not add to list of flag overrides
if (compiler_option_s == "," || compiler_option_s == " ")
continue;
m_dxc_compile_flags_override.push_back(compiler_option_s);
}

return true;
}

return false;
Expand All @@ -126,7 +136,9 @@ struct preprocessing_hooks final : public boost::wave::context_policies::default
const IShaderCompiler::CIncludeFinder* m_includeFinder;
system::logger_opt_ptr m_logger;
IShader::E_SHADER_STAGE m_pragmaStage;
int hash_token_occurences;
std::vector<std::string> m_dxc_compile_flags_override;

};

class context : private boost::noncopyable
Expand Down

0 comments on commit ffbd843

Please sign in to comment.