Skip to content

Commit 68e2e20

Browse files
authored
Merge pull request #970 from Devsh-Graphics-Programming/nsc_preprocess_only
Add NSC flag to allow for preprocessing without compilation
2 parents bea9962 + 4a14db7 commit 68e2e20

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

tools/nsc/main.cpp

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ class ShaderCompiler final : public system::IApplicationFramework
153153
});
154154
};
155155

156+
auto preprocessOnly = findOutputFlag("-P") != m_arguments.end();
156157
auto output_flag_pos_fc = findOutputFlag("-Fc");
157158
auto output_flag_pos_fo = findOutputFlag("-Fo");
158159
if (output_flag_pos_fc != m_arguments.end() && output_flag_pos_fo != m_arguments.end()) {
@@ -195,7 +196,8 @@ class ShaderCompiler final : public system::IApplicationFramework
195196
return false;
196197
}
197198

198-
m_logger->log("Compiled shader code will be saved to " + output_filepath, ILogger::ELL_INFO);
199+
std::string outputType = preprocessOnly ? "Preprocessed" : "Compiled";
200+
m_logger->log(outputType + " shader code will be saved to " + output_filepath, ILogger::ELL_INFO);
199201
}
200202

201203
#ifndef NBL_EMBED_BUILTIN_RESOURCES
@@ -227,13 +229,27 @@ class ShaderCompiler final : public system::IApplicationFramework
227229
}
228230

229231
auto start = std::chrono::high_resolution_clock::now();
230-
auto compilation_result = compile_shader(shader.get(), shaderStage, file_to_compile);
232+
smart_refctd_ptr<IShader> compilation_result;
233+
std::string preprocessing_result;
234+
std::string_view result_view;
235+
if (preprocessOnly)
236+
{
237+
preprocessing_result = preprocess_shader(shader.get(), shaderStage, file_to_compile);
238+
result_view = preprocessing_result;
239+
}
240+
else
241+
{
242+
compilation_result = compile_shader(shader.get(), shaderStage, file_to_compile);
243+
result_view = { (const char*)compilation_result->getContent()->getPointer(), compilation_result->getContent()->getSize() };
244+
}
231245
auto end = std::chrono::high_resolution_clock::now();
232246

233-
// writie compiled shader to file as bytes
234-
if (compilation_result)
247+
// write compiled/preprocessed shader to file as bytes
248+
std::string operationType = preprocessOnly ? "preprocessing" : "compilation";
249+
const bool success = preprocessOnly ? preprocessing_result != std::string{} : bool(compilation_result);
250+
if (success)
235251
{
236-
m_logger->log("Shader compilation successful.", ILogger::ELL_INFO);
252+
m_logger->log("Shader " + operationType + " successful.", ILogger::ELL_INFO);
237253
const auto took = std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count());
238254
m_logger->log("Took %s ms.", ILogger::ELL_PERFORMANCE, took.c_str());
239255
{
@@ -258,7 +274,7 @@ class ShaderCompiler final : public system::IApplicationFramework
258274
return false;
259275
}
260276

261-
output_file.write((const char*)compilation_result->getContent()->getPointer(), compilation_result->getContent()->getSize());
277+
output_file.write(result_view.data(), result_view.size());
262278

263279
if (output_file.fail())
264280
{
@@ -279,7 +295,7 @@ class ShaderCompiler final : public system::IApplicationFramework
279295
}
280296
else
281297
{
282-
m_logger->log("Shader compilation failed.", ILogger::ELL_ERROR);
298+
m_logger->log("Shader " + operationType + " failed.", ILogger::ELL_ERROR);
283299
return false;
284300
}
285301
}
@@ -291,6 +307,28 @@ class ShaderCompiler final : public system::IApplicationFramework
291307

292308
private:
293309

310+
std::string preprocess_shader(const IShader* shader, hlsl::ShaderStage shaderStage, std::string_view sourceIdentifier) {
311+
smart_refctd_ptr<CHLSLCompiler> hlslcompiler = make_smart_refctd_ptr<CHLSLCompiler>(smart_refctd_ptr(m_system));
312+
313+
CHLSLCompiler::SPreprocessorOptions options = {};
314+
options.sourceIdentifier = sourceIdentifier;
315+
options.logger = m_logger.get();
316+
317+
auto includeFinder = make_smart_refctd_ptr<IShaderCompiler::CIncludeFinder>(smart_refctd_ptr(m_system));
318+
auto includeLoader = includeFinder->getDefaultFileSystemLoader();
319+
320+
// because before real compilation we do preprocess the input it doesn't really matter we proxy include search direcotries further with dxcOptions since at the end all includes are resolved to single file
321+
for (const auto& it : m_include_search_paths)
322+
includeFinder->addSearchPath(it, includeLoader);
323+
324+
options.includeFinder = includeFinder.get();
325+
326+
const char* code_ptr = (const char*)shader->getContent()->getPointer();
327+
std::string_view code({ code_ptr, strlen(code_ptr)});
328+
329+
return hlslcompiler->preprocessShader(std::string(code), shaderStage, options, nullptr);
330+
}
331+
294332
core::smart_refctd_ptr<IShader> compile_shader(const IShader* shader, hlsl::ShaderStage shaderStage, std::string_view sourceIdentifier) {
295333
smart_refctd_ptr<CHLSLCompiler> hlslcompiler = make_smart_refctd_ptr<CHLSLCompiler>(smart_refctd_ptr(m_system));
296334

0 commit comments

Comments
 (0)