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.
Files changed (166) hide show
  1. package/dist/src/cli/help.d.ts +1 -1
  2. package/dist/src/codegen/generator/module.js +23 -7
  3. package/dist/src/codegen/generator/module.js.map +1 -1
  4. package/dist/src/codegen/generator/state.js +1 -0
  5. package/dist/src/codegen/generator/state.js.map +1 -1
  6. package/dist/src/codegen/generator/tables.js +1 -0
  7. package/dist/src/codegen/generator/tables.js.map +1 -1
  8. package/dist/src/driver/bundler/deferred.d.ts +63 -0
  9. package/dist/src/driver/bundler/deferred.js +279 -0
  10. package/dist/src/driver/bundler/deferred.js.map +1 -0
  11. package/dist/src/driver/bundler/merge.js +214 -2
  12. package/dist/src/driver/bundler/merge.js.map +1 -1
  13. package/dist/src/driver/runtime-objects.d.ts +1 -1
  14. package/dist/src/driver/runtime-objects.js +1 -0
  15. package/dist/src/driver/runtime-objects.js.map +1 -1
  16. package/dist/src/driver/version.d.ts +1 -1
  17. package/dist/src/driver/version.js +1 -1
  18. package/dist/src/extensions/gui/html.js +98 -15
  19. package/dist/src/extensions/gui/html.js.map +1 -1
  20. package/dist/src/extensions/gui/index.js +1 -0
  21. package/dist/src/extensions/gui/index.js.map +1 -1
  22. package/dist/src/extensions/gui/three.d.ts +4 -3
  23. package/dist/src/extensions/gui/three.js +4 -3
  24. package/dist/src/extensions/gui/three.js.map +1 -1
  25. package/dist/tests/codegen/closures.test.js +7 -0
  26. package/dist/tests/codegen/closures.test.js.map +1 -1
  27. package/dist/tests/e2e/compile-objects-classes.test.js +31 -0
  28. package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
  29. package/dist/tests/e2e/gui-canvas-state.test.d.ts +9 -0
  30. package/dist/tests/e2e/gui-canvas-state.test.js +297 -0
  31. package/dist/tests/e2e/gui-canvas-state.test.js.map +1 -0
  32. package/dist/tests/e2e/gui-draw-perf.test.d.ts +22 -0
  33. package/dist/tests/e2e/gui-draw-perf.test.js +405 -0
  34. package/dist/tests/e2e/gui-draw-perf.test.js.map +1 -0
  35. package/dist/tests/e2e/gui-perf.test.d.ts +23 -0
  36. package/dist/tests/e2e/gui-perf.test.js +283 -0
  37. package/dist/tests/e2e/gui-perf.test.js.map +1 -0
  38. package/dist/tests/e2e/gui-script-import-order.test.d.ts +10 -0
  39. package/dist/tests/e2e/gui-script-import-order.test.js +169 -0
  40. package/dist/tests/e2e/gui-script-import-order.test.js.map +1 -0
  41. package/dist/tests/e2e/gui-webgl.test.js +4 -4
  42. package/dist/tests/e2e/gui-webgl.test.js.map +1 -1
  43. package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.d.ts +8 -0
  44. package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.js +336 -0
  45. package/dist/tests/e2e/gui-webgl2-shadow-sampler.test.js.map +1 -0
  46. package/dist/tests/e2e/gui-webgl2-shadow.test.d.ts +10 -0
  47. package/dist/tests/e2e/gui-webgl2-shadow.test.js +108 -0
  48. package/dist/tests/e2e/gui-webgl2-shadow.test.js.map +1 -0
  49. package/dist/tests/e2e/url.test.d.ts +6 -0
  50. package/dist/tests/e2e/url.test.js +114 -0
  51. package/dist/tests/e2e/url.test.js.map +1 -0
  52. package/dist/tests/extensions/gui.test.js +45 -10
  53. package/dist/tests/extensions/gui.test.js.map +1 -1
  54. package/doc/gui/api.md +28 -2
  55. package/doc/gui/canvas.md +110 -27
  56. package/doc/gui/known-issues.md +32 -10
  57. package/doc/gui/rendering.md +77 -0
  58. package/doc/gui/runtime.md +18 -3
  59. package/doc/gui/webgl.md +58 -29
  60. package/doc/gui-scripts.md +19 -19
  61. package/doc/gui.md +43 -9
  62. package/doc/implemented/fetch.md +5 -0
  63. package/doc/implemented/modules.md +13 -0
  64. package/doc/implemented/stdlib.md +17 -0
  65. package/doc/unimplemented/deviations.md +1 -0
  66. package/doc/zh-CN/gui/api.md +25 -2
  67. package/doc/zh-CN/gui/canvas.md +95 -26
  68. package/doc/zh-CN/gui/known-issues.md +21 -4
  69. package/doc/zh-CN/gui/rendering.md +59 -0
  70. package/doc/zh-CN/gui/runtime.md +13 -3
  71. package/doc/zh-CN/gui/webgl.md +30 -8
  72. package/doc/zh-CN/gui-scripts.md +14 -13
  73. package/doc/zh-CN/gui.md +32 -8
  74. package/doc/zh-CN/implemented/fetch.md +4 -0
  75. package/doc/zh-CN/implemented/modules.md +10 -0
  76. package/doc/zh-CN/implemented/stdlib.md +15 -0
  77. package/doc/zh-CN/unimplemented/deviations.md +1 -0
  78. package/package.json +7 -7
  79. package/runtime/ext_gui/browser.cpp +3 -1
  80. package/runtime/ext_gui/canvas.cpp +135 -89
  81. package/runtime/ext_gui/canvas.h +116 -0
  82. package/runtime/ext_gui/canvas_clip.cpp +143 -0
  83. package/runtime/ext_gui/canvas_composite.cpp +241 -0
  84. package/runtime/ext_gui/canvas_coverage.cpp +241 -0
  85. package/runtime/ext_gui/canvas_gradient.cpp +41 -4
  86. package/runtime/ext_gui/canvas_image_data.cpp +4 -0
  87. package/runtime/ext_gui/canvas_internal.h +34 -9
  88. package/runtime/ext_gui/canvas_raster.cpp +207 -178
  89. package/runtime/ext_gui/canvas_shadow.cpp +161 -0
  90. package/runtime/ext_gui/canvas_stroke.cpp +37 -9
  91. package/runtime/ext_gui/canvas_style.cpp +59 -0
  92. package/runtime/ext_gui/canvas_text.cpp +140 -0
  93. package/runtime/ext_gui/css.h +7 -0
  94. package/runtime/ext_gui/css_sheet.cpp +22 -0
  95. package/runtime/ext_gui/document.cpp +25 -1
  96. package/runtime/ext_gui/document.h +8 -0
  97. package/runtime/ext_gui/dom_api_canvas.cpp +16 -1
  98. package/runtime/ext_gui/dom_api_canvas_image.cpp +9 -0
  99. package/runtime/ext_gui/dom_api_canvas_state.cpp +217 -0
  100. package/runtime/ext_gui/dom_api_internal.h +36 -37
  101. package/runtime/ext_gui/dom_api_offscreen.cpp +213 -0
  102. package/runtime/ext_gui/dom_api_proto.cpp +18 -0
  103. package/runtime/ext_gui/dom_api_webgl.cpp +29 -9
  104. package/runtime/ext_gui/dom_api_webgl2.cpp +33 -1
  105. package/runtime/ext_gui/dom_api_webgl_internal.h +58 -0
  106. package/runtime/ext_gui/dom_api_webgl_source.cpp +18 -0
  107. package/runtime/ext_gui/gradient_values.cpp +12 -1
  108. package/runtime/ext_gui/gui.cpp +5 -0
  109. package/runtime/ext_gui/gui_canvas.cpp +4 -0
  110. package/runtime/ext_gui/gui_engine.h +32 -0
  111. package/runtime/ext_gui/gui_events.cpp +182 -58
  112. package/runtime/ext_gui/gui_media.cpp +3 -0
  113. package/runtime/ext_gui/image.cpp +69 -0
  114. package/runtime/ext_gui/image_bitmap_browser.cpp +11 -0
  115. package/runtime/ext_gui/layout.cpp +4 -0
  116. package/runtime/ext_gui/paint.cpp +19 -0
  117. package/runtime/ext_gui/paint_background.cpp +18 -1
  118. package/runtime/ext_gui/perf.cpp +171 -0
  119. package/runtime/ext_gui/perf.h +127 -0
  120. package/runtime/ext_gui/renderer.cpp +109 -41
  121. package/runtime/ext_gui/renderer.h +33 -9
  122. package/runtime/ext_gui/renderer_image.cpp +135 -65
  123. package/runtime/ext_gui/renderer_internal.h +15 -3
  124. package/runtime/ext_gui/renderer_text.cpp +24 -12
  125. package/runtime/ext_gui/script.cpp +31 -0
  126. package/runtime/ext_gui/style.cpp +101 -30
  127. package/runtime/ext_gui/style.h +6 -3
  128. package/runtime/ext_gui/style_print.cpp +7 -1
  129. package/runtime/ext_gui/text.cpp +23 -4
  130. package/runtime/ext_gui/text.h +29 -0
  131. package/runtime/ext_gui/text_cache.cpp +118 -0
  132. package/runtime/ext_gui/text_glyph_cache.cpp +100 -0
  133. package/runtime/ext_gui/webgl.h +48 -146
  134. package/runtime/ext_gui/webgl_blit.cpp +12 -1
  135. package/runtime/ext_gui/webgl_blit_depth.cpp +270 -0
  136. package/runtime/ext_gui/webgl_buffer.cpp +59 -1
  137. package/runtime/ext_gui/webgl_buffer_objects.cpp +106 -9
  138. package/runtime/ext_gui/webgl_clear.cpp +3 -0
  139. package/runtime/ext_gui/webgl_context.cpp +29 -3
  140. package/runtime/ext_gui/webgl_draw.cpp +75 -270
  141. package/runtime/ext_gui/webgl_draw_buffers.cpp +1 -0
  142. package/runtime/ext_gui/webgl_draw_setup.cpp +321 -0
  143. package/runtime/ext_gui/webgl_draw_state.h +130 -0
  144. package/runtime/ext_gui/webgl_glsl.h +3 -0
  145. package/runtime/ext_gui/webgl_glsl_scan.cpp +3 -8
  146. package/runtime/ext_gui/webgl_glsl_unroll.cpp +283 -0
  147. package/runtime/ext_gui/webgl_msl.cpp +4 -0
  148. package/runtime/ext_gui/webgl_objects.h +148 -0
  149. package/runtime/ext_gui/webgl_pipeline.cpp +8 -8
  150. package/runtime/ext_gui/webgl_program_internal.h +35 -0
  151. package/runtime/ext_gui/webgl_shader.cpp +34 -36
  152. package/runtime/ext_gui/webgl_webgl2.cpp +36 -0
  153. package/runtime/ext_gui/window.cpp +56 -1
  154. package/runtime/rt.h +3 -0
  155. package/runtime/xt_fetch/async.inc +60 -0
  156. package/runtime/xt_url_object.c +463 -0
  157. package/src/codegen/generator/module.ts +22 -7
  158. package/src/codegen/generator/state.ts +1 -0
  159. package/src/codegen/generator/tables.ts +1 -0
  160. package/src/driver/bundler/deferred.ts +351 -0
  161. package/src/driver/bundler/merge.ts +219 -2
  162. package/src/driver/runtime-objects.ts +1 -0
  163. package/src/driver/version.ts +1 -1
  164. package/src/extensions/gui/html.ts +100 -17
  165. package/src/extensions/gui/index.ts +1 -0
  166. package/src/extensions/gui/three.ts +4 -3
@@ -12,12 +12,13 @@
12
12
  #include <cstring>
13
13
 
14
14
  #include "gui_internal.h"
15
+ #include "perf.h"
15
16
 
16
17
  namespace xtgui {
17
18
  namespace {
18
19
 
19
20
  bool upload_transfer(SDL_GPUDevice *device, SDL_GPUCommandBuffer *cmd, SDL_GPUBuffer *buffer,
20
- const void *bytes, uint32_t size) {
21
+ const void *bytes, uint32_t size, uint32_t offset) {
21
22
  if (size == 0) return true;
22
23
  SDL_GPUTransferBufferCreateInfo info;
23
24
  memset(&info, 0, sizeof(info));
@@ -39,6 +40,7 @@ bool upload_transfer(SDL_GPUDevice *device, SDL_GPUCommandBuffer *cmd, SDL_GPUBu
39
40
  SDL_GPUBufferRegion region;
40
41
  memset(&region, 0, sizeof(region));
41
42
  region.buffer = buffer;
43
+ region.offset = offset;
42
44
  region.size = size;
43
45
  SDL_UploadToGPUBuffer(copy, &source, &region, false);
44
46
  SDL_EndGPUCopyPass(copy);
@@ -46,6 +48,33 @@ bool upload_transfer(SDL_GPUDevice *device, SDL_GPUCommandBuffer *cmd, SDL_GPUBu
46
48
  return true;
47
49
  }
48
50
 
51
+ /** Extend a buffer's dirty range to cover `[offset, offset + size)`. Offsets
52
+ * are rounded to 4 bytes because the SDL_GPU copy path requires an aligned
53
+ * destination offset. */
54
+ void mark_dirty_range(WebGLBuffer *buffer, uint32_t offset, uint32_t size) {
55
+ if (size == 0) return;
56
+ uint32_t lo = offset & ~3u;
57
+ uint32_t hi = (offset + size + 3u) & ~3u;
58
+ if (hi > (uint32_t)buffer->data.size()) hi = (uint32_t)buffer->data.size();
59
+ if (lo > hi) lo = hi;
60
+ if (!buffer->dirty) {
61
+ buffer->dirty_lo = lo;
62
+ buffer->dirty_hi = hi;
63
+ } else {
64
+ buffer->dirty_lo = std::min(buffer->dirty_lo, lo);
65
+ buffer->dirty_hi = std::max(buffer->dirty_hi, hi);
66
+ }
67
+ buffer->dirty = true;
68
+ }
69
+
70
+ /** Round a byte size up to a power of two, so a growing buffer is reallocated
71
+ * O(log n) times instead of once per new frame's vertex count. */
72
+ uint32_t grow_capacity(uint32_t size) {
73
+ uint32_t capacity = 64;
74
+ while (capacity < size && capacity < (1u << 31)) capacity <<= 1;
75
+ return capacity < size ? size : capacity;
76
+ }
77
+
49
78
  } // namespace
50
79
 
51
80
  /* -- buffers ------------------------------------------------------------- */
@@ -66,6 +95,8 @@ void WebGLContext::delete_buffer(uint32_t id) {
66
95
  for (WebGLAttribState &attrib : attribs_) {
67
96
  if (attrib.buffer == id) attrib.buffer = 0;
68
97
  }
98
+ gpu_version_ += 1;
99
+ attribs_version_ += 1;
69
100
  if (found->second->gpu != nullptr && guidev::g_device != nullptr) {
70
101
  submit(); SDL_WaitForGPUIdle(guidev::g_device);
71
102
  SDL_ReleaseGPUBuffer(guidev::g_device, found->second->gpu);
@@ -107,7 +138,7 @@ bool WebGLContext::copy_buffer_sub_data(int read_target, int write_target, uint3
107
138
  memmove(write_buffer->data.data() + write_offset,
108
139
  read_buffer->data.data() + read_offset, size);
109
140
  }
110
- write_buffer->dirty = true;
141
+ mark_dirty_range(write_buffer, write_offset, size);
111
142
  return ensure_buffer_gpu(write_buffer) != nullptr || size == 0;
112
143
  }
113
144
 
@@ -125,39 +156,97 @@ bool WebGLContext::get_buffer_sub_data(int target, uint32_t offset, uint8_t *out
125
156
  SDL_GPUBuffer *WebGLContext::ensure_buffer_gpu(WebGLBuffer *buffer) {
126
157
  if (buffer == nullptr || guidev::g_device == nullptr) return nullptr;
127
158
  if (buffer->data.empty()) return nullptr;
159
+ const uint32_t size = (uint32_t)buffer->data.size();
160
+ const bool needs_storage = buffer->gpu == nullptr || buffer->capacity < size;
161
+ /* Steady state (data already on the GPU) must not end the open render pass:
162
+ * that was one pass restart per draw for every multi-element scene. */
163
+ if (!needs_storage && !buffer->dirty) return buffer->gpu;
128
164
  end_pass();
129
165
  ensure_command();
130
166
  if (cmd_ == nullptr) return nullptr;
131
- const uint32_t size = (uint32_t)buffer->data.size();
132
- if (buffer->gpu == nullptr || buffer->capacity < size) {
167
+ if (needs_storage) {
133
168
  if (buffer->gpu != nullptr) {
134
- submit(); SDL_WaitForGPUIdle(guidev::g_device);
169
+ submit();
170
+ SDL_WaitForGPUIdle(guidev::g_device);
135
171
  SDL_ReleaseGPUBuffer(guidev::g_device, buffer->gpu);
136
172
  }
137
173
  SDL_GPUBufferCreateInfo info;
138
174
  memset(&info, 0, sizeof(info));
139
175
  info.usage = SDL_GPU_BUFFERUSAGE_VERTEX | SDL_GPU_BUFFERUSAGE_INDEX;
140
- info.size = size;
176
+ info.size = grow_capacity(size);
141
177
  buffer->gpu = SDL_CreateGPUBuffer(guidev::g_device, &info);
142
- buffer->capacity = size;
178
+ buffer->capacity = info.size;
143
179
  if (buffer->gpu == nullptr) {
144
180
  set_error(GL_OUT_OF_MEMORY);
145
181
  return nullptr;
146
182
  }
183
+ /* A fresh buffer holds nothing: everything must be uploaded. */
184
+ buffer->dirty_lo = 0;
185
+ buffer->dirty_hi = size;
186
+ buffer->dirty = true;
187
+ /* Cached draw setups hold the old handle. */
188
+ gpu_version_ += 1;
147
189
  }
148
190
  if (buffer->dirty) {
149
191
  /* Recreating the buffer above submitted the pending command buffer. */
150
192
  ensure_command();
151
193
  if (cmd_ == nullptr) return nullptr;
152
- if (!upload_transfer(guidev::g_device, cmd_, buffer->gpu, buffer->data.data(), size)) {
194
+ uint32_t lo = std::min(buffer->dirty_lo, size);
195
+ uint32_t hi = std::min(buffer->dirty_hi, size);
196
+ if (hi > lo &&
197
+ !upload_transfer(guidev::g_device, cmd_, buffer->gpu, buffer->data.data() + lo, hi - lo,
198
+ lo)) {
153
199
  set_error(GL_OUT_OF_MEMORY);
154
200
  return nullptr;
155
201
  }
202
+ g_perf_frame.webglBufferUploadBytes += hi - lo;
156
203
  buffer->dirty = false;
204
+ buffer->dirty_lo = 0;
205
+ buffer->dirty_hi = 0;
157
206
  }
158
207
  return buffer->gpu;
159
208
  }
160
209
 
210
+ bool WebGLContext::upload_buffer_range(SDL_GPUBuffer *gpu, uint32_t offset, const void *bytes,
211
+ uint32_t size) {
212
+ if (gpu == nullptr || size == 0) return true;
213
+ end_pass();
214
+ ensure_command();
215
+ if (cmd_ == nullptr) return false;
216
+ if (!upload_transfer(guidev::g_device, cmd_, gpu, bytes, size, offset)) {
217
+ set_error(GL_OUT_OF_MEMORY);
218
+ return false;
219
+ }
220
+ g_perf_frame.webglBufferUploadBytes += size;
221
+ return true;
222
+ }
223
+
224
+ SDL_GPUBuffer *WebGLContext::constant_attrib_buffer(int index) {
225
+ if (index < 0 || index >= kWebGLMaxAttribs || guidev::g_device == nullptr) return nullptr;
226
+ WebGLAttribState &attrib = attribs_[index];
227
+ if (attrib.constant_gpu == nullptr) {
228
+ SDL_GPUBufferCreateInfo info;
229
+ memset(&info, 0, sizeof(info));
230
+ info.usage = SDL_GPU_BUFFERUSAGE_VERTEX;
231
+ info.size = sizeof(attrib.current);
232
+ attrib.constant_gpu = SDL_CreateGPUBuffer(guidev::g_device, &info);
233
+ if (attrib.constant_gpu == nullptr) {
234
+ set_error(GL_OUT_OF_MEMORY);
235
+ return nullptr;
236
+ }
237
+ attrib.constant_bytes = (uint32_t)sizeof(attrib.current);
238
+ attrib.constant_dirty = true;
239
+ }
240
+ if (attrib.constant_dirty) {
241
+ if (!upload_buffer_range(attrib.constant_gpu, 0, attrib.current,
242
+ (uint32_t)sizeof(attrib.current))) {
243
+ return nullptr;
244
+ }
245
+ attrib.constant_dirty = false;
246
+ }
247
+ return attrib.constant_gpu;
248
+ }
249
+
161
250
  bool WebGLContext::buffer_data(uint32_t id, const uint8_t *bytes, uint32_t size, int usage) {
162
251
  WebGLBuffer *record = buffer(id);
163
252
  if (record == nullptr) {
@@ -173,6 +262,8 @@ bool WebGLContext::buffer_data(uint32_t id, const uint8_t *bytes, uint32_t size,
173
262
  record->data.assign(size, 0);
174
263
  if (bytes != nullptr && size > 0) memcpy(record->data.data(), bytes, size);
175
264
  record->dirty = true;
265
+ record->dirty_lo = 0;
266
+ record->dirty_hi = size;
176
267
  return ensure_buffer_gpu(record) != nullptr || size == 0;
177
268
  }
178
269
 
@@ -185,7 +276,7 @@ bool WebGLContext::buffer_sub_data(uint32_t id, uint32_t offset, const uint8_t *
185
276
  return false;
186
277
  }
187
278
  memcpy(record->data.data() + offset, bytes, size);
188
- record->dirty = true;
279
+ mark_dirty_range(record, offset, size);
189
280
  return ensure_buffer_gpu(record) != nullptr;
190
281
  }
191
282
 
@@ -202,6 +293,7 @@ void WebGLContext::enable_attrib(int index, bool enabled) {
202
293
  return;
203
294
  }
204
295
  attribs_[index].enabled = enabled;
296
+ attribs_version_ += 1;
205
297
  }
206
298
 
207
299
  bool WebGLContext::attrib_enabled(int index) const {
@@ -222,6 +314,7 @@ void WebGLContext::attrib_pointer(int index, int size, int type, bool normalized
222
314
  attrib.integer = false;
223
315
  attrib.stride = stride > 0 ? stride : 0;
224
316
  attrib.offset = offset;
317
+ attribs_version_ += 1;
225
318
  }
226
319
 
227
320
  void WebGLContext::attrib_ipointer(int index, int size, int type, int stride, int offset) {
@@ -237,6 +330,7 @@ void WebGLContext::attrib_ipointer(int index, int size, int type, int stride, in
237
330
  attrib.integer = true;
238
331
  attrib.stride = stride > 0 ? stride : 0;
239
332
  attrib.offset = offset;
333
+ attribs_version_ += 1;
240
334
  }
241
335
 
242
336
  void WebGLContext::attrib_divisor(int index, int divisor) {
@@ -248,12 +342,15 @@ void WebGLContext::attrib_divisor(int index, int divisor) {
248
342
  * rates WebGL programs use — per vertex (0) and per instance (1) — map onto
249
343
  * the backend. A larger divisor is clamped. */
250
344
  attribs_[index].divisor = divisor > 0 ? 1 : 0;
345
+ attribs_version_ += 1;
251
346
  }
252
347
 
253
348
  void WebGLContext::attrib_value(int index, int components, const float *values) {
254
349
  if (index < 0 || index >= kWebGLMaxAttribs) return;
255
350
  for (int i = 0; i < 4; i++) attribs_[index].current[i] = i < components ? values[i] : 0.0f;
256
351
  if (components < 4) attribs_[index].current[3] = 1.0f;
352
+ attribs_[index].constant_dirty = true;
353
+ attribs_version_ += 1;
257
354
  }
258
355
 
259
356
  void WebGLContext::attrib_state(int index, int *size, int *type, int *stride, bool *normalized,
@@ -114,6 +114,8 @@ void WebGLContext::scissored_clear(int mask) {
114
114
  attribs_[attrib].type = GL_FLOAT;
115
115
  attribs_[attrib].stride = 8;
116
116
  attribs_[attrib].offset = 0;
117
+ /* The temporary attribute layout must not be mistaken for the caller's. */
118
+ attribs_version_ += 1;
117
119
  int target_width = 0;
118
120
  int target_height = 0;
119
121
  framebuffer_size(bound_framebuffer_, &target_width, &target_height);
@@ -136,6 +138,7 @@ void WebGLContext::scissored_clear(int mask) {
136
138
  current_program_ = saved_program;
137
139
  bound_array_ = saved_array;
138
140
  memcpy(attribs_, saved_attribs, sizeof(attribs_));
141
+ attribs_version_ += 1;
139
142
  for (int i = 0; i < 4; i++) viewport_[i] = saved_viewport[i];
140
143
  }
141
144
 
@@ -15,6 +15,7 @@
15
15
  #include <cstring>
16
16
 
17
17
  #include "gui_internal.h"
18
+ #include "perf.h"
18
19
 
19
20
  namespace xtgui {
20
21
  namespace {
@@ -54,13 +55,22 @@ void WebGLContext::release_gpu_resources() {
54
55
  if (guidev::g_device == nullptr) return;
55
56
  SDL_WaitForGPUIdle(guidev::g_device);
56
57
  for (auto &entry : programs_) release_program_pipelines(entry.second.get());
58
+ for (auto &entry : internal_pipelines_) {
59
+ if (entry.second != nullptr) SDL_ReleaseGPUGraphicsPipeline(guidev::g_device, entry.second);
60
+ }
61
+ internal_pipelines_.clear();
62
+ clear_draw_cache();
57
63
  for (auto &entry : textures_) {
58
64
  if (entry.second->gpu != nullptr) SDL_ReleaseGPUTexture(guidev::g_device, entry.second->gpu);
59
65
  if (entry.second->sampler != nullptr) {
60
66
  SDL_ReleaseGPUSampler(guidev::g_device, entry.second->sampler);
61
67
  }
68
+ if (entry.second->compare_sampler != nullptr) {
69
+ SDL_ReleaseGPUSampler(guidev::g_device, entry.second->compare_sampler);
70
+ }
62
71
  entry.second->gpu = nullptr;
63
72
  entry.second->sampler = nullptr;
73
+ entry.second->compare_sampler = nullptr;
64
74
  }
65
75
  for (auto &entry : buffers_) {
66
76
  if (entry.second->gpu != nullptr) SDL_ReleaseGPUBuffer(guidev::g_device, entry.second->gpu);
@@ -95,6 +105,10 @@ void WebGLContext::release_gpu_resources() {
95
105
  SDL_ReleaseGPUSampler(guidev::g_device, fallback_sampler_);
96
106
  fallback_sampler_ = nullptr;
97
107
  }
108
+ if (blit_sampler_ != nullptr) {
109
+ SDL_ReleaseGPUSampler(guidev::g_device, blit_sampler_);
110
+ blit_sampler_ = nullptr;
111
+ }
98
112
  if (color_ != nullptr) {
99
113
  SDL_ReleaseGPUTexture(guidev::g_device, color_);
100
114
  color_ = nullptr;
@@ -118,6 +132,8 @@ void WebGLContext::lose_context() {
118
132
  * after the restore. */
119
133
  shaders_.clear();
120
134
  programs_.clear();
135
+ clear_draw_cache();
136
+ internal_pipelines_.clear();
121
137
  buffers_.clear();
122
138
  textures_.clear();
123
139
  framebuffers_.clear();
@@ -198,7 +214,8 @@ void WebGLContext::ensure_default_target() {
198
214
  info.sample_count = SDL_GPU_SAMPLECOUNT_1;
199
215
  if (color_ == nullptr) color_ = SDL_CreateGPUTexture(guidev::g_device, &info);
200
216
  info.format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT;
201
- info.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
217
+ /* SAMPLER too: `blitFramebuffer` may copy the default depth attachment. */
218
+ info.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER;
202
219
  if (depth_ == nullptr) depth_ = SDL_CreateGPUTexture(guidev::g_device, &info);
203
220
  }
204
221
 
@@ -234,6 +251,7 @@ void WebGLContext::resize(int width, int height) {
234
251
  if (height < 0) height = 0;
235
252
  width_ = width > 0 ? width : 1;
236
253
  height_ = height > 0 ? height : 1;
254
+ framebuffer_version_ += 1;
237
255
  viewport_[0] = 0;
238
256
  viewport_[1] = 0;
239
257
  viewport_[2] = width_;
@@ -290,11 +308,15 @@ void WebGLContext::framebuffer_size(uint32_t id, int *width, int *height) {
290
308
  }
291
309
 
292
310
  SDL_GPUTexture *WebGLContext::target_depth() {
293
- if (bound_framebuffer_ == 0) {
311
+ return framebuffer_depth(bound_framebuffer_);
312
+ }
313
+
314
+ SDL_GPUTexture *WebGLContext::framebuffer_depth(uint32_t id) {
315
+ if (id == 0) {
294
316
  ensure_default_target();
295
317
  return depth_;
296
318
  }
297
- WebGLFramebuffer *framebuffer = this->framebuffer(bound_framebuffer_);
319
+ WebGLFramebuffer *framebuffer = this->framebuffer(id);
298
320
  if (framebuffer == nullptr) return nullptr;
299
321
  if (framebuffer->depth_texture != 0) {
300
322
  WebGLTexture *texture = this->texture(framebuffer->depth_texture);
@@ -393,6 +415,10 @@ void WebGLContext::begin_pass(bool clear_color, bool clear_depth, bool clear_ste
393
415
 
394
416
  pass_ = SDL_BeginGPURenderPass(cmd_, color_infos, (Uint32)color_count,
395
417
  depth != nullptr ? &depth_info : nullptr);
418
+ if (pass_ != nullptr) {
419
+ g_perf_frame.webglPasses += 1;
420
+ pass_serial_ += 1;
421
+ }
396
422
  pass_targets_default_ = bound_framebuffer_ == 0;
397
423
  pass_framebuffer_ = bound_framebuffer_;
398
424
  }