xbintsc 0.5.31 → 0.5.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -10
- package/dist/src/binder/references.js +14 -1
- package/dist/src/binder/references.js.map +1 -1
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/codegen/generator/module.d.ts +1 -0
- package/dist/src/codegen/generator/module.js +54 -0
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/statements/variables.js +6 -4
- package/dist/src/codegen/generator/statements/variables.js.map +1 -1
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/gui/css.d.ts +26 -0
- package/dist/src/extensions/gui/css.js +100 -0
- package/dist/src/extensions/gui/css.js.map +1 -0
- package/dist/src/extensions/gui/html.js +9 -2
- package/dist/src/extensions/gui/html.js.map +1 -1
- package/dist/src/extensions/gui/index.js +16 -2
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/gui/three.d.ts +16 -0
- package/dist/src/extensions/gui/three.js +22 -0
- package/dist/src/extensions/gui/three.js.map +1 -0
- package/dist/src/extensions/media/index.d.ts +6 -5
- package/dist/src/extensions/media/index.js +12 -14
- package/dist/src/extensions/media/index.js.map +1 -1
- package/dist/tests/e2e/compile-builtins.test.js +24 -0
- package/dist/tests/e2e/compile-builtins.test.js.map +1 -1
- package/dist/tests/e2e/compile-objects-classes.test.js +23 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
- package/dist/tests/e2e/gui-browser.test.js +1 -1
- package/dist/tests/e2e/gui-browser.test.js.map +1 -1
- package/dist/tests/e2e/gui-effects.test.d.ts +6 -0
- package/dist/tests/e2e/gui-effects.test.js +262 -0
- package/dist/tests/e2e/gui-effects.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-webgl.test.d.ts +10 -0
- package/dist/tests/e2e/gui-example-webgl.test.js +75 -0
- package/dist/tests/e2e/gui-example-webgl.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-webgl2.test.d.ts +8 -0
- package/dist/tests/e2e/gui-example-webgl2.test.js +72 -0
- package/dist/tests/e2e/gui-example-webgl2.test.js.map +1 -0
- package/dist/tests/e2e/gui-layout.test.js +48 -0
- package/dist/tests/e2e/gui-layout.test.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.js +5 -4
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl.test.d.ts +11 -0
- package/dist/tests/e2e/gui-webgl.test.js +179 -0
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2.test.js +238 -0
- package/dist/tests/e2e/gui-webgl2.test.js.map +1 -0
- package/dist/tests/extensions/gui.test.js +41 -0
- package/dist/tests/extensions/gui.test.js.map +1 -1
- package/dist/tests/extensions/media.test.js +7 -3
- package/dist/tests/extensions/media.test.js.map +1 -1
- package/doc/ai/extensions.md +29 -9
- package/doc/ai/troubleshooting.md +12 -8
- package/doc/ai/zh-CN/extensions.md +26 -8
- package/doc/ai/zh-CN/troubleshooting.md +10 -6
- package/doc/gui/api.md +3 -2
- package/doc/gui/build.md +72 -16
- package/doc/gui/canvas.md +11 -3
- package/doc/gui/dom.md +33 -18
- package/doc/gui/known-issues.md +57 -24
- package/doc/gui/layout.md +18 -0
- package/doc/gui/media.md +17 -13
- package/doc/gui/rendering.md +50 -3
- package/doc/gui/webgl.md +256 -0
- package/doc/gui.md +108 -17
- package/doc/npm-package.md +6 -4
- package/doc/requirements.md +18 -9
- package/doc/zh-CN/gui/api.md +3 -2
- package/doc/zh-CN/gui/build.md +64 -15
- package/doc/zh-CN/gui/canvas.md +9 -2
- package/doc/zh-CN/gui/dom.md +20 -7
- package/doc/zh-CN/gui/known-issues.md +45 -19
- package/doc/zh-CN/gui/layout.md +14 -0
- package/doc/zh-CN/gui/media.md +15 -11
- package/doc/zh-CN/gui/rendering.md +41 -4
- package/doc/zh-CN/gui/webgl.md +115 -0
- package/doc/zh-CN/gui.md +89 -14
- package/doc/zh-CN/npm-package.md +9 -6
- package/doc/zh-CN/requirements.md +12 -6
- package/llms.txt +2 -0
- package/package.json +1 -1
- package/runtime/ext_gui/browser.cpp +39 -13
- package/runtime/ext_gui/canvas.cpp +3 -18
- package/runtime/ext_gui/canvas_internal.h +10 -0
- package/runtime/ext_gui/canvas_raster.cpp +60 -0
- package/runtime/ext_gui/clip_values.cpp +246 -0
- package/runtime/ext_gui/css.cpp +94 -0
- package/runtime/ext_gui/css.h +22 -1
- package/runtime/ext_gui/css_match.cpp +3 -0
- package/runtime/ext_gui/css_selector.cpp +9 -0
- package/runtime/ext_gui/css_sheet.cpp +89 -45
- package/runtime/ext_gui/document.cpp +4 -1
- package/runtime/ext_gui/document.h +2 -0
- package/runtime/ext_gui/dom.h +16 -0
- package/runtime/ext_gui/dom_api.cpp +1 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +17 -80
- package/runtime/ext_gui/dom_api_canvas_extra.cpp +130 -1
- package/runtime/ext_gui/dom_api_canvas_pending.cpp +41 -0
- package/runtime/ext_gui/dom_api_internal.h +259 -0
- package/runtime/ext_gui/dom_api_webgl.cpp +376 -0
- package/runtime/ext_gui/dom_api_webgl2.cpp +434 -0
- package/runtime/ext_gui/dom_api_webgl2_draw.cpp +269 -0
- package/runtime/ext_gui/dom_api_webgl_buffer.cpp +212 -0
- package/runtime/ext_gui/dom_api_webgl_rt.h +30 -0
- package/runtime/ext_gui/dom_api_webgl_shader.cpp +443 -0
- package/runtime/ext_gui/dom_api_webgl_state.cpp +444 -0
- package/runtime/ext_gui/dom_api_webgl_texture.cpp +445 -0
- package/runtime/ext_gui/effect_values.cpp +312 -0
- package/runtime/ext_gui/gradient_values.cpp +476 -0
- package/runtime/ext_gui/grid_values.cpp +230 -0
- package/runtime/ext_gui/gui_canvas.cpp +50 -2
- package/runtime/ext_gui/gui_engine.h +27 -0
- package/runtime/ext_gui/gui_events.cpp +4 -1
- package/runtime/ext_gui/gui_media.cpp +1 -1
- package/runtime/ext_gui/gui_webgl.cpp +83 -0
- package/runtime/ext_gui/layout.cpp +21 -0
- package/runtime/ext_gui/layout_flow.cpp +81 -4
- package/runtime/ext_gui/layout_flow_internal.h +31 -0
- package/runtime/ext_gui/layout_grid.cpp +374 -0
- package/runtime/ext_gui/media.h +1 -1
- package/runtime/ext_gui/media_api.h +2 -2
- package/runtime/ext_gui/media_query.cpp +211 -0
- package/runtime/ext_gui/paint.cpp +111 -77
- package/runtime/ext_gui/paint.h +33 -3
- package/runtime/ext_gui/paint_background.cpp +229 -0
- package/runtime/ext_gui/paint_clip.cpp +268 -0
- package/runtime/ext_gui/paint_effects.cpp +324 -0
- package/runtime/ext_gui/paint_internal.h +85 -0
- package/runtime/ext_gui/renderer.cpp +8 -31
- package/runtime/ext_gui/renderer_clip.cpp +196 -0
- package/runtime/ext_gui/renderer_image.cpp +13 -8
- package/runtime/ext_gui/renderer_internal.h +15 -8
- package/runtime/ext_gui/renderer_text.cpp +6 -31
- package/runtime/ext_gui/style.cpp +343 -20
- package/runtime/ext_gui/style.h +144 -3
- package/runtime/ext_gui/style_print.cpp +134 -1
- package/runtime/ext_gui/style_values.cpp +152 -126
- package/runtime/ext_gui/style_values_internal.h +35 -0
- package/runtime/ext_gui/webgl.h +466 -0
- package/runtime/ext_gui/webgl2_constants.h +274 -0
- package/runtime/ext_gui/webgl_buffer.cpp +565 -0
- package/runtime/ext_gui/webgl_constants.h +317 -0
- package/runtime/ext_gui/webgl_context.cpp +466 -0
- package/runtime/ext_gui/webgl_draw.cpp +495 -0
- package/runtime/ext_gui/webgl_glsl.h +125 -0
- package/runtime/ext_gui/webgl_glsl_compile.cpp +431 -0
- package/runtime/ext_gui/webgl_glsl_rewrite.cpp +349 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +581 -0
- package/runtime/ext_gui/webgl_msl.cpp +62 -0
- package/runtime/ext_gui/webgl_msl.h +33 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +274 -0
- package/runtime/ext_gui/webgl_program_internal.h +18 -0
- package/runtime/ext_gui/webgl_shader.cpp +582 -0
- package/runtime/ext_gui/webgl_texture.cpp +293 -0
- package/runtime/ext_gui/webgl_uniform.cpp +167 -0
- package/runtime/ext_gui/webgl_webgl2.cpp +224 -0
- package/runtime/ext_media/media.cpp +1 -1
- package/runtime/ext_media/media_bridge.c +9 -3
- package/runtime/rt_internal.h +1 -0
- package/runtime/xt_containers/access.inc +8 -0
- package/runtime/xt_regex/api.inc +2 -0
- package/runtime/xt_regex/matcher.inc +16 -3
- package/runtime/xt_regex/parser.inc +8 -2
- package/runtime/xt_regex/types.inc +3 -0
- package/runtime/xt_stdlib2/regexp-match.inc +60 -21
- package/runtime/xt_stdlib2/regexp.inc +1 -0
- package/runtime/xt_typed_array.c +1 -1
- package/scripts/build-gui.ts +90 -3
- package/scripts/build-media.ts +323 -58
- package/scripts/setup-vs-toolchain.ps1 +152 -0
- package/src/binder/references.ts +13 -1
- package/src/codegen/generator/module.ts +50 -0
- package/src/codegen/generator/statements/variables.ts +6 -3
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/css.ts +113 -0
- package/src/extensions/gui/html.ts +9 -2
- package/src/extensions/gui/index.ts +16 -2
- package/src/extensions/gui/three.ts +25 -0
- package/src/extensions/media/index.ts +13 -16
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc GUI engine — WebGL GLSL rewriter.
|
|
3
|
+
*
|
|
4
|
+
* Turns the GLSL ES 1.00/3.00 a WebGL program supplies into the Vulkan-dialect
|
|
5
|
+
* GLSL ES 3.10 glslang accepts: explicit attribute/varying/output locations, one
|
|
6
|
+
* std140 uniform block (set 1 for vertex, set 3 for fragment), samplers with an
|
|
7
|
+
* explicit descriptor set/binding, and the legacy `texture2D` / `gl_FragColor`
|
|
8
|
+
* spellings. The original text is spliced, so comments, spacing and `#if`
|
|
9
|
+
* blocks survive.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#include "webgl_glsl.h"
|
|
13
|
+
|
|
14
|
+
#include <algorithm>
|
|
15
|
+
#include <cctype>
|
|
16
|
+
#include <string>
|
|
17
|
+
#include <vector>
|
|
18
|
+
|
|
19
|
+
namespace xtgui {
|
|
20
|
+
namespace {
|
|
21
|
+
|
|
22
|
+
struct Edit {
|
|
23
|
+
size_t begin = 0;
|
|
24
|
+
size_t end = 0;
|
|
25
|
+
std::string text;
|
|
26
|
+
int order = 0;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
std::string trim(const std::string &text) {
|
|
30
|
+
size_t begin = 0;
|
|
31
|
+
size_t end = text.size();
|
|
32
|
+
while (begin < end && std::isspace((unsigned char)text[begin]) != 0) begin++;
|
|
33
|
+
while (end > begin && std::isspace((unsigned char)text[end - 1]) != 0) end--;
|
|
34
|
+
return text.substr(begin, end - begin);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** `<type> <name><array>` — the shape a block member or a layout-qualified
|
|
38
|
+
* declaration needs. */
|
|
39
|
+
std::string declarator_text(const GlslUniformDecl &decl) {
|
|
40
|
+
return decl.type + " " + decl.name + decl.array;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The same, keeping a precision qualifier (allowed on `in`/`out`/sampler
|
|
44
|
+
* declarations but not needed on block members). */
|
|
45
|
+
std::string qualified_declarator_text(const GlslUniformDecl &decl) {
|
|
46
|
+
std::string text;
|
|
47
|
+
if (!decl.precision.empty()) text = decl.precision + " ";
|
|
48
|
+
return text + declarator_text(decl);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
bool has_float_precision(const std::string &source) {
|
|
52
|
+
size_t at = 0;
|
|
53
|
+
while ((at = source.find("precision", at)) != std::string::npos) {
|
|
54
|
+
const size_t end = source.find(';', at);
|
|
55
|
+
if (end == std::string::npos) break;
|
|
56
|
+
const std::string line = source.substr(at, end - at);
|
|
57
|
+
if (line.find("float") != std::string::npos) return true;
|
|
58
|
+
at = end;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Replace the `#version` line (or prepend one) and append the preamble the
|
|
64
|
+
* rewritten shader needs. */
|
|
65
|
+
std::string version_block(const std::string &source, bool fragment, bool needs_output,
|
|
66
|
+
bool *found_version, size_t *version_begin, size_t *version_end) {
|
|
67
|
+
*found_version = false;
|
|
68
|
+
*version_begin = 0;
|
|
69
|
+
*version_end = 0;
|
|
70
|
+
size_t line = 0;
|
|
71
|
+
while (line < source.size()) {
|
|
72
|
+
size_t line_end = source.find('\n', line);
|
|
73
|
+
if (line_end == std::string::npos) line_end = source.size();
|
|
74
|
+
const std::string text = trim(source.substr(line, line_end - line));
|
|
75
|
+
if (!text.empty() && text[0] != '#') break;
|
|
76
|
+
if (text.rfind("#version", 0) == 0) {
|
|
77
|
+
*found_version = true;
|
|
78
|
+
*version_begin = line;
|
|
79
|
+
*version_end = line_end;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
if (!text.empty() && text[0] == '#' && text.rfind("#extension", 0) != 0 &&
|
|
83
|
+
text.rfind("#version", 0) != 0) {
|
|
84
|
+
/* A non-version directive before `#version` is illegal, but keep looking
|
|
85
|
+
* so the rewritten shader still gets a version line. */
|
|
86
|
+
}
|
|
87
|
+
line = line_end + 1;
|
|
88
|
+
}
|
|
89
|
+
std::string block = "#version 310 es\n";
|
|
90
|
+
if (fragment) {
|
|
91
|
+
if (!has_float_precision(source)) block += "precision highp float;\nprecision highp int;\n";
|
|
92
|
+
if (needs_output) block += "layout(location = 0) out highp vec4 xt_FragColor;\n";
|
|
93
|
+
}
|
|
94
|
+
/* three.js keeps its light loops unrolled only when it can pre-evaluate
|
|
95
|
+
* per-iteration #if blocks. Without shadow maps the index-0 branch is the
|
|
96
|
+
* correct one for every supported scene. */
|
|
97
|
+
if (source.find("UNROLLED_LOOP_INDEX") != std::string::npos) {
|
|
98
|
+
block += "#define UNROLLED_LOOP_INDEX 0\n";
|
|
99
|
+
}
|
|
100
|
+
return block;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
} // namespace
|
|
104
|
+
|
|
105
|
+
std::string rewrite_glsl(const std::string &source, bool fragment, const GlslLinkLayout &layout,
|
|
106
|
+
const GlslShaderInfo &info) {
|
|
107
|
+
std::vector<Edit> edits;
|
|
108
|
+
bool found_version = false;
|
|
109
|
+
size_t version_begin = 0;
|
|
110
|
+
size_t version_end = 0;
|
|
111
|
+
/* A GLSL ES 3.00 source may already declare its own output (three.js emits
|
|
112
|
+
* `layout(location = 0) out highp vec4 pc_fragColor;` and defines
|
|
113
|
+
* `gl_FragColor` to it). In that case the legacy name maps to the declared
|
|
114
|
+
* output instead of adding a second declaration at location 0. */
|
|
115
|
+
std::string fragment_output_name = "xt_FragColor";
|
|
116
|
+
if (fragment && info.has_fragment_output) {
|
|
117
|
+
for (const GlslDeclSite &site : info.sites) {
|
|
118
|
+
if (site.kind == GlslDeclSite::FragmentOut) {
|
|
119
|
+
fragment_output_name = site.decl.name;
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const bool needs_output =
|
|
125
|
+
fragment && info.legacy_fragment_output && !info.has_fragment_output;
|
|
126
|
+
const std::string block =
|
|
127
|
+
version_block(source, fragment, needs_output, &found_version, &version_begin, &version_end);
|
|
128
|
+
|
|
129
|
+
Edit version;
|
|
130
|
+
version.begin = version_begin;
|
|
131
|
+
version.end = version_end;
|
|
132
|
+
version.text = block;
|
|
133
|
+
version.order = 0;
|
|
134
|
+
edits.push_back(version);
|
|
135
|
+
|
|
136
|
+
/* Remove extension directives that are core in ES 3.10 (or unsupported). */
|
|
137
|
+
const char *const stripped_extensions[] = {
|
|
138
|
+
"#extension GL_EXT_shader_texture_lod",
|
|
139
|
+
"#extension GL_OES_standard_derivatives",
|
|
140
|
+
"#extension GL_EXT_frag_depth",
|
|
141
|
+
"#extension GL_EXT_draw_buffers",
|
|
142
|
+
"#extension GL_EXT_shader_framebuffer_fetch",
|
|
143
|
+
};
|
|
144
|
+
size_t line = 0;
|
|
145
|
+
while (line < source.size()) {
|
|
146
|
+
size_t line_end = source.find('\n', line);
|
|
147
|
+
if (line_end == std::string::npos) line_end = source.size();
|
|
148
|
+
const std::string text = trim(source.substr(line, line_end - line));
|
|
149
|
+
for (const char *prefix : stripped_extensions) {
|
|
150
|
+
if (text.rfind(prefix, 0) == 0) {
|
|
151
|
+
Edit edit;
|
|
152
|
+
edit.begin = line;
|
|
153
|
+
edit.end = line_end;
|
|
154
|
+
edit.text.clear();
|
|
155
|
+
edit.order = 1;
|
|
156
|
+
edits.push_back(edit);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
line = line_end + 1;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* Insert the uniform block before the first uniform declaration (or before
|
|
163
|
+
* the `#if` that encloses it, so the members stay unconditional). Struct
|
|
164
|
+
* definitions are hoisted to the same point: a uniform may name a type that
|
|
165
|
+
* three.js declares after the prefix uniforms (`DirectionalLight`). */
|
|
166
|
+
if (!layout.block_members.empty() && info.first_uniform_offset != std::string::npos) {
|
|
167
|
+
std::string hoisted;
|
|
168
|
+
for (const std::string &definition : info.struct_definitions) {
|
|
169
|
+
hoisted += definition;
|
|
170
|
+
hoisted += "\n";
|
|
171
|
+
}
|
|
172
|
+
for (const auto &range : info.structs) {
|
|
173
|
+
Edit remove;
|
|
174
|
+
remove.begin = range.first;
|
|
175
|
+
remove.end = range.second;
|
|
176
|
+
remove.order = 1;
|
|
177
|
+
edits.push_back(remove);
|
|
178
|
+
}
|
|
179
|
+
size_t insert_at = info.first_uniform_offset;
|
|
180
|
+
int depth = 0;
|
|
181
|
+
std::vector<size_t> starts;
|
|
182
|
+
line = 0;
|
|
183
|
+
while (line < info.first_uniform_offset) {
|
|
184
|
+
size_t line_end = source.find('\n', line);
|
|
185
|
+
if (line_end == std::string::npos || line_end > info.first_uniform_offset) {
|
|
186
|
+
line_end = info.first_uniform_offset;
|
|
187
|
+
}
|
|
188
|
+
const std::string text = trim(source.substr(line, line_end - line));
|
|
189
|
+
if (text.rfind("#if", 0) == 0) {
|
|
190
|
+
starts.push_back(line);
|
|
191
|
+
depth++;
|
|
192
|
+
} else if (text.rfind("#endif", 0) == 0) {
|
|
193
|
+
if (!starts.empty()) starts.pop_back();
|
|
194
|
+
if (depth > 0) depth--;
|
|
195
|
+
}
|
|
196
|
+
line = line_end + 1;
|
|
197
|
+
}
|
|
198
|
+
if (!starts.empty()) insert_at = starts.front();
|
|
199
|
+
std::string members = "layout(std140, set = ";
|
|
200
|
+
members += fragment ? "3" : "1";
|
|
201
|
+
members += ", binding = 0) uniform XtUniforms {\n";
|
|
202
|
+
for (const GlslUniformDecl &decl : layout.block_members) {
|
|
203
|
+
members += " ";
|
|
204
|
+
members += declarator_text(decl);
|
|
205
|
+
members += ";\n";
|
|
206
|
+
}
|
|
207
|
+
members += "};\n";
|
|
208
|
+
Edit block_edit;
|
|
209
|
+
block_edit.begin = insert_at;
|
|
210
|
+
block_edit.end = insert_at;
|
|
211
|
+
block_edit.text = hoisted + members;
|
|
212
|
+
block_edit.order = 2;
|
|
213
|
+
edits.push_back(block_edit);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
int fragment_output = 0;
|
|
217
|
+
for (const GlslDeclSite &site : info.sites) {
|
|
218
|
+
Edit edit;
|
|
219
|
+
edit.begin = site.begin;
|
|
220
|
+
edit.end = site.end;
|
|
221
|
+
edit.order = 3;
|
|
222
|
+
switch (site.kind) {
|
|
223
|
+
case GlslDeclSite::Uniform:
|
|
224
|
+
edit.text.clear();
|
|
225
|
+
break;
|
|
226
|
+
case GlslDeclSite::Sampler: {
|
|
227
|
+
int binding = 0;
|
|
228
|
+
auto found = layout.samplers.find(site.decl.name);
|
|
229
|
+
if (found != layout.samplers.end()) binding = found->second;
|
|
230
|
+
edit.text = "layout(set = ";
|
|
231
|
+
edit.text += fragment ? "2" : "0";
|
|
232
|
+
edit.text += ", binding = ";
|
|
233
|
+
edit.text += std::to_string(binding);
|
|
234
|
+
edit.text += ") uniform ";
|
|
235
|
+
edit.text += qualified_declarator_text(site.decl);
|
|
236
|
+
edit.text += ";";
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
case GlslDeclSite::Attribute:
|
|
240
|
+
case GlslDeclSite::Varying:
|
|
241
|
+
case GlslDeclSite::FragmentOut: {
|
|
242
|
+
int location = site.existing_location;
|
|
243
|
+
if (location < 0) {
|
|
244
|
+
if (site.kind == GlslDeclSite::Attribute) {
|
|
245
|
+
auto found = layout.attributes.find(site.decl.name);
|
|
246
|
+
if (found != layout.attributes.end()) location = found->second;
|
|
247
|
+
} else if (site.kind == GlslDeclSite::Varying) {
|
|
248
|
+
auto found = layout.varyings.find(site.decl.name);
|
|
249
|
+
if (found != layout.varyings.end()) location = found->second;
|
|
250
|
+
} else if (site.kind == GlslDeclSite::FragmentOut) {
|
|
251
|
+
location = fragment_output;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (location < 0) location = 0;
|
|
255
|
+
if (site.kind == GlslDeclSite::FragmentOut) {
|
|
256
|
+
fragment_output = location + 1;
|
|
257
|
+
}
|
|
258
|
+
const char *direction = "in";
|
|
259
|
+
if (site.kind == GlslDeclSite::Varying) direction = fragment ? "in" : "out";
|
|
260
|
+
if (site.kind == GlslDeclSite::FragmentOut) direction = "out";
|
|
261
|
+
edit.text = "layout(location = " + std::to_string(location) + ") ";
|
|
262
|
+
edit.text += direction;
|
|
263
|
+
edit.text += " ";
|
|
264
|
+
edit.text += qualified_declarator_text(site.decl);
|
|
265
|
+
edit.text += ";";
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
edits.push_back(edit);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* Legacy identifiers. `average` is a built-in in the Vulkan GLSL dialect
|
|
273
|
+
* (three.js defines its own `average` in `common`), so rename it to avoid a
|
|
274
|
+
* redeclaration error. */
|
|
275
|
+
const char *const identifiers[] = {"texture2D", "textureCube", "texture2DProj",
|
|
276
|
+
"texture2DLodEXT", "textureCubeLodEXT", "gl_FragColor",
|
|
277
|
+
"gl_FragDepthEXT", "gl_FragData", "average"};
|
|
278
|
+
const std::string replacements[] = {"texture", "texture", "textureProj", "textureLod",
|
|
279
|
+
"textureLod", fragment_output_name, "gl_FragDepth",
|
|
280
|
+
fragment_output_name, "xt_average"};
|
|
281
|
+
size_t at = 0;
|
|
282
|
+
while (at < source.size()) {
|
|
283
|
+
const char c = source[at];
|
|
284
|
+
if (std::isalpha((unsigned char)c) == 0 && c != '_') {
|
|
285
|
+
at++;
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
size_t end = at + 1;
|
|
289
|
+
while (end < source.size() &&
|
|
290
|
+
(std::isalnum((unsigned char)source[end]) != 0 || source[end] == '_')) {
|
|
291
|
+
end++;
|
|
292
|
+
}
|
|
293
|
+
const std::string word = source.substr(at, end - at);
|
|
294
|
+
for (size_t k = 0; k < sizeof(identifiers) / sizeof(identifiers[0]); k++) {
|
|
295
|
+
if (word != identifiers[k]) continue;
|
|
296
|
+
bool inside = false;
|
|
297
|
+
for (const GlslDeclSite &site : info.sites) {
|
|
298
|
+
if (at >= site.begin && at < site.end) inside = true;
|
|
299
|
+
}
|
|
300
|
+
if (inside) break;
|
|
301
|
+
if (word == "gl_FragData") {
|
|
302
|
+
size_t probe = end;
|
|
303
|
+
while (probe < source.size() && std::isspace((unsigned char)source[probe]) != 0) probe++;
|
|
304
|
+
if (probe < source.size() && source[probe] == '[') {
|
|
305
|
+
size_t close = source.find(']', probe);
|
|
306
|
+
if (close != std::string::npos) {
|
|
307
|
+
const std::string index = trim(source.substr(probe + 1, close - probe - 1));
|
|
308
|
+
if (index != "0") break; // MRT is not supported
|
|
309
|
+
Edit edit;
|
|
310
|
+
edit.begin = at;
|
|
311
|
+
edit.end = close + 1;
|
|
312
|
+
edit.text = fragment_output_name;
|
|
313
|
+
edit.order = 4;
|
|
314
|
+
edits.push_back(edit);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
Edit edit;
|
|
320
|
+
edit.begin = at;
|
|
321
|
+
edit.end = end;
|
|
322
|
+
edit.text = replacements[k];
|
|
323
|
+
edit.order = 4;
|
|
324
|
+
edits.push_back(edit);
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
at = end;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/* Apply the non-overlapping edits in source order. */
|
|
331
|
+
std::stable_sort(edits.begin(), edits.end(), [](const Edit &a, const Edit &b) {
|
|
332
|
+
if (a.begin != b.begin) return a.begin < b.begin;
|
|
333
|
+
if (a.end != b.end) return a.end < b.end;
|
|
334
|
+
return a.order < b.order;
|
|
335
|
+
});
|
|
336
|
+
std::string result;
|
|
337
|
+
result.reserve(source.size() + 256);
|
|
338
|
+
size_t cursor = 0;
|
|
339
|
+
for (const Edit &edit : edits) {
|
|
340
|
+
if (edit.begin < cursor) continue; // overlaps an earlier replacement
|
|
341
|
+
result.append(source, cursor, edit.begin - cursor);
|
|
342
|
+
result += edit.text;
|
|
343
|
+
cursor = edit.end;
|
|
344
|
+
}
|
|
345
|
+
result.append(source, cursor, std::string::npos);
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
} // namespace xtgui
|