xbintsc 0.5.37 → 0.5.41
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/dist/src/cli/help.d.ts +1 -1
- package/dist/src/codegen/generator/module.js +23 -7
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.js +1 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/tables.js +1 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/bundler/deferred.d.ts +63 -0
- package/dist/src/driver/bundler/deferred.js +279 -0
- package/dist/src/driver/bundler/deferred.js.map +1 -0
- package/dist/src/driver/bundler/merge.js +214 -2
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/runtime-objects.d.ts +1 -1
- package/dist/src/driver/runtime-objects.js +1 -0
- package/dist/src/driver/runtime-objects.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/html.js +98 -15
- package/dist/src/extensions/gui/html.js.map +1 -1
- package/dist/src/extensions/gui/index.js +1 -0
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/gui/three.d.ts +4 -3
- package/dist/src/extensions/gui/three.js +4 -3
- package/dist/src/extensions/gui/three.js.map +1 -1
- package/dist/tests/codegen/closures.test.js +7 -0
- package/dist/tests/codegen/closures.test.js.map +1 -1
- package/dist/tests/e2e/compile-objects-classes.test.js +31 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
- package/dist/tests/e2e/gui-canvas-state.test.d.ts +9 -0
- package/dist/tests/e2e/gui-canvas-state.test.js +297 -0
- package/dist/tests/e2e/gui-canvas-state.test.js.map +1 -0
- package/dist/tests/e2e/gui-draw-perf.test.d.ts +22 -0
- package/dist/tests/e2e/gui-draw-perf.test.js +405 -0
- package/dist/tests/e2e/gui-draw-perf.test.js.map +1 -0
- package/dist/tests/e2e/gui-perf.test.d.ts +23 -0
- package/dist/tests/e2e/gui-perf.test.js +283 -0
- package/dist/tests/e2e/gui-perf.test.js.map +1 -0
- package/dist/tests/e2e/gui-script-import-order.test.d.ts +10 -0
- package/dist/tests/e2e/gui-script-import-order.test.js +169 -0
- package/dist/tests/e2e/gui-script-import-order.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl.test.js +4 -4
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.d.ts +8 -0
- package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.js +336 -0
- package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-shadow.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2-shadow.test.js +108 -0
- package/dist/tests/e2e/gui-webgl2-shadow.test.js.map +1 -0
- package/dist/tests/e2e/url.test.d.ts +6 -0
- package/dist/tests/e2e/url.test.js +114 -0
- package/dist/tests/e2e/url.test.js.map +1 -0
- package/dist/tests/extensions/gui.test.js +45 -10
- package/dist/tests/extensions/gui.test.js.map +1 -1
- package/doc/gui/api.md +28 -2
- package/doc/gui/canvas.md +110 -27
- package/doc/gui/known-issues.md +32 -10
- package/doc/gui/rendering.md +77 -0
- package/doc/gui/runtime.md +18 -3
- package/doc/gui/webgl.md +58 -29
- package/doc/gui-scripts.md +19 -19
- package/doc/gui.md +43 -9
- package/doc/implemented/fetch.md +5 -0
- package/doc/implemented/modules.md +13 -0
- package/doc/implemented/stdlib.md +17 -0
- package/doc/unimplemented/deviations.md +1 -0
- package/doc/zh-CN/gui/api.md +25 -2
- package/doc/zh-CN/gui/canvas.md +95 -26
- package/doc/zh-CN/gui/known-issues.md +21 -4
- package/doc/zh-CN/gui/rendering.md +59 -0
- package/doc/zh-CN/gui/runtime.md +13 -3
- package/doc/zh-CN/gui/webgl.md +30 -8
- package/doc/zh-CN/gui-scripts.md +14 -13
- package/doc/zh-CN/gui.md +32 -8
- package/doc/zh-CN/implemented/fetch.md +4 -0
- package/doc/zh-CN/implemented/modules.md +10 -0
- package/doc/zh-CN/implemented/stdlib.md +15 -0
- package/doc/zh-CN/unimplemented/deviations.md +1 -0
- package/package.json +7 -7
- package/runtime/ext_gui/browser.cpp +3 -1
- package/runtime/ext_gui/canvas.cpp +135 -89
- package/runtime/ext_gui/canvas.h +116 -0
- package/runtime/ext_gui/canvas_clip.cpp +143 -0
- package/runtime/ext_gui/canvas_composite.cpp +241 -0
- package/runtime/ext_gui/canvas_coverage.cpp +241 -0
- package/runtime/ext_gui/canvas_gradient.cpp +41 -4
- package/runtime/ext_gui/canvas_image_data.cpp +4 -0
- package/runtime/ext_gui/canvas_internal.h +34 -9
- package/runtime/ext_gui/canvas_raster.cpp +207 -178
- package/runtime/ext_gui/canvas_shadow.cpp +161 -0
- package/runtime/ext_gui/canvas_stroke.cpp +37 -9
- package/runtime/ext_gui/canvas_style.cpp +59 -0
- package/runtime/ext_gui/canvas_text.cpp +140 -0
- package/runtime/ext_gui/css.h +7 -0
- package/runtime/ext_gui/css_sheet.cpp +22 -0
- package/runtime/ext_gui/document.cpp +25 -1
- package/runtime/ext_gui/document.h +8 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +16 -1
- package/runtime/ext_gui/dom_api_canvas_image.cpp +9 -0
- package/runtime/ext_gui/dom_api_canvas_state.cpp +217 -0
- package/runtime/ext_gui/dom_api_internal.h +36 -37
- package/runtime/ext_gui/dom_api_offscreen.cpp +213 -0
- package/runtime/ext_gui/dom_api_proto.cpp +18 -0
- package/runtime/ext_gui/dom_api_webgl.cpp +29 -9
- package/runtime/ext_gui/dom_api_webgl2.cpp +33 -1
- package/runtime/ext_gui/dom_api_webgl_internal.h +58 -0
- package/runtime/ext_gui/dom_api_webgl_source.cpp +18 -0
- package/runtime/ext_gui/gradient_values.cpp +12 -1
- package/runtime/ext_gui/gui.cpp +5 -0
- package/runtime/ext_gui/gui_canvas.cpp +4 -0
- package/runtime/ext_gui/gui_engine.h +32 -0
- package/runtime/ext_gui/gui_events.cpp +182 -58
- package/runtime/ext_gui/gui_media.cpp +3 -0
- package/runtime/ext_gui/image.cpp +69 -0
- package/runtime/ext_gui/image_bitmap_browser.cpp +11 -0
- package/runtime/ext_gui/layout.cpp +4 -0
- package/runtime/ext_gui/paint.cpp +19 -0
- package/runtime/ext_gui/paint_background.cpp +18 -1
- package/runtime/ext_gui/perf.cpp +171 -0
- package/runtime/ext_gui/perf.h +127 -0
- package/runtime/ext_gui/renderer.cpp +109 -41
- package/runtime/ext_gui/renderer.h +33 -9
- package/runtime/ext_gui/renderer_image.cpp +135 -65
- package/runtime/ext_gui/renderer_internal.h +15 -3
- package/runtime/ext_gui/renderer_text.cpp +24 -12
- package/runtime/ext_gui/script.cpp +31 -0
- package/runtime/ext_gui/style.cpp +101 -30
- package/runtime/ext_gui/style.h +6 -3
- package/runtime/ext_gui/style_print.cpp +7 -1
- package/runtime/ext_gui/text.cpp +23 -4
- package/runtime/ext_gui/text.h +29 -0
- package/runtime/ext_gui/text_cache.cpp +118 -0
- package/runtime/ext_gui/text_glyph_cache.cpp +100 -0
- package/runtime/ext_gui/webgl.h +48 -146
- package/runtime/ext_gui/webgl_blit.cpp +12 -1
- package/runtime/ext_gui/webgl_blit_depth.cpp +270 -0
- package/runtime/ext_gui/webgl_buffer.cpp +59 -1
- package/runtime/ext_gui/webgl_buffer_objects.cpp +106 -9
- package/runtime/ext_gui/webgl_clear.cpp +3 -0
- package/runtime/ext_gui/webgl_context.cpp +29 -3
- package/runtime/ext_gui/webgl_draw.cpp +75 -270
- package/runtime/ext_gui/webgl_draw_buffers.cpp +1 -0
- package/runtime/ext_gui/webgl_draw_setup.cpp +321 -0
- package/runtime/ext_gui/webgl_draw_state.h +130 -0
- package/runtime/ext_gui/webgl_glsl.h +3 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +3 -8
- package/runtime/ext_gui/webgl_glsl_unroll.cpp +283 -0
- package/runtime/ext_gui/webgl_msl.cpp +4 -0
- package/runtime/ext_gui/webgl_objects.h +148 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +8 -8
- package/runtime/ext_gui/webgl_program_internal.h +35 -0
- package/runtime/ext_gui/webgl_shader.cpp +34 -36
- package/runtime/ext_gui/webgl_webgl2.cpp +36 -0
- package/runtime/ext_gui/window.cpp +56 -1
- package/runtime/rt.h +3 -0
- package/runtime/xt_fetch/async.inc +60 -0
- package/runtime/xt_url_object.c +463 -0
- package/src/codegen/generator/module.ts +22 -7
- package/src/codegen/generator/state.ts +1 -0
- package/src/codegen/generator/tables.ts +1 -0
- package/src/driver/bundler/deferred.ts +351 -0
- package/src/driver/bundler/merge.ts +219 -2
- package/src/driver/runtime-objects.ts +1 -0
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/html.ts +100 -17
- package/src/extensions/gui/index.ts +1 -0
- package/src/extensions/gui/three.ts +4 -3
|
@@ -3,22 +3,24 @@
|
|
|
3
3
|
*
|
|
4
4
|
* SDL_GPU has no dynamic state for blend/depth/rasterisation: those live in a
|
|
5
5
|
* `SDL_GPUGraphicsPipeline`. WebGL changes them with `glEnable`/`glDepthFunc`,
|
|
6
|
-
* so a pipeline is built lazily per (program, vertex layout,
|
|
7
|
-
* fixed-function state that matters) and cached on the program.
|
|
6
|
+
* so a pipeline is built lazily per (program, vertex layout, state) and cached.
|
|
8
7
|
*
|
|
9
|
-
* A
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* A draw is mostly a cache lookup: `prepare_draw` returns the pipeline plus the
|
|
9
|
+
* vertex-layout bindings for the current state, and a repeated draw in the same
|
|
10
|
+
* render pass is one pipeline bind (when it changed) and one `SDL_Draw*` call.
|
|
11
|
+
* Everything that needs a GPU upload (buffer/texture data, an expanded index
|
|
12
|
+
* list, a constant attribute) records that upload *before* `begin_pass`, so an
|
|
13
|
+
* unchanged sequence of draws never ends the pass it is recording into.
|
|
12
14
|
*/
|
|
13
15
|
|
|
14
16
|
#include "webgl.h"
|
|
15
17
|
|
|
16
18
|
#include <algorithm>
|
|
17
19
|
#include <cstring>
|
|
18
|
-
#include <string>
|
|
19
20
|
#include <vector>
|
|
20
21
|
|
|
21
22
|
#include "gui_internal.h"
|
|
23
|
+
#include "perf.h"
|
|
22
24
|
|
|
23
25
|
namespace xtgui {
|
|
24
26
|
namespace {
|
|
@@ -36,150 +38,6 @@ int type_size(int type) {
|
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
int components_of_type(const std::string &type) {
|
|
40
|
-
if (!type.empty() && type.back() >= '2' && type.back() <= '4') return type.back() - '0';
|
|
41
|
-
return 1;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
SDL_GPUVertexElementFormat float_format(int size) {
|
|
45
|
-
switch (size) {
|
|
46
|
-
case 1:
|
|
47
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_FLOAT;
|
|
48
|
-
case 2:
|
|
49
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
|
|
50
|
-
case 3:
|
|
51
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3;
|
|
52
|
-
default:
|
|
53
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
SDL_GPUVertexElementFormat format_of(int size, int type, bool normalized) {
|
|
58
|
-
if (size < 1 || size > 4) return SDL_GPU_VERTEXELEMENTFORMAT_INVALID;
|
|
59
|
-
if (type == GL_FLOAT) return float_format(size);
|
|
60
|
-
if (type == GL_UNSIGNED_BYTE || type == GL_BYTE) {
|
|
61
|
-
const bool is_byte = type == GL_BYTE;
|
|
62
|
-
if (size == 2) {
|
|
63
|
-
return normalized ? (is_byte ? SDL_GPU_VERTEXELEMENTFORMAT_BYTE2_NORM
|
|
64
|
-
: SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2_NORM)
|
|
65
|
-
: (is_byte ? SDL_GPU_VERTEXELEMENTFORMAT_BYTE2
|
|
66
|
-
: SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2);
|
|
67
|
-
}
|
|
68
|
-
if (size == 4) {
|
|
69
|
-
return normalized ? (is_byte ? SDL_GPU_VERTEXELEMENTFORMAT_BYTE4_NORM
|
|
70
|
-
: SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM)
|
|
71
|
-
: (is_byte ? SDL_GPU_VERTEXELEMENTFORMAT_BYTE4
|
|
72
|
-
: SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4);
|
|
73
|
-
}
|
|
74
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_INVALID;
|
|
75
|
-
}
|
|
76
|
-
if (type == GL_UNSIGNED_SHORT || type == GL_SHORT) {
|
|
77
|
-
const bool is_short = type == GL_SHORT;
|
|
78
|
-
if (size == 2) {
|
|
79
|
-
return normalized ? (is_short ? SDL_GPU_VERTEXELEMENTFORMAT_SHORT2_NORM
|
|
80
|
-
: SDL_GPU_VERTEXELEMENTFORMAT_USHORT2_NORM)
|
|
81
|
-
: (is_short ? SDL_GPU_VERTEXELEMENTFORMAT_SHORT2
|
|
82
|
-
: SDL_GPU_VERTEXELEMENTFORMAT_USHORT2);
|
|
83
|
-
}
|
|
84
|
-
if (size == 4) {
|
|
85
|
-
return normalized ? (is_short ? SDL_GPU_VERTEXELEMENTFORMAT_SHORT4_NORM
|
|
86
|
-
: SDL_GPU_VERTEXELEMENTFORMAT_USHORT4_NORM)
|
|
87
|
-
: (is_short ? SDL_GPU_VERTEXELEMENTFORMAT_SHORT4
|
|
88
|
-
: SDL_GPU_VERTEXELEMENTFORMAT_USHORT4);
|
|
89
|
-
}
|
|
90
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_INVALID;
|
|
91
|
-
}
|
|
92
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_INVALID;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** `vertexAttribIPointer` formats: integer attributes keep their integer type
|
|
96
|
-
* in the shader (`in ivec3 …`). SDL has no 1- or 3-component byte/short
|
|
97
|
-
* integer formats, so only the sizes it can express are accepted. */
|
|
98
|
-
SDL_GPUVertexElementFormat int_format_of(int size, int type) {
|
|
99
|
-
if (size < 1 || size > 4) return SDL_GPU_VERTEXELEMENTFORMAT_INVALID;
|
|
100
|
-
if (type == GL_INT) {
|
|
101
|
-
switch (size) {
|
|
102
|
-
case 1:
|
|
103
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_INT;
|
|
104
|
-
case 2:
|
|
105
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_INT2;
|
|
106
|
-
case 3:
|
|
107
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_INT3;
|
|
108
|
-
default:
|
|
109
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_INT4;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (type == GL_UNSIGNED_INT) {
|
|
113
|
-
switch (size) {
|
|
114
|
-
case 1:
|
|
115
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_UINT;
|
|
116
|
-
case 2:
|
|
117
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_UINT2;
|
|
118
|
-
case 3:
|
|
119
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_UINT3;
|
|
120
|
-
default:
|
|
121
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_UINT4;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (type == GL_SHORT && (size == 2 || size == 4)) {
|
|
125
|
-
return size == 2 ? SDL_GPU_VERTEXELEMENTFORMAT_SHORT2 : SDL_GPU_VERTEXELEMENTFORMAT_SHORT4;
|
|
126
|
-
}
|
|
127
|
-
if (type == GL_UNSIGNED_SHORT && (size == 2 || size == 4)) {
|
|
128
|
-
return size == 2 ? SDL_GPU_VERTEXELEMENTFORMAT_USHORT2
|
|
129
|
-
: SDL_GPU_VERTEXELEMENTFORMAT_USHORT4;
|
|
130
|
-
}
|
|
131
|
-
if (type == GL_BYTE && (size == 2 || size == 4)) {
|
|
132
|
-
return size == 2 ? SDL_GPU_VERTEXELEMENTFORMAT_BYTE2 : SDL_GPU_VERTEXELEMENTFORMAT_BYTE4;
|
|
133
|
-
}
|
|
134
|
-
if (type == GL_UNSIGNED_BYTE && (size == 2 || size == 4)) {
|
|
135
|
-
return size == 2 ? SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2 : SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4;
|
|
136
|
-
}
|
|
137
|
-
return SDL_GPU_VERTEXELEMENTFORMAT_INVALID;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** A cache key covering everything (other than the program) that a
|
|
141
|
-
* `SDL_GPUGraphicsPipeline` bakes in. */
|
|
142
|
-
std::string pipeline_key(int mode, int index_size,
|
|
143
|
-
const std::vector<SDL_GPUVertexAttribute> &attrs,
|
|
144
|
-
const std::vector<SDL_GPUVertexBufferDescription> &buffers,
|
|
145
|
-
const WebGLDrawState &state) {
|
|
146
|
-
std::string key = std::to_string(mode) + "/" + std::to_string(index_size);
|
|
147
|
-
key += "/f" + std::to_string(state.color_target_count) + ":";
|
|
148
|
-
for (int i = 0; i < state.color_target_count; i++) {
|
|
149
|
-
key += std::to_string(state.color_formats[i]) + ",";
|
|
150
|
-
}
|
|
151
|
-
key += ":" + std::to_string(state.depth_format);
|
|
152
|
-
for (const SDL_GPUVertexAttribute &attr : attrs) {
|
|
153
|
-
key += "/" + std::to_string(attr.location) + ":" + std::to_string(attr.buffer_slot) + ":" +
|
|
154
|
-
std::to_string((int)attr.format) + ":" + std::to_string(attr.offset);
|
|
155
|
-
}
|
|
156
|
-
for (const SDL_GPUVertexBufferDescription &buffer : buffers) {
|
|
157
|
-
key += "|" + std::to_string(buffer.slot) + ":" + std::to_string(buffer.pitch) + ":" +
|
|
158
|
-
std::to_string((int)buffer.input_rate);
|
|
159
|
-
}
|
|
160
|
-
char state_key[256];
|
|
161
|
-
snprintf(state_key, sizeof(state_key), "|%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
|
162
|
-
(int)state.blend, state.blend_src_rgb, state.blend_dst_rgb, state.blend_src_alpha,
|
|
163
|
-
state.blend_dst_alpha, state.blend_eq_rgb, state.blend_eq_alpha, (int)state.depth_test,
|
|
164
|
-
(int)state.depth_write, state.depth_func, (int)state.cull, state.cull_face,
|
|
165
|
-
state.front_face, (int)state.color_mask[0]);
|
|
166
|
-
key += state_key;
|
|
167
|
-
key += std::to_string((int)state.color_mask[1]);
|
|
168
|
-
key += std::to_string((int)state.color_mask[2]);
|
|
169
|
-
key += std::to_string((int)state.color_mask[3]);
|
|
170
|
-
char stencil_key[224];
|
|
171
|
-
snprintf(stencil_key, sizeof(stencil_key), "|s%d,%d,%d,%d,%d,%u,%d,%d,%d,%d,%u,%u,%u",
|
|
172
|
-
(int)state.stencil, state.stencil_front.func, state.stencil_front.fail,
|
|
173
|
-
state.stencil_front.zfail, state.stencil_front.zpass,
|
|
174
|
-
(unsigned)state.stencil_front.write_mask, state.stencil_back.func,
|
|
175
|
-
state.stencil_back.fail, state.stencil_back.zfail, state.stencil_back.zpass,
|
|
176
|
-
(unsigned)state.stencil_back.write_mask,
|
|
177
|
-
(unsigned)state.stencil_front.value_mask,
|
|
178
|
-
(unsigned)state.stencil_front.write_mask);
|
|
179
|
-
key += stencil_key;
|
|
180
|
-
return key;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
41
|
} // namespace
|
|
184
42
|
|
|
185
43
|
void WebGLContext::draw_arrays(int mode, int first, int count) {
|
|
@@ -233,6 +91,7 @@ void WebGLContext::draw_range_elements(int mode, int start, int end, int count,
|
|
|
233
91
|
void WebGLContext::draw(int mode, int first, int count, int index_type, int offset,
|
|
234
92
|
int instances) {
|
|
235
93
|
if (count <= 0) return;
|
|
94
|
+
g_perf_frame.webglDraws += 1;
|
|
236
95
|
WebGLProgram *program_ = program(current_program_);
|
|
237
96
|
if (program_ == nullptr || !program_->linked || program_->vs_shader == nullptr) {
|
|
238
97
|
set_error(GL_INVALID_OPERATION);
|
|
@@ -244,13 +103,14 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
244
103
|
return;
|
|
245
104
|
}
|
|
246
105
|
ensure_fallback();
|
|
247
|
-
end_pass();
|
|
248
106
|
ensure_command();
|
|
107
|
+
if (cmd_ == nullptr) return;
|
|
249
108
|
|
|
250
109
|
/* Expand source indices when the draw needs a primitive SDL_GPU lacks or a
|
|
251
|
-
* byte-sized index type.
|
|
110
|
+
* byte-sized index type. These are per-draw temporary buffers: they change
|
|
111
|
+
* the index buffer, not the pipeline, so they stay out of the setup cache. */
|
|
252
112
|
std::vector<uint32_t> expanded;
|
|
253
|
-
SDL_GPUBuffer *
|
|
113
|
+
SDL_GPUBuffer *expanded_gpu = nullptr;
|
|
254
114
|
int index_size = 0;
|
|
255
115
|
int first_index = 0;
|
|
256
116
|
int draw_mode = mode;
|
|
@@ -302,10 +162,10 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
302
162
|
}
|
|
303
163
|
index_size = 4;
|
|
304
164
|
if (!expanded.empty()) {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (
|
|
165
|
+
expanded_gpu = upload_temp_buffer(expanded.data(),
|
|
166
|
+
(uint32_t)(expanded.size() * sizeof(uint32_t)),
|
|
167
|
+
SDL_GPU_BUFFERUSAGE_INDEX);
|
|
168
|
+
if (expanded_gpu == nullptr) return;
|
|
309
169
|
}
|
|
310
170
|
} else if (index_type != 0) {
|
|
311
171
|
WebGLBuffer *element = buffer(bound_element_);
|
|
@@ -313,8 +173,6 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
313
173
|
set_error(GL_INVALID_OPERATION);
|
|
314
174
|
return;
|
|
315
175
|
}
|
|
316
|
-
index_gpu = ensure_buffer_gpu(element);
|
|
317
|
-
if (index_gpu == nullptr) return;
|
|
318
176
|
index_size = type_size(index_type) == 4 ? 4 : 2;
|
|
319
177
|
first_index = offset / index_size;
|
|
320
178
|
}
|
|
@@ -333,77 +191,18 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
333
191
|
if (state_.color_target_count == 0) state_.color_target_count = 1;
|
|
334
192
|
state_.depth_format = target_depth_format();
|
|
335
193
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
194
|
+
WebGLDrawKey key;
|
|
195
|
+
key.program = current_program_;
|
|
196
|
+
key.mode = draw_mode;
|
|
197
|
+
key.index_size = index_size;
|
|
198
|
+
key.element_buffer = !needs_expand && index_size > 0 ? bound_element_ : 0;
|
|
199
|
+
key.attribs_version = attribs_version_;
|
|
200
|
+
key.gpu_version = gpu_version_;
|
|
201
|
+
key.framebuffer_version = framebuffer_version_;
|
|
202
|
+
draw_state_hash(&key.state_hash, &key.state_hash2);
|
|
339
203
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
if (location_it == program_->attrib_locations.end()) continue;
|
|
343
|
-
const int base_location = location_it->second;
|
|
344
|
-
if (base_location < 0 || base_location >= kWebGLMaxAttribs) continue;
|
|
345
|
-
WebGLAttribState &attrib = attribs_[base_location];
|
|
346
|
-
const int slots = decl.type == "mat2" ? 2 : (decl.type == "mat3" ? 3 : (decl.type == "mat4" ? 4 : 1));
|
|
347
|
-
const int components = slots > 1 ? slots : (components_of_type(decl.type) > 4 ? 4
|
|
348
|
-
: components_of_type(decl.type));
|
|
349
|
-
const uint32_t slot = (uint32_t)buffers.size();
|
|
350
|
-
SDL_GPUVertexBufferDescription description;
|
|
351
|
-
memset(&description, 0, sizeof(description));
|
|
352
|
-
description.slot = slot;
|
|
353
|
-
description.input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX;
|
|
354
|
-
SDL_GPUBufferBinding binding;
|
|
355
|
-
memset(&binding, 0, sizeof(binding));
|
|
356
|
-
if (!attrib.enabled) {
|
|
357
|
-
float values[4] = {attrib.current[0], attrib.current[1], attrib.current[2], attrib.current[3]};
|
|
358
|
-
binding.buffer = upload_temp_buffer(values, sizeof(values), SDL_GPU_BUFFERUSAGE_VERTEX);
|
|
359
|
-
description.pitch = 0;
|
|
360
|
-
if (binding.buffer == nullptr) continue;
|
|
361
|
-
for (int column = 0; column < slots; column++) {
|
|
362
|
-
SDL_GPUVertexAttribute attribute;
|
|
363
|
-
memset(&attribute, 0, sizeof(attribute));
|
|
364
|
-
attribute.location = (Uint32)(base_location + column);
|
|
365
|
-
attribute.buffer_slot = slot;
|
|
366
|
-
attribute.format = float_format(components);
|
|
367
|
-
attribute.offset = 0;
|
|
368
|
-
attributes.push_back(attribute);
|
|
369
|
-
}
|
|
370
|
-
buffers.push_back(description);
|
|
371
|
-
bindings.push_back(binding);
|
|
372
|
-
continue;
|
|
373
|
-
}
|
|
374
|
-
WebGLBuffer *buffer_ = buffer(attrib.buffer);
|
|
375
|
-
if (buffer_ == nullptr || buffer_->data.empty()) {
|
|
376
|
-
set_error(GL_INVALID_OPERATION);
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
SDL_GPUVertexElementFormat format = attrib.integer
|
|
380
|
-
? int_format_of(attrib.size, attrib.type)
|
|
381
|
-
: format_of(attrib.size, attrib.type, attrib.normalized);
|
|
382
|
-
if (format == SDL_GPU_VERTEXELEMENTFORMAT_INVALID) {
|
|
383
|
-
set_error(GL_INVALID_OPERATION);
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
description.input_rate = attrib.divisor > 0 ? SDL_GPU_VERTEXINPUTRATE_INSTANCE
|
|
387
|
-
: SDL_GPU_VERTEXINPUTRATE_VERTEX;
|
|
388
|
-
const int stride =
|
|
389
|
-
attrib.stride > 0 ? attrib.stride : components * type_size(attrib.type) * slots;
|
|
390
|
-
description.pitch = (Uint32)stride;
|
|
391
|
-
SDL_GPUBuffer *gpu = ensure_buffer_gpu(buffer_);
|
|
392
|
-
if (gpu == nullptr) return;
|
|
393
|
-
binding.buffer = gpu;
|
|
394
|
-
binding.offset = 0;
|
|
395
|
-
for (int column = 0; column < slots; column++) {
|
|
396
|
-
SDL_GPUVertexAttribute attribute;
|
|
397
|
-
memset(&attribute, 0, sizeof(attribute));
|
|
398
|
-
attribute.location = (Uint32)(base_location + column);
|
|
399
|
-
attribute.buffer_slot = slot;
|
|
400
|
-
attribute.format = format;
|
|
401
|
-
attribute.offset = (Uint32)(attrib.offset + column * components * type_size(attrib.type));
|
|
402
|
-
attributes.push_back(attribute);
|
|
403
|
-
}
|
|
404
|
-
buffers.push_back(description);
|
|
405
|
-
bindings.push_back(binding);
|
|
406
|
-
}
|
|
204
|
+
const WebGLDrawSetup *setup = prepare_draw(key);
|
|
205
|
+
if (setup == nullptr) return;
|
|
407
206
|
|
|
408
207
|
begin_pass(false, false, false);
|
|
409
208
|
if (pass_ == nullptr) return;
|
|
@@ -443,18 +242,29 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
443
242
|
if (scissor.h < 0) scissor.h = 0;
|
|
444
243
|
SDL_SetGPUScissor(pass_, &scissor);
|
|
445
244
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
245
|
+
/* Bindings belong to the render pass, so a setup reused across an upload (a
|
|
246
|
+
* new pass) must be bound again even though nothing about it changed. */
|
|
247
|
+
if (last_setup_ != setup || last_setup_pass_ != pass_serial_) {
|
|
248
|
+
SDL_BindGPUGraphicsPipeline(pass_, setup->pipeline);
|
|
249
|
+
if (!setup->bindings.empty()) {
|
|
250
|
+
SDL_BindGPUVertexBuffers(pass_, 0, setup->bindings.data(),
|
|
251
|
+
(Uint32)setup->bindings.size());
|
|
252
|
+
}
|
|
253
|
+
SDL_GPUBuffer *index_buffer = index_size > 0 ? (needs_expand ? expanded_gpu : setup->index_buffer)
|
|
254
|
+
: nullptr;
|
|
255
|
+
if (index_buffer != nullptr) {
|
|
256
|
+
SDL_GPUBufferBinding binding;
|
|
257
|
+
memset(&binding, 0, sizeof(binding));
|
|
258
|
+
binding.buffer = index_buffer;
|
|
259
|
+
binding.offset = 0;
|
|
260
|
+
SDL_BindGPUIndexBuffer(pass_, &binding,
|
|
261
|
+
index_size == 4 ? SDL_GPU_INDEXELEMENTSIZE_32BIT
|
|
262
|
+
: SDL_GPU_INDEXELEMENTSIZE_16BIT);
|
|
263
|
+
}
|
|
264
|
+
last_pipeline_ = setup->pipeline;
|
|
265
|
+
last_setup_ = setup;
|
|
266
|
+
last_setup_pass_ = pass_serial_;
|
|
454
267
|
}
|
|
455
|
-
if (pipeline == nullptr) return;
|
|
456
|
-
|
|
457
|
-
SDL_BindGPUGraphicsPipeline(pass_, pipeline);
|
|
458
268
|
if (state_.stencil) {
|
|
459
269
|
SDL_SetGPUStencilReference(pass_, (Uint8)(stencil_reference() & 0xFF));
|
|
460
270
|
}
|
|
@@ -466,17 +276,6 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
466
276
|
constants.a = blend_color_[3];
|
|
467
277
|
SDL_SetGPUBlendConstants(pass_, constants);
|
|
468
278
|
}
|
|
469
|
-
if (!bindings.empty()) {
|
|
470
|
-
SDL_BindGPUVertexBuffers(pass_, 0, bindings.data(), (Uint32)bindings.size());
|
|
471
|
-
}
|
|
472
|
-
if (index_size > 0) {
|
|
473
|
-
SDL_GPUBufferBinding binding;
|
|
474
|
-
binding.buffer = index_gpu;
|
|
475
|
-
binding.offset = 0;
|
|
476
|
-
SDL_BindGPUIndexBuffer(pass_, &binding,
|
|
477
|
-
index_size == 4 ? SDL_GPU_INDEXELEMENTSIZE_32BIT
|
|
478
|
-
: SDL_GPU_INDEXELEMENTSIZE_16BIT);
|
|
479
|
-
}
|
|
480
279
|
/* User uniform blocks live in the same std140 block; refresh their members
|
|
481
280
|
* from the CPU-side buffer bound to each block's binding point. */
|
|
482
281
|
for (const WebGLUniformBlock &block : program_->blocks) {
|
|
@@ -485,17 +284,17 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
485
284
|
if (binding.buffer == 0) continue;
|
|
486
285
|
WebGLBuffer *uniform_buffer = buffer(binding.buffer);
|
|
487
286
|
if (uniform_buffer == nullptr) continue;
|
|
488
|
-
size_t
|
|
287
|
+
size_t block_offset = binding.offset;
|
|
489
288
|
size_t length = (size_t)block.data_size;
|
|
490
289
|
if (binding.size > 0 && length > binding.size) length = binding.size;
|
|
491
|
-
if (
|
|
492
|
-
if (length > uniform_buffer->data.size() -
|
|
493
|
-
length = uniform_buffer->data.size() -
|
|
290
|
+
if (block_offset > uniform_buffer->data.size()) continue;
|
|
291
|
+
if (length > uniform_buffer->data.size() - block_offset) {
|
|
292
|
+
length = uniform_buffer->data.size() - block_offset;
|
|
494
293
|
}
|
|
495
294
|
if (block.base_offset >= 0 &&
|
|
496
295
|
block.base_offset + (int)length <= program_->block_size) {
|
|
497
296
|
memcpy(program_->block.data() + block.base_offset,
|
|
498
|
-
uniform_buffer->data.data() +
|
|
297
|
+
uniform_buffer->data.data() + block_offset, length);
|
|
499
298
|
}
|
|
500
299
|
}
|
|
501
300
|
|
|
@@ -503,32 +302,38 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
503
302
|
SDL_PushGPUVertexUniformData(cmd_, 0, program_->block.data(), (Uint32)program_->block.size());
|
|
504
303
|
}
|
|
505
304
|
if (program_->fs_has_block && program_->block_size > 0) {
|
|
506
|
-
SDL_PushGPUFragmentUniformData(cmd_, 0, program_->block.data(),
|
|
305
|
+
SDL_PushGPUFragmentUniformData(cmd_, 0, program_->block.data(),
|
|
306
|
+
(Uint32)program_->block.size());
|
|
507
307
|
}
|
|
508
308
|
|
|
509
309
|
auto bind_samplers = [&](const std::vector<int> &stage, bool vertex_stage) {
|
|
510
310
|
if (stage.empty()) return;
|
|
511
|
-
|
|
512
|
-
|
|
311
|
+
sampler_bindings_.clear();
|
|
312
|
+
sampler_bindings_.reserve(stage.size());
|
|
513
313
|
for (int uniform_index : stage) {
|
|
514
314
|
const WebGLUniform &uniform = program_->uniforms[(size_t)uniform_index];
|
|
515
315
|
const int unit =
|
|
516
316
|
uniform.unit >= 0 && uniform.unit < kWebGLMaxTextureUnits ? uniform.unit : 0;
|
|
517
317
|
uint32_t texture_id = bound_textures_[unit];
|
|
518
|
-
if (uniform.layout.gl_type == GL_SAMPLER_CUBE
|
|
318
|
+
if (uniform.layout.gl_type == GL_SAMPLER_CUBE ||
|
|
319
|
+
uniform.layout.gl_type == GL_SAMPLER_CUBE_SHADOW) {
|
|
519
320
|
texture_id = bound_cube_textures_[unit];
|
|
520
321
|
} else if (uniform.layout.gl_type == GL_SAMPLER_3D) {
|
|
521
322
|
texture_id = bound_3d_textures_[unit];
|
|
522
|
-
} else if (uniform.layout.gl_type == GL_SAMPLER_2D_ARRAY
|
|
323
|
+
} else if (uniform.layout.gl_type == GL_SAMPLER_2D_ARRAY ||
|
|
324
|
+
uniform.layout.gl_type == GL_SAMPLER_2D_ARRAY_SHADOW) {
|
|
523
325
|
texture_id = bound_array_textures_[unit];
|
|
524
326
|
}
|
|
525
327
|
WebGLTexture *sampled = texture(texture_id);
|
|
526
328
|
SDL_GPUTexture *gpu = sampled != nullptr ? ensure_texture_gpu(sampled, sampled->as_target)
|
|
527
329
|
: nullptr;
|
|
528
330
|
WebGLSampler *sampler_object = this->sampler(bound_samplers_[unit]);
|
|
529
|
-
SDL_GPUSampler *sampler =
|
|
530
|
-
|
|
531
|
-
|
|
331
|
+
SDL_GPUSampler *sampler = nullptr;
|
|
332
|
+
if (sampler_object != nullptr) {
|
|
333
|
+
sampler = sampler_gpu(sampler_object);
|
|
334
|
+
} else if (sampled != nullptr) {
|
|
335
|
+
sampler = uniform.compare ? sampler_for_compare(sampled) : sampler_for(sampled);
|
|
336
|
+
}
|
|
532
337
|
if (gpu == nullptr || sampler == nullptr) {
|
|
533
338
|
gpu = fallback_texture_;
|
|
534
339
|
sampler = fallback_sampler_;
|
|
@@ -536,14 +341,14 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
536
341
|
SDL_GPUTextureSamplerBinding texture_binding;
|
|
537
342
|
texture_binding.texture = gpu;
|
|
538
343
|
texture_binding.sampler = sampler;
|
|
539
|
-
|
|
344
|
+
sampler_bindings_.push_back(texture_binding);
|
|
540
345
|
}
|
|
541
346
|
if (vertex_stage) {
|
|
542
|
-
SDL_BindGPUVertexSamplers(pass_, 0,
|
|
543
|
-
(Uint32)
|
|
347
|
+
SDL_BindGPUVertexSamplers(pass_, 0, sampler_bindings_.data(),
|
|
348
|
+
(Uint32)sampler_bindings_.size());
|
|
544
349
|
} else {
|
|
545
|
-
SDL_BindGPUFragmentSamplers(pass_, 0,
|
|
546
|
-
(Uint32)
|
|
350
|
+
SDL_BindGPUFragmentSamplers(pass_, 0, sampler_bindings_.data(),
|
|
351
|
+
(Uint32)sampler_bindings_.size());
|
|
547
352
|
}
|
|
548
353
|
};
|
|
549
354
|
bind_samplers(program_->vs_sampler_uniforms, true);
|
|
@@ -557,4 +362,4 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
557
362
|
}
|
|
558
363
|
}
|
|
559
364
|
|
|
560
|
-
} // namespace xtgui
|
|
365
|
+
} // namespace xtgui
|