Skip to content

Commit 1d0b018

Browse files
committed
Optimize ShaderTemplate by precomputing placeholder positions
1 parent 390584d commit 1d0b018

File tree

2 files changed

+32
-20
lines changed

2 files changed

+32
-20
lines changed

libopenage/renderer/stages/world/shader_template.cpp

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ ShaderTemplate::ShaderTemplate(const util::Path &template_path) {
1313
auto file = template_path.open();
1414
this->template_code = file.read();
1515
file.close();
16+
17+
std::string marker = "// PLACEHOLDER: ";
18+
size_t pos = 0;
19+
20+
while ((pos = this->template_code.find(marker, pos)) != std::string::npos) {
21+
size_t name_start = pos + marker.length();
22+
size_t line_end = this->template_code.find('\n', name_start);
23+
std::string name = this->template_code.substr(name_start, line_end - name_start);
24+
// Trim trailing whitespace (space, tab, carriage return, etc.)
25+
name.erase(name.find_last_not_of(" \t\r\n") + 1);
26+
27+
this->placeholders.push_back({name, pos, line_end - pos});
28+
pos = line_end;
29+
}
1630
}
1731

1832
void ShaderTemplate::load_snippets(const util::Path &snippet_path) {
@@ -38,28 +52,18 @@ void ShaderTemplate::add_snippet(const util::Path &snippet_path) {
3852
renderer::resources::ShaderSource ShaderTemplate::generate_source() const {
3953
std::string result_src = template_code;
4054

41-
// Process each placeholder
42-
for (const auto &[name, snippet_code] : snippets) {
43-
std::string placeholder = "// PLACEHOLDER: " + name;
44-
size_t pos = result_src.find(placeholder);
45-
46-
if (pos != std::string::npos) {
47-
result_src.replace(pos, placeholder.length(), snippet_code);
55+
// Replace placeholders in reverse order (to avoid offset issues)
56+
for (auto it = placeholders.rbegin(); it != placeholders.rend(); ++it) {
57+
const auto &ph = *it;
58+
auto snippet_it = snippets.find(ph.name);
59+
if (snippet_it != snippets.end()) {
60+
result_src.replace(ph.position, ph.length, snippet_it->second);
4861
}
4962
else {
50-
log::log(WARN << "Placeholder not found in template: " << name);
63+
throw Error(MSG(err) << "Missing snippet for placeholder: " << ph.name);
5164
}
5265
}
5366

54-
// Check if all placeholders were replaced
55-
size_t placeholder_pos = result_src.find("// PLACEHOLDER:");
56-
if (placeholder_pos != std::string::npos) {
57-
size_t line_end = result_src.find('\n', placeholder_pos);
58-
std::string missing = result_src.substr(placeholder_pos,
59-
line_end - placeholder_pos);
60-
throw Error(MSG(err) << "Missing snippet for placeholder: " << missing);
61-
}
62-
6367
auto result = resources::ShaderSource(
6468
resources::shader_lang_t::glsl,
6569
resources::shader_stage_t::fragment,

libopenage/renderer/stages/world/shader_template.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@ class ShaderTemplate {
2929
explicit ShaderTemplate(const util::Path &template_path);
3030

3131
/**
32-
* Load all snippets from a JSON config file.
32+
* Load all snippets from a directory of .snippet files.
3333
*
34-
* @param config_path Path to JSON config file.
35-
* @param base_path Base path for resolving relative snippet paths.
34+
* @param snippet_path Path to directory containing snippet files.
3635
*/
3736
void load_snippets(const util::Path &snippet_path);
3837

@@ -57,6 +56,15 @@ class ShaderTemplate {
5756
std::string template_code;
5857
/// Mapping of placeholder IDs to their code snippets
5958
std::map<std::string, std::string> snippets;
59+
60+
/// Info about a placeholder found in the template
61+
struct Placeholder {
62+
std::string name;
63+
size_t position;
64+
size_t length;
65+
};
66+
67+
std::vector<Placeholder> placeholders;
6068
};
6169
} // namespace world
6270
} // namespace renderer

0 commit comments

Comments
 (0)