add 'do-trace-shaders' setting and fix shaders recompiling

This commit is contained in:
MihailRis 2025-08-31 18:14:05 +03:00
parent 5e3373313b
commit a621b179d3
10 changed files with 84 additions and 26 deletions

View File

@ -71,8 +71,8 @@ static auto process_program(const ResPaths& paths, const std::string& filename)
auto& preprocessor = *Shader::preprocessor;
auto vertex = preprocessor.process(vertexFile, vertexSource);
auto fragment = preprocessor.process(fragmentFile, fragmentSource);
auto vertex = preprocessor.process(vertexFile, vertexSource, false, {});
auto fragment = preprocessor.process(fragmentFile, fragmentSource, false, {});
return std::make_pair(vertex, fragment);
}
@ -121,7 +121,7 @@ assetload::postfunc assetload::posteffect(
auto& preprocessor = *Shader::preprocessor;
preprocessor.addHeader(
"__effect__", preprocessor.process(effectFile, effectSource, true)
"__effect__", preprocessor.process(effectFile, effectSource, true, {})
);
auto [vertex, fragment] = process_program(paths, SHADERS_FOLDER + "/effect");

View File

@ -22,6 +22,10 @@ void GLSLExtension::setPaths(const ResPaths* paths) {
this->paths = paths;
}
void GLSLExtension::setTraceOutput(bool enabled) {
this->traceOutput = enabled;
}
void GLSLExtension::loadHeader(const std::string& name) {
if (paths == nullptr) {
return;
@ -29,7 +33,7 @@ void GLSLExtension::loadHeader(const std::string& name) {
io::path file = paths->find("shaders/lib/" + name + ".glsl");
std::string source = io::read_string(file);
addHeader(name, {});
addHeader(name, process(file, source, true));
addHeader(name, process(file, source, true, {}));
}
void GLSLExtension::addHeader(const std::string& name, ProcessingResult header) {
@ -123,13 +127,22 @@ static Value default_value_for(Type type) {
class GLSLParser : public BasicParser<char> {
public:
GLSLParser(GLSLExtension& glsl, std::string_view file, std::string_view source, bool header)
GLSLParser(
GLSLExtension& glsl,
std::string_view file,
std::string_view source,
bool header,
const std::vector<std::string>& defines
)
: BasicParser(file, source), glsl(glsl) {
if (!header) {
ss << "#version " << GLSLExtension::VERSION << '\n';
}
for (auto& entry : glsl.getDefines()) {
ss << "#define " << entry.first << " " << entry.second << '\n';
for (auto& entry : defines) {
ss << "#define " << entry << '\n';
}
for (auto& entry : defines) {
ss << "#define " << entry << '\n';
}
}
uint linenum = 1;
source_line(ss, linenum);
@ -289,10 +302,34 @@ private:
std::stringstream ss;
};
static void trace_output(
const io::path& file,
const std::string& source,
const GLSLExtension::ProcessingResult& result
) {
std::stringstream ss;
ss << "export:trace/" << file.name();
io::path outfile = ss.str();
try {
io::create_directories(outfile.parent());
io::write_string(outfile, result.code);
} catch (const std::runtime_error& err) {
logger.error() << "error on saving GLSLExtension::preprocess output ("
<< outfile.string() << "): " << err.what();
}
}
GLSLExtension::ProcessingResult GLSLExtension::process(
const io::path& file, const std::string& source, bool header
const io::path& file,
const std::string& source,
bool header,
const std::vector<std::string>& defines
) {
std::string filename = file.string();
GLSLParser parser(*this, filename, source, header);
return parser.process();
GLSLParser parser(*this, filename, source, header, defines);
auto result = parser.process();
if (traceOutput) {
trace_output(file, source, result);
}
return result;
}

View File

@ -5,6 +5,7 @@
#include <vector>
#include "io/io.hpp"
#include "data/setting.hpp"
#include "graphics/core/PostEffect.hpp"
class ResPaths;
@ -19,6 +20,7 @@ public:
};
void setPaths(const ResPaths* paths);
void setTraceOutput(bool enabled);
void define(const std::string& name, std::string value);
void undefine(const std::string& name);
@ -37,7 +39,8 @@ public:
ProcessingResult process(
const io::path& file,
const std::string& source,
bool header = false
bool header,
const std::vector<std::string>& defines
);
static inline std::string VERSION = "330 core";
@ -46,4 +49,5 @@ private:
std::unordered_map<std::string, std::string> defines;
const ResPaths* paths = nullptr;
bool traceOutput = false;
};

View File

@ -143,6 +143,12 @@ void Engine::initializeClient() {
},
true
));
keepAlive(settings.debug.doTraceShaders.observe(
[](bool value) {
Shader::preprocessor->setTraceOutput(value);
},
true
));
}
void Engine::initialize(CoreParameters coreParameters) {

View File

@ -2,7 +2,6 @@
#include <exception>
#include <fstream>
#include <iostream>
#include <sstream>
#include <filesystem>
@ -138,15 +137,21 @@ glshader compile_shader(GLenum type, const GLchar* source, const std::string& fi
}
static GLuint compile_program(
const Shader::Source& vertexSource, const Shader::Source& fragmentSource
const Shader::Source& vertexSource,
const Shader::Source& fragmentSource,
const std::vector<std::string>& defines
) {
auto& preprocessor = *Shader::preprocessor;
auto vertexCode = std::move(
preprocessor.process(vertexSource.file, vertexSource.code).code
preprocessor
.process(vertexSource.file, vertexSource.code, false, defines)
.code
);
auto fragmentCode = std::move(
preprocessor.process(fragmentSource.file, fragmentSource.code).code
preprocessor
.process(fragmentSource.file, fragmentSource.code, false, defines)
.code
);
const GLchar* vCode = vertexCode.c_str();
@ -176,8 +181,8 @@ static GLuint compile_program(
return program;
}
void Shader::recompile() {
GLuint newProgram = compile_program(vertexSource, fragmentSource);
void Shader::recompile(const std::vector<std::string>& defines) {
GLuint newProgram = compile_program(vertexSource, fragmentSource, defines);
glDeleteProgram(id);
id = newProgram;
uniformLocations.clear();
@ -188,7 +193,7 @@ std::unique_ptr<Shader> Shader::create(
Source&& vertexSource, Source&& fragmentSource
) {
return std::make_unique<Shader>(
compile_program(vertexSource, fragmentSource),
compile_program(vertexSource, fragmentSource, {}),
std::move(vertexSource),
std::move(fragmentSource)
);

View File

@ -4,6 +4,7 @@
#include <string>
#include <memory>
#include <vector>
#include <unordered_map>
#include <glm/glm.hpp>
@ -50,7 +51,7 @@ public:
void uniform4v(const std::string& name, int length, const float* v);
/// @brief Re-preprocess source code and re-compile shader program
void recompile();
void recompile(const std::vector<std::string>& defines);
/// @brief Create shader program using vertex and fragment shaders source.
/// @return linked shader program containing vertex and fragment shaders

View File

@ -321,11 +321,13 @@ void WorldRenderer::renderFrame(
prevCTShaderSettings.shadows != currentSettings.shadows ||
prevCTShaderSettings.ssao != currentSettings.ssao
) {
Shader::preprocessor->setDefined("ENABLE_SHADOWS", currentSettings.shadows);
Shader::preprocessor->setDefined("ENABLE_SSAO", currentSettings.ssao);
Shader::preprocessor->setDefined("ADVANCED_RENDER", currentSettings.advancedRender);
std::vector<std::string> defines;
if (currentSettings.shadows) defines.emplace_back("ENABLE_SHADOWS");
if (currentSettings.ssao) defines.emplace_back("ENABLE_SSAO");
if (currentSettings.advancedRender) defines.emplace_back("ADVANCED_RENDER");
for (auto shader : affectedShaders) {
shader->recompile();
shader->recompile(defines);
}
prevCTShaderSettings = currentSettings;
}

View File

@ -89,6 +89,7 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) {
builder.section("debug");
builder.add("generator-test-mode", &settings.debug.generatorTestMode);
builder.add("do-write-lights", &settings.debug.doWriteLights);
builder.add("do-trace-shaders", &settings.debug.doTraceShaders);
builder.add("enable-experimental", &settings.debug.enableExperimental);
}

View File

@ -95,6 +95,8 @@ struct DebugSettings {
FlagSetting generatorTestMode {false};
/// @brief Write lights cache
FlagSetting doWriteLights {true};
/// @brief Write preprocessed shaders code to user:export
FlagSetting doTraceShaders {false};
/// @brief Enable experimental optimizations and features
FlagSetting enableExperimental {false};
};

View File

@ -11,7 +11,7 @@ TEST(GLSLExtension, processing) {
"float sum(float a, float b) {\n"
" return a + b;\n"
"}\n",
true
true, {}
)
);
try {
@ -27,7 +27,7 @@ TEST(GLSLExtension, processing) {
" vec4 color = texture(u_screen, v_uv);\n"
" return mix(color, 1.0 - color, p_intensity);\n"
"}\n",
false);
false, {});
std::cout << processed.code << std::endl;
} catch (const parsing_error& err) {
std::cerr << err.errorLog() << std::endl;