xbintsc 0.5.32 → 0.5.36
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 +10 -7
- package/README.zh-CN.md +10 -8
- package/dist/scripts/check-version.d.ts +27 -0
- package/dist/scripts/check-version.js +71 -0
- package/dist/scripts/check-version.js.map +1 -0
- package/dist/scripts/package-platform.d.ts +58 -0
- package/dist/scripts/package-platform.js +142 -0
- package/dist/scripts/package-platform.js.map +1 -0
- package/dist/scripts/verify-platform-package.d.ts +34 -0
- package/dist/scripts/verify-platform-package.js +161 -0
- package/dist/scripts/verify-platform-package.js.map +1 -0
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/cli/main.js +3 -1
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/driver/runtime-lib.d.ts +29 -4
- package/dist/src/driver/runtime-lib.js +68 -10
- package/dist/src/driver/runtime-lib.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/index.js +6 -5
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/media/index.js +4 -3
- package/dist/src/extensions/media/index.js.map +1 -1
- package/dist/src/parser/context.d.ts +41 -0
- package/dist/src/parser/context.js +89 -4
- package/dist/src/parser/context.js.map +1 -1
- package/dist/src/parser/literals.js +6 -12
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/driver/platform-package.test.d.ts +1 -0
- package/dist/tests/driver/platform-package.test.js +49 -0
- package/dist/tests/driver/platform-package.test.js.map +1 -0
- package/dist/tests/driver/runtime-lib.test.js +51 -4
- package/dist/tests/driver/runtime-lib.test.js.map +1 -1
- package/dist/tests/e2e/gui-audio.test.d.ts +14 -0
- package/dist/tests/e2e/gui-audio.test.js +287 -0
- package/dist/tests/e2e/gui-audio.test.js.map +1 -0
- package/dist/tests/e2e/gui-helpers.d.ts +7 -0
- package/dist/tests/e2e/gui-helpers.js +1 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.js +78 -0
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-style.test.js +55 -0
- package/dist/tests/e2e/gui-style.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl.test.js +258 -0
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl2-3d.test.d.ts +4 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.js +264 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.js +262 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.d.ts +6 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.js +395 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.d.ts +4 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.js +105 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.d.ts +8 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.js +112 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2.test.js +45 -1
- package/dist/tests/e2e/gui-webgl2.test.js.map +1 -1
- package/dist/tests/extensions/gui-index.test.js +1 -0
- package/dist/tests/extensions/gui-index.test.js.map +1 -1
- package/dist/tests/extensions/media.test.js +1 -0
- package/dist/tests/extensions/media.test.js.map +1 -1
- package/dist/tests/parser/expressions.test.js +30 -0
- package/dist/tests/parser/expressions.test.js.map +1 -1
- package/dist/tests/platform-tarball.test.d.ts +1 -0
- package/dist/tests/platform-tarball.test.js +111 -0
- package/dist/tests/platform-tarball.test.js.map +1 -0
- package/dist/tests/version.test.js +6 -0
- package/dist/tests/version.test.js.map +1 -1
- package/doc/ai/contributing.md +11 -0
- package/doc/ai/extensions.md +7 -4
- package/doc/ai/troubleshooting.md +7 -5
- package/doc/ai/zh-CN/contributing.md +9 -0
- package/doc/ai/zh-CN/extensions.md +4 -2
- package/doc/ai/zh-CN/troubleshooting.md +5 -3
- package/doc/gui/api.md +61 -13
- package/doc/gui/build.md +11 -4
- package/doc/gui/dom.md +6 -3
- package/doc/gui/media.md +4 -0
- package/doc/gui/webgl.md +105 -46
- package/doc/gui.md +7 -3
- package/doc/npm-package.md +55 -27
- package/doc/requirements.md +6 -2
- package/doc/zh-CN/gui/api.md +51 -10
- package/doc/zh-CN/gui/build.md +7 -2
- package/doc/zh-CN/gui/dom.md +3 -1
- package/doc/zh-CN/gui/media.md +3 -0
- package/doc/zh-CN/gui/webgl.md +22 -16
- package/doc/zh-CN/gui.md +3 -2
- package/doc/zh-CN/npm-package.md +44 -23
- package/doc/zh-CN/requirements.md +4 -1
- package/package.json +17 -1
- package/runtime/ext_gui/audio.cpp +365 -153
- package/runtime/ext_gui/audio_buffer.cpp +166 -0
- package/runtime/ext_gui/audio_buffer.h +37 -0
- package/runtime/ext_gui/audio_decode.cpp +219 -0
- package/runtime/ext_gui/audio_decode.h +39 -0
- package/runtime/ext_gui/audio_device.cpp +87 -0
- package/runtime/ext_gui/audio_effects.cpp +163 -0
- package/runtime/ext_gui/audio_effects.h +25 -0
- package/runtime/ext_gui/audio_internal.h +30 -0
- package/runtime/ext_gui/audio_mixer.cpp +494 -0
- package/runtime/ext_gui/audio_mixer.h +238 -0
- package/runtime/ext_gui/audio_param.cpp +104 -0
- package/runtime/ext_gui/audio_param_object.cpp +155 -0
- package/runtime/ext_gui/browser.cpp +11 -1
- package/runtime/ext_gui/css_selector.cpp +21 -3
- package/runtime/ext_gui/dom_api_internal.h +16 -0
- package/runtime/ext_gui/dom_api_webgl.cpp +7 -0
- package/runtime/ext_gui/dom_api_webgl2.cpp +151 -36
- package/runtime/ext_gui/dom_api_webgl2_draw.cpp +3 -3
- package/runtime/ext_gui/dom_api_webgl_buffer.cpp +6 -2
- package/runtime/ext_gui/dom_api_webgl_compressed.cpp +167 -0
- package/runtime/ext_gui/dom_api_webgl_framebuffer.cpp +160 -0
- package/runtime/ext_gui/dom_api_webgl_shader.cpp +4 -4
- package/runtime/ext_gui/dom_api_webgl_source.cpp +161 -0
- package/runtime/ext_gui/dom_api_webgl_state.cpp +169 -23
- package/runtime/ext_gui/dom_api_webgl_texture.cpp +276 -236
- package/runtime/ext_gui/dom_api_webgl_ubo.cpp +81 -0
- package/runtime/ext_gui/gui.cpp +44 -9
- package/runtime/ext_gui/gui_engine.h +9 -4
- package/runtime/ext_gui/image_bitmap.cpp +28 -0
- package/runtime/ext_gui/image_bitmap.h +26 -0
- package/runtime/ext_gui/image_bitmap_browser.cpp +136 -0
- package/runtime/ext_gui/media.cpp +32 -0
- package/runtime/ext_gui/media.h +13 -0
- package/runtime/ext_gui/media_api.h +23 -0
- package/runtime/ext_gui/webgl.h +152 -18
- package/runtime/ext_gui/webgl_blit.cpp +95 -0
- package/runtime/ext_gui/webgl_buffer.cpp +178 -263
- package/runtime/ext_gui/webgl_buffer_objects.cpp +270 -0
- package/runtime/ext_gui/webgl_clear.cpp +142 -0
- package/runtime/ext_gui/webgl_compressed.cpp +180 -0
- package/runtime/ext_gui/webgl_context.cpp +241 -156
- package/runtime/ext_gui/webgl_draw.cpp +68 -3
- package/runtime/ext_gui/webgl_draw_buffers.cpp +75 -0
- package/runtime/ext_gui/webgl_glsl.h +40 -0
- package/runtime/ext_gui/webgl_glsl_compile.cpp +6 -0
- package/runtime/ext_gui/webgl_glsl_rewrite.cpp +18 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +20 -11
- package/runtime/ext_gui/webgl_glsl_scan_block.cpp +126 -0
- package/runtime/ext_gui/webgl_glsl_tokens.h +28 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +71 -19
- package/runtime/ext_gui/webgl_program_blocks.cpp +58 -0
- package/runtime/ext_gui/webgl_program_internal.h +6 -0
- package/runtime/ext_gui/webgl_shader.cpp +13 -1
- package/runtime/ext_gui/webgl_state.cpp +228 -0
- package/runtime/ext_gui/webgl_texture.cpp +144 -17
- package/runtime/ext_gui/webgl_texture_3d.cpp +215 -0
- package/runtime/ext_gui/webgl_uniform_block.h +31 -0
- package/runtime/ext_gui/webgl_webgl2.cpp +58 -5
- package/runtime/ext_media/decode_audio.cpp +308 -0
- package/runtime/ext_media/media_bridge.c +2 -0
- package/runtime/rt.h +17 -0
- package/runtime/xt_array_buffer.c +30 -0
- package/runtime/xt_typed_array/elements.inc +13 -0
- package/scripts/build-media.ts +14 -6
- package/scripts/build-runtime.ts +21 -16
- package/scripts/check-version.ts +39 -9
- package/scripts/package-platform.ts +183 -0
- package/scripts/set-platform-version.ts +62 -0
- package/scripts/verify-platform-package.ts +182 -0
- package/src/cli/main.ts +5 -1
- package/src/driver/runtime-lib.ts +73 -9
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/index.ts +6 -5
- package/src/extensions/media/index.ts +4 -3
- package/src/parser/context.ts +99 -4
- package/src/parser/literals.ts +6 -12
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* xbintsc GUI engine — WebGL context lifetime
|
|
3
|
-
* state.
|
|
2
|
+
* xbintsc GUI engine — WebGL context lifetime and GPU targets.
|
|
4
3
|
*
|
|
5
4
|
* Every context records into one SDL_GPU command buffer. A render pass stays
|
|
6
5
|
* open across draws and is ended whenever a copy pass (buffer/texture upload)
|
|
7
6
|
* or a different attachment has to be recorded; the next draw starts a new
|
|
8
7
|
* pass with `LOAD`, so the framebuffer persists like a WebGL drawing buffer.
|
|
8
|
+
* Fixed-function state lives in `webgl_state.cpp`.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
#include "webgl.h"
|
|
@@ -46,38 +46,130 @@ WebGLContext::WebGLContext(uint64_t id, int width, int height, bool webgl2)
|
|
|
46
46
|
|
|
47
47
|
WebGLContext::~WebGLContext() {
|
|
48
48
|
submit();
|
|
49
|
-
if (guidev::g_device != nullptr)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
for (auto &entry : samplers_) {
|
|
62
|
-
if (entry.second->gpu != nullptr) {
|
|
63
|
-
SDL_ReleaseGPUSampler(guidev::g_device, entry.second->gpu);
|
|
64
|
-
}
|
|
49
|
+
if (guidev::g_device != nullptr) release_gpu_resources();
|
|
50
|
+
g_contexts.erase(id_);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
void WebGLContext::release_gpu_resources() {
|
|
54
|
+
if (guidev::g_device == nullptr) return;
|
|
55
|
+
SDL_WaitForGPUIdle(guidev::g_device);
|
|
56
|
+
for (auto &entry : programs_) release_program_pipelines(entry.second.get());
|
|
57
|
+
for (auto &entry : textures_) {
|
|
58
|
+
if (entry.second->gpu != nullptr) SDL_ReleaseGPUTexture(guidev::g_device, entry.second->gpu);
|
|
59
|
+
if (entry.second->sampler != nullptr) {
|
|
60
|
+
SDL_ReleaseGPUSampler(guidev::g_device, entry.second->sampler);
|
|
65
61
|
}
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
entry.second->gpu = nullptr;
|
|
63
|
+
entry.second->sampler = nullptr;
|
|
64
|
+
}
|
|
65
|
+
for (auto &entry : buffers_) {
|
|
66
|
+
if (entry.second->gpu != nullptr) SDL_ReleaseGPUBuffer(guidev::g_device, entry.second->gpu);
|
|
67
|
+
entry.second->gpu = nullptr;
|
|
68
|
+
entry.second->capacity = 0;
|
|
69
|
+
}
|
|
70
|
+
for (auto &entry : samplers_) {
|
|
71
|
+
if (entry.second->gpu != nullptr) {
|
|
72
|
+
SDL_ReleaseGPUSampler(guidev::g_device, entry.second->gpu);
|
|
73
|
+
entry.second->gpu = nullptr;
|
|
68
74
|
}
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
}
|
|
76
|
+
for (auto &entry : framebuffers_) {
|
|
77
|
+
if (entry.second->depth != nullptr) {
|
|
78
|
+
SDL_ReleaseGPUTexture(guidev::g_device, entry.second->depth);
|
|
79
|
+
entry.second->depth = nullptr;
|
|
71
80
|
}
|
|
72
|
-
|
|
73
|
-
|
|
81
|
+
}
|
|
82
|
+
for (auto &entry : renderbuffers_) {
|
|
83
|
+
if (entry.second->depth != nullptr) {
|
|
84
|
+
SDL_ReleaseGPUTexture(guidev::g_device, entry.second->depth);
|
|
85
|
+
entry.second->depth = nullptr;
|
|
74
86
|
}
|
|
75
|
-
if (fallback_texture_ != nullptr) SDL_ReleaseGPUTexture(guidev::g_device, fallback_texture_);
|
|
76
|
-
if (fallback_sampler_ != nullptr) SDL_ReleaseGPUSampler(guidev::g_device, fallback_sampler_);
|
|
77
|
-
if (color_ != nullptr) SDL_ReleaseGPUTexture(guidev::g_device, color_);
|
|
78
|
-
if (depth_ != nullptr) SDL_ReleaseGPUTexture(guidev::g_device, depth_);
|
|
79
87
|
}
|
|
80
|
-
|
|
88
|
+
for (SDL_GPUBuffer *buffer : temp_buffers_) SDL_ReleaseGPUBuffer(guidev::g_device, buffer);
|
|
89
|
+
temp_buffers_.clear();
|
|
90
|
+
if (fallback_texture_ != nullptr) {
|
|
91
|
+
SDL_ReleaseGPUTexture(guidev::g_device, fallback_texture_);
|
|
92
|
+
fallback_texture_ = nullptr;
|
|
93
|
+
}
|
|
94
|
+
if (fallback_sampler_ != nullptr) {
|
|
95
|
+
SDL_ReleaseGPUSampler(guidev::g_device, fallback_sampler_);
|
|
96
|
+
fallback_sampler_ = nullptr;
|
|
97
|
+
}
|
|
98
|
+
if (color_ != nullptr) {
|
|
99
|
+
SDL_ReleaseGPUTexture(guidev::g_device, color_);
|
|
100
|
+
color_ = nullptr;
|
|
101
|
+
}
|
|
102
|
+
if (depth_ != nullptr) {
|
|
103
|
+
SDL_ReleaseGPUTexture(guidev::g_device, depth_);
|
|
104
|
+
depth_ = nullptr;
|
|
105
|
+
}
|
|
106
|
+
if (clear_texture_ != nullptr) {
|
|
107
|
+
SDL_ReleaseGPUTexture(guidev::g_device, clear_texture_);
|
|
108
|
+
clear_texture_ = nullptr;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
void WebGLContext::lose_context() {
|
|
113
|
+
if (lost_) return;
|
|
114
|
+
submit();
|
|
115
|
+
if (guidev::g_device != nullptr) release_gpu_resources();
|
|
116
|
+
/* The WebGL spec invalidates every object when the context is lost: a page
|
|
117
|
+
* that gets `webglcontextlost` must recreate buffers, textures and programs
|
|
118
|
+
* after the restore. */
|
|
119
|
+
shaders_.clear();
|
|
120
|
+
programs_.clear();
|
|
121
|
+
buffers_.clear();
|
|
122
|
+
textures_.clear();
|
|
123
|
+
framebuffers_.clear();
|
|
124
|
+
renderbuffers_.clear();
|
|
125
|
+
vertex_arrays_.clear();
|
|
126
|
+
samplers_.clear();
|
|
127
|
+
queries_.clear();
|
|
128
|
+
syncs_.clear();
|
|
129
|
+
default_vertex_array_ = WebGLVertexArray();
|
|
130
|
+
for (WebGLAttribState &attrib : attribs_) attrib = WebGLAttribState();
|
|
131
|
+
current_program_ = 0;
|
|
132
|
+
bound_array_ = 0;
|
|
133
|
+
bound_element_ = 0;
|
|
134
|
+
bound_framebuffer_ = 0;
|
|
135
|
+
read_framebuffer_ = 0;
|
|
136
|
+
bound_renderbuffer_ = 0;
|
|
137
|
+
bound_vertex_array_ = 0;
|
|
138
|
+
copy_read_buffer_ = 0;
|
|
139
|
+
copy_write_buffer_ = 0;
|
|
140
|
+
active_unit_ = 0;
|
|
141
|
+
for (uint32_t &texture : bound_textures_) texture = 0;
|
|
142
|
+
for (uint32_t &texture : bound_cube_textures_) texture = 0;
|
|
143
|
+
for (uint32_t &texture : bound_array_textures_) texture = 0;
|
|
144
|
+
for (uint32_t &texture : bound_3d_textures_) texture = 0;
|
|
145
|
+
for (int &target : active_texture_target_) target = GL_TEXTURE_2D;
|
|
146
|
+
for (uint32_t &sampler : bound_samplers_) sampler = 0;
|
|
147
|
+
state_ = WebGLDrawState();
|
|
148
|
+
scissor_test_ = false;
|
|
149
|
+
error_ = 0;
|
|
150
|
+
lost_ = true;
|
|
151
|
+
clear_program_ = 0;
|
|
152
|
+
clear_buffer_ = 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
void WebGLContext::restore_context() {
|
|
156
|
+
if (!lost_) return;
|
|
157
|
+
if (guidev::g_device == nullptr) return;
|
|
158
|
+
lost_ = false;
|
|
159
|
+
error_ = 0;
|
|
160
|
+
ensure_default_target();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
void WebGLContext::drawing_buffer_storage(int width, int height) {
|
|
164
|
+
if (width <= 0 || height <= 0) {
|
|
165
|
+
set_error(GL_INVALID_VALUE);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
fixed_storage_ = true;
|
|
169
|
+
if (width == width_ && height == height_) return;
|
|
170
|
+
width_ = width;
|
|
171
|
+
height_ = height;
|
|
172
|
+
rebuild_default_target();
|
|
81
173
|
}
|
|
82
174
|
|
|
83
175
|
/* -- targets ------------------------------------------------------------- */
|
|
@@ -105,7 +197,7 @@ void WebGLContext::ensure_default_target() {
|
|
|
105
197
|
info.num_levels = 1;
|
|
106
198
|
info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
|
107
199
|
if (color_ == nullptr) color_ = SDL_CreateGPUTexture(guidev::g_device, &info);
|
|
108
|
-
info.format =
|
|
200
|
+
info.format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT;
|
|
109
201
|
info.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
|
|
110
202
|
if (depth_ == nullptr) depth_ = SDL_CreateGPUTexture(guidev::g_device, &info);
|
|
111
203
|
}
|
|
@@ -129,11 +221,15 @@ void WebGLContext::rebuild_default_target() {
|
|
|
129
221
|
}
|
|
130
222
|
|
|
131
223
|
SDL_GPUTexture *WebGLContext::color_texture() {
|
|
224
|
+
if (lost_) return nullptr;
|
|
132
225
|
ensure_default_target();
|
|
133
226
|
return color_;
|
|
134
227
|
}
|
|
135
228
|
|
|
136
229
|
void WebGLContext::resize(int width, int height) {
|
|
230
|
+
/* After `drawingBufferStorage` the drawing buffer has an explicit size and a
|
|
231
|
+
* canvas resize no longer changes it (WebGL 2). */
|
|
232
|
+
if (fixed_storage_) return;
|
|
137
233
|
if (width < 0) width = 0;
|
|
138
234
|
if (height < 0) height = 0;
|
|
139
235
|
width_ = width > 0 ? width : 1;
|
|
@@ -165,12 +261,34 @@ SDL_GPUTexture *WebGLContext::target_color() {
|
|
|
165
261
|
return color_;
|
|
166
262
|
}
|
|
167
263
|
WebGLFramebuffer *framebuffer = this->framebuffer(bound_framebuffer_);
|
|
168
|
-
if (framebuffer == nullptr || framebuffer->
|
|
169
|
-
WebGLTexture *texture = this->texture(framebuffer->
|
|
264
|
+
if (framebuffer == nullptr || framebuffer->color_textures[0] == 0) return nullptr;
|
|
265
|
+
WebGLTexture *texture = this->texture(framebuffer->color_textures[0]);
|
|
170
266
|
if (texture == nullptr) return nullptr;
|
|
171
267
|
return ensure_texture_gpu(texture, true);
|
|
172
268
|
}
|
|
173
269
|
|
|
270
|
+
SDL_GPUTexture *WebGLContext::framebuffer_color(uint32_t id) {
|
|
271
|
+
if (id == 0) {
|
|
272
|
+
ensure_default_target();
|
|
273
|
+
return color_;
|
|
274
|
+
}
|
|
275
|
+
WebGLFramebuffer *framebuffer_ = framebuffer(id);
|
|
276
|
+
if (framebuffer_ == nullptr || framebuffer_->color_textures[0] == 0) return nullptr;
|
|
277
|
+
WebGLTexture *texture_ = texture(framebuffer_->color_textures[0]);
|
|
278
|
+
return texture_ != nullptr ? ensure_texture_gpu(texture_, true) : nullptr;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
void WebGLContext::framebuffer_size(uint32_t id, int *width, int *height) {
|
|
282
|
+
if (id == 0) {
|
|
283
|
+
*width = width_;
|
|
284
|
+
*height = height_;
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
WebGLFramebuffer *framebuffer_ = framebuffer(id);
|
|
288
|
+
*width = framebuffer_ != nullptr ? framebuffer_->width : 0;
|
|
289
|
+
*height = framebuffer_ != nullptr ? framebuffer_->height : 0;
|
|
290
|
+
}
|
|
291
|
+
|
|
174
292
|
SDL_GPUTexture *WebGLContext::target_depth() {
|
|
175
293
|
if (bound_framebuffer_ == 0) {
|
|
176
294
|
ensure_default_target();
|
|
@@ -178,12 +296,18 @@ SDL_GPUTexture *WebGLContext::target_depth() {
|
|
|
178
296
|
}
|
|
179
297
|
WebGLFramebuffer *framebuffer = this->framebuffer(bound_framebuffer_);
|
|
180
298
|
if (framebuffer == nullptr) return nullptr;
|
|
299
|
+
if (framebuffer->depth_texture != 0) {
|
|
300
|
+
WebGLTexture *texture = this->texture(framebuffer->depth_texture);
|
|
301
|
+
if (texture == nullptr) return nullptr;
|
|
302
|
+
texture->as_depth_target = true;
|
|
303
|
+
return ensure_texture_gpu(texture, true);
|
|
304
|
+
}
|
|
181
305
|
if (framebuffer->depth == nullptr && framebuffer->depth_renderbuffer == 0 &&
|
|
182
306
|
framebuffer->width > 0 && framebuffer->height > 0 && guidev::g_device != nullptr) {
|
|
183
307
|
SDL_GPUTextureCreateInfo info;
|
|
184
308
|
memset(&info, 0, sizeof(info));
|
|
185
309
|
info.type = SDL_GPU_TEXTURETYPE_2D;
|
|
186
|
-
info.format =
|
|
310
|
+
info.format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT;
|
|
187
311
|
info.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
|
|
188
312
|
info.width = (Uint32)framebuffer->width;
|
|
189
313
|
info.height = (Uint32)framebuffer->height;
|
|
@@ -195,6 +319,27 @@ SDL_GPUTexture *WebGLContext::target_depth() {
|
|
|
195
319
|
return framebuffer->depth;
|
|
196
320
|
}
|
|
197
321
|
|
|
322
|
+
int WebGLContext::target_color_format() {
|
|
323
|
+
if (bound_framebuffer_ == 0) return SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
|
324
|
+
WebGLFramebuffer *framebuffer = this->framebuffer(bound_framebuffer_);
|
|
325
|
+
if (framebuffer == nullptr || framebuffer->color_textures[0] == 0) {
|
|
326
|
+
return SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
|
327
|
+
}
|
|
328
|
+
WebGLTexture *texture = this->texture(framebuffer->color_textures[0]);
|
|
329
|
+
return texture != nullptr ? (int)texture->format : SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
int WebGLContext::target_depth_format() {
|
|
333
|
+
if (bound_framebuffer_ == 0) return SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT;
|
|
334
|
+
WebGLFramebuffer *framebuffer = this->framebuffer(bound_framebuffer_);
|
|
335
|
+
if (framebuffer == nullptr) return SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT;
|
|
336
|
+
if (framebuffer->depth_texture != 0) {
|
|
337
|
+
WebGLTexture *texture = this->texture(framebuffer->depth_texture);
|
|
338
|
+
if (texture != nullptr) return (int)texture->format;
|
|
339
|
+
}
|
|
340
|
+
return SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT;
|
|
341
|
+
}
|
|
342
|
+
|
|
198
343
|
void WebGLContext::end_pass() {
|
|
199
344
|
if (pass_ != nullptr && cmd_ != nullptr) {
|
|
200
345
|
SDL_EndGPURenderPass(pass_);
|
|
@@ -202,30 +347,37 @@ void WebGLContext::end_pass() {
|
|
|
202
347
|
}
|
|
203
348
|
}
|
|
204
349
|
|
|
205
|
-
void WebGLContext::begin_pass(bool clear_color, bool clear_depth) {
|
|
350
|
+
void WebGLContext::begin_pass(bool clear_color, bool clear_depth, bool clear_stencil) {
|
|
206
351
|
if (guidev::g_device == nullptr) return;
|
|
207
352
|
if (pass_ != nullptr && pass_targets_default_ == (bound_framebuffer_ == 0) &&
|
|
208
|
-
pass_framebuffer_ == bound_framebuffer_ && !clear_color && !clear_depth
|
|
353
|
+
pass_framebuffer_ == bound_framebuffer_ && !clear_color && !clear_depth &&
|
|
354
|
+
!clear_stencil) {
|
|
209
355
|
return;
|
|
210
356
|
}
|
|
211
357
|
end_pass();
|
|
212
358
|
ensure_command();
|
|
213
359
|
if (cmd_ == nullptr) return;
|
|
214
|
-
SDL_GPUTexture *color = target_color();
|
|
215
360
|
SDL_GPUTexture *depth = target_depth();
|
|
216
|
-
|
|
361
|
+
SDL_GPUColorTargetInfo color_infos[kWebGLMaxDrawBuffers];
|
|
362
|
+
int color_count = 0;
|
|
363
|
+
for (int slot = 0; slot < kWebGLMaxDrawBuffers; slot++) {
|
|
364
|
+
SDL_GPUTexture *color = draw_color_texture(slot);
|
|
365
|
+
if (color == nullptr) continue;
|
|
366
|
+
SDL_GPUColorTargetInfo &color_info = color_infos[color_count++];
|
|
367
|
+
memset(&color_info, 0, sizeof(color_info));
|
|
368
|
+
color_info.texture = color;
|
|
369
|
+
color_info.layer_or_depth_plane = (Uint32)draw_color_layer(slot);
|
|
370
|
+
color_info.clear_color.r = clear_color_[0];
|
|
371
|
+
color_info.clear_color.g = clear_color_[1];
|
|
372
|
+
color_info.clear_color.b = clear_color_[2];
|
|
373
|
+
color_info.clear_color.a = clear_color_[3];
|
|
374
|
+
color_info.load_op = clear_color ? SDL_GPU_LOADOP_CLEAR : SDL_GPU_LOADOP_LOAD;
|
|
375
|
+
color_info.store_op = SDL_GPU_STOREOP_STORE;
|
|
376
|
+
}
|
|
377
|
+
if (color_count == 0) {
|
|
217
378
|
set_error(GL_INVALID_FRAMEBUFFER_OPERATION);
|
|
218
379
|
return;
|
|
219
380
|
}
|
|
220
|
-
SDL_GPUColorTargetInfo color_info;
|
|
221
|
-
memset(&color_info, 0, sizeof(color_info));
|
|
222
|
-
color_info.texture = color;
|
|
223
|
-
color_info.clear_color.r = clear_color_[0];
|
|
224
|
-
color_info.clear_color.g = clear_color_[1];
|
|
225
|
-
color_info.clear_color.b = clear_color_[2];
|
|
226
|
-
color_info.clear_color.a = clear_color_[3];
|
|
227
|
-
color_info.load_op = clear_color ? SDL_GPU_LOADOP_CLEAR : SDL_GPU_LOADOP_LOAD;
|
|
228
|
-
color_info.store_op = SDL_GPU_STOREOP_STORE;
|
|
229
381
|
|
|
230
382
|
SDL_GPUDepthStencilTargetInfo depth_info;
|
|
231
383
|
memset(&depth_info, 0, sizeof(depth_info));
|
|
@@ -234,111 +386,17 @@ void WebGLContext::begin_pass(bool clear_color, bool clear_depth) {
|
|
|
234
386
|
depth_info.load_op = (clear_depth && depth != nullptr) ? SDL_GPU_LOADOP_CLEAR
|
|
235
387
|
: SDL_GPU_LOADOP_LOAD;
|
|
236
388
|
depth_info.store_op = SDL_GPU_STOREOP_STORE;
|
|
237
|
-
depth_info.
|
|
238
|
-
depth_info.
|
|
389
|
+
depth_info.clear_stencil = (Uint8)(clear_stencil_ & 0xFF);
|
|
390
|
+
depth_info.stencil_load_op = (clear_stencil && depth != nullptr) ? SDL_GPU_LOADOP_CLEAR
|
|
391
|
+
: SDL_GPU_LOADOP_LOAD;
|
|
392
|
+
depth_info.stencil_store_op = SDL_GPU_STOREOP_STORE;
|
|
239
393
|
|
|
240
|
-
pass_ = SDL_BeginGPURenderPass(cmd_,
|
|
394
|
+
pass_ = SDL_BeginGPURenderPass(cmd_, color_infos, (Uint32)color_count,
|
|
395
|
+
depth != nullptr ? &depth_info : nullptr);
|
|
241
396
|
pass_targets_default_ = bound_framebuffer_ == 0;
|
|
242
397
|
pass_framebuffer_ = bound_framebuffer_;
|
|
243
398
|
}
|
|
244
399
|
|
|
245
|
-
/* -- state --------------------------------------------------------------- */
|
|
246
|
-
|
|
247
|
-
void WebGLContext::enable(int cap) {
|
|
248
|
-
if (cap == GL_BLEND) state_.blend = true;
|
|
249
|
-
if (cap == GL_DEPTH_TEST) state_.depth_test = true;
|
|
250
|
-
if (cap == GL_CULL_FACE) state_.cull = true;
|
|
251
|
-
if (cap == GL_SCISSOR_TEST) scissor_test_ = true;
|
|
252
|
-
if (cap == GL_STENCIL_TEST) stencil_test_ = true;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
void WebGLContext::disable(int cap) {
|
|
256
|
-
if (cap == GL_BLEND) state_.blend = false;
|
|
257
|
-
if (cap == GL_DEPTH_TEST) state_.depth_test = false;
|
|
258
|
-
if (cap == GL_CULL_FACE) state_.cull = false;
|
|
259
|
-
if (cap == GL_SCISSOR_TEST) scissor_test_ = false;
|
|
260
|
-
if (cap == GL_STENCIL_TEST) stencil_test_ = false;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
bool WebGLContext::is_enabled(int cap) const {
|
|
264
|
-
if (cap == GL_BLEND) return state_.blend;
|
|
265
|
-
if (cap == GL_DEPTH_TEST) return state_.depth_test;
|
|
266
|
-
if (cap == GL_CULL_FACE) return state_.cull;
|
|
267
|
-
if (cap == GL_SCISSOR_TEST) return scissor_test_;
|
|
268
|
-
if (cap == GL_STENCIL_TEST) return stencil_test_;
|
|
269
|
-
return false;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
void WebGLContext::clear_color(float r, float g, float b, float a) {
|
|
273
|
-
clear_color_[0] = r;
|
|
274
|
-
clear_color_[1] = g;
|
|
275
|
-
clear_color_[2] = b;
|
|
276
|
-
clear_color_[3] = a;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
void WebGLContext::color_mask(bool r, bool g, bool b, bool a) {
|
|
280
|
-
state_.color_mask[0] = r;
|
|
281
|
-
state_.color_mask[1] = g;
|
|
282
|
-
state_.color_mask[2] = b;
|
|
283
|
-
state_.color_mask[3] = a;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
void WebGLContext::blend_func(int src, int dst) {
|
|
287
|
-
state_.blend_src_rgb = src;
|
|
288
|
-
state_.blend_dst_rgb = dst;
|
|
289
|
-
state_.blend_src_alpha = src;
|
|
290
|
-
state_.blend_dst_alpha = dst;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
void WebGLContext::blend_func_separate(int src_rgb, int dst_rgb, int src_alpha, int dst_alpha) {
|
|
294
|
-
state_.blend_src_rgb = src_rgb;
|
|
295
|
-
state_.blend_dst_rgb = dst_rgb;
|
|
296
|
-
state_.blend_src_alpha = src_alpha;
|
|
297
|
-
state_.blend_dst_alpha = dst_alpha;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
void WebGLContext::blend_equation(int mode) {
|
|
301
|
-
state_.blend_eq_rgb = mode;
|
|
302
|
-
state_.blend_eq_alpha = mode;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
void WebGLContext::blend_equation_separate(int rgb, int alpha) {
|
|
306
|
-
state_.blend_eq_rgb = rgb;
|
|
307
|
-
state_.blend_eq_alpha = alpha;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
void WebGLContext::cull_face(int mode) { state_.cull_face = mode; }
|
|
311
|
-
|
|
312
|
-
void WebGLContext::front_face(int mode) { state_.front_face = mode; }
|
|
313
|
-
|
|
314
|
-
void WebGLContext::viewport(int x, int y, int w, int h) {
|
|
315
|
-
viewport_[0] = x;
|
|
316
|
-
viewport_[1] = y;
|
|
317
|
-
viewport_[2] = w;
|
|
318
|
-
viewport_[3] = h;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
void WebGLContext::scissor(int x, int y, int w, int h) {
|
|
322
|
-
scissor_box_[0] = x;
|
|
323
|
-
scissor_box_[1] = y;
|
|
324
|
-
scissor_box_[2] = w;
|
|
325
|
-
scissor_box_[3] = h;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
void WebGLContext::clear(int mask) {
|
|
329
|
-
if (guidev::g_device == nullptr) return;
|
|
330
|
-
const bool color_bit = (mask & GL_COLOR_BUFFER_BIT) != 0;
|
|
331
|
-
const bool depth_bit = (mask & GL_DEPTH_BUFFER_BIT) != 0;
|
|
332
|
-
/* The scissor rectangle is not honoured by a pass-begin clear; WebGL pages
|
|
333
|
-
* that clear a sub-rectangle are rare and documented as a limitation. */
|
|
334
|
-
begin_pass(color_bit, depth_bit);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
void WebGLContext::finish() {
|
|
338
|
-
submit();
|
|
339
|
-
if (guidev::g_device != nullptr) SDL_WaitForGPUIdle(guidev::g_device);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
400
|
/* -- queries ------------------------------------------------------------- */
|
|
343
401
|
|
|
344
402
|
double WebGLContext::parameter(int pname) {
|
|
@@ -352,7 +410,9 @@ double WebGLContext::parameter(int pname) {
|
|
|
352
410
|
case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
|
|
353
411
|
return kWebGLMaxTextureUnits * 2;
|
|
354
412
|
case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
|
|
355
|
-
|
|
413
|
+
/* The vertex stage binds its own sampler set (`SDL_BindGPUVertexSamplers`)
|
|
414
|
+
* and the translator emits vertex samplers in descriptor set 0. */
|
|
415
|
+
return kWebGLMaxTextureUnits;
|
|
356
416
|
case GL_MAX_VERTEX_UNIFORM_VECTORS:
|
|
357
417
|
case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
|
|
358
418
|
case GL_MAX_VARYING_VECTORS:
|
|
@@ -362,7 +422,7 @@ double WebGLContext::parameter(int pname) {
|
|
|
362
422
|
case GL_MAX_VIEWPORT_DIMS:
|
|
363
423
|
return 8192;
|
|
364
424
|
case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
|
|
365
|
-
return
|
|
425
|
+
return 8192;
|
|
366
426
|
case GL_SAMPLES:
|
|
367
427
|
case GL_SAMPLE_BUFFERS:
|
|
368
428
|
return 0;
|
|
@@ -375,7 +435,7 @@ double WebGLContext::parameter(int pname) {
|
|
|
375
435
|
case GL_DEPTH_BITS:
|
|
376
436
|
return 8;
|
|
377
437
|
case GL_STENCIL_BITS:
|
|
378
|
-
return
|
|
438
|
+
return 8;
|
|
379
439
|
case GL_UNPACK_ALIGNMENT:
|
|
380
440
|
case GL_PACK_ALIGNMENT:
|
|
381
441
|
return 4;
|
|
@@ -394,13 +454,23 @@ double WebGLContext::parameter(int pname) {
|
|
|
394
454
|
return 256;
|
|
395
455
|
case GL_MAX_DRAW_BUFFERS:
|
|
396
456
|
case GL_MAX_COLOR_ATTACHMENTS:
|
|
397
|
-
return
|
|
457
|
+
return kWebGLMaxDrawBuffers;
|
|
458
|
+
case GL_READ_BUFFER:
|
|
459
|
+
return read_buffer_;
|
|
460
|
+
case GL_DRAW_BUFFER0:
|
|
461
|
+
return draw_buffer_value(0);
|
|
462
|
+
case GL_DRAW_BUFFER1:
|
|
463
|
+
return draw_buffer_value(1);
|
|
464
|
+
case GL_DRAW_BUFFER2:
|
|
465
|
+
return draw_buffer_value(2);
|
|
466
|
+
case GL_DRAW_BUFFER3:
|
|
467
|
+
return draw_buffer_value(3);
|
|
398
468
|
case GL_MAX_SAMPLES:
|
|
399
469
|
return 0;
|
|
400
470
|
case GL_MAX_UNIFORM_BUFFER_BINDINGS:
|
|
401
471
|
case GL_MAX_VERTEX_UNIFORM_BLOCKS:
|
|
402
472
|
case GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
|
|
403
|
-
return
|
|
473
|
+
return 16;
|
|
404
474
|
case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
|
|
405
475
|
return 256;
|
|
406
476
|
case GL_MAX_ELEMENT_INDEX:
|
|
@@ -417,11 +487,7 @@ double WebGLContext::parameter(int pname) {
|
|
|
417
487
|
case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
|
|
418
488
|
case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
|
|
419
489
|
return 1024;
|
|
420
|
-
|
|
421
|
-
return 16384;
|
|
422
|
-
case GL_READ_BUFFER:
|
|
423
|
-
case GL_DRAW_BUFFER0:
|
|
424
|
-
return GL_BACK;
|
|
490
|
+
|
|
425
491
|
default:
|
|
426
492
|
return 0;
|
|
427
493
|
}
|
|
@@ -452,9 +518,28 @@ uint32_t WebGLContext::bound_buffer(int target) const { return buffer_for_target
|
|
|
452
518
|
|
|
453
519
|
uint32_t WebGLContext::bound_texture(int unit) const {
|
|
454
520
|
if (unit < 0 || unit >= kWebGLMaxTextureUnits) return 0;
|
|
521
|
+
const int target = active_texture_target_[unit];
|
|
522
|
+
if (target == GL_TEXTURE_CUBE_MAP) return bound_cube_textures_[unit];
|
|
523
|
+
if (target == GL_TEXTURE_2D_ARRAY) return bound_array_textures_[unit];
|
|
524
|
+
if (target == GL_TEXTURE_3D) return bound_3d_textures_[unit];
|
|
455
525
|
return bound_textures_[unit];
|
|
456
526
|
}
|
|
457
527
|
|
|
528
|
+
uint32_t WebGLContext::bound_cube_texture(int unit) const {
|
|
529
|
+
if (unit < 0 || unit >= kWebGLMaxTextureUnits) return 0;
|
|
530
|
+
return bound_cube_textures_[unit];
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
uint32_t WebGLContext::bound_array_texture(int unit) const {
|
|
534
|
+
if (unit < 0 || unit >= kWebGLMaxTextureUnits) return 0;
|
|
535
|
+
return bound_array_textures_[unit];
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
uint32_t WebGLContext::bound_3d_texture(int unit) const {
|
|
539
|
+
if (unit < 0 || unit >= kWebGLMaxTextureUnits) return 0;
|
|
540
|
+
return bound_3d_textures_[unit];
|
|
541
|
+
}
|
|
542
|
+
|
|
458
543
|
void WebGLContext::viewport_box(int out[4]) const {
|
|
459
544
|
for (int i = 0; i < 4; i++) out[i] = viewport_[i];
|
|
460
545
|
}
|
|
@@ -144,6 +144,11 @@ std::string pipeline_key(int mode, int index_size,
|
|
|
144
144
|
const std::vector<SDL_GPUVertexBufferDescription> &buffers,
|
|
145
145
|
const WebGLDrawState &state) {
|
|
146
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);
|
|
147
152
|
for (const SDL_GPUVertexAttribute &attr : attrs) {
|
|
148
153
|
key += "/" + std::to_string(attr.location) + ":" + std::to_string(attr.buffer_slot) + ":" +
|
|
149
154
|
std::to_string((int)attr.format) + ":" + std::to_string(attr.offset);
|
|
@@ -152,7 +157,7 @@ std::string pipeline_key(int mode, int index_size,
|
|
|
152
157
|
key += "|" + std::to_string(buffer.slot) + ":" + std::to_string(buffer.pitch) + ":" +
|
|
153
158
|
std::to_string((int)buffer.input_rate);
|
|
154
159
|
}
|
|
155
|
-
char state_key[
|
|
160
|
+
char state_key[256];
|
|
156
161
|
snprintf(state_key, sizeof(state_key), "|%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
|
157
162
|
(int)state.blend, state.blend_src_rgb, state.blend_dst_rgb, state.blend_src_alpha,
|
|
158
163
|
state.blend_dst_alpha, state.blend_eq_rgb, state.blend_eq_alpha, (int)state.depth_test,
|
|
@@ -162,6 +167,16 @@ std::string pipeline_key(int mode, int index_size,
|
|
|
162
167
|
key += std::to_string((int)state.color_mask[1]);
|
|
163
168
|
key += std::to_string((int)state.color_mask[2]);
|
|
164
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;
|
|
165
180
|
return key;
|
|
166
181
|
}
|
|
167
182
|
|
|
@@ -308,6 +323,15 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
308
323
|
bound_framebuffer_ != 0 ? framebuffer(bound_framebuffer_) : nullptr;
|
|
309
324
|
const int target_width = framebuffer_ != nullptr ? framebuffer_->width : width_;
|
|
310
325
|
const int target_height = framebuffer_ != nullptr ? framebuffer_->height : height_;
|
|
326
|
+
/* A pipeline bakes in the attachment formats; float colour targets, MRT
|
|
327
|
+
* layouts and depth textures therefore need their own pipeline variants. */
|
|
328
|
+
state_.color_target_count = 0;
|
|
329
|
+
for (int slot = 0; slot < kWebGLMaxDrawBuffers; slot++) {
|
|
330
|
+
if (draw_color_texture(slot) == nullptr) continue;
|
|
331
|
+
state_.color_formats[state_.color_target_count++] = draw_color_format(slot);
|
|
332
|
+
}
|
|
333
|
+
if (state_.color_target_count == 0) state_.color_target_count = 1;
|
|
334
|
+
state_.depth_format = target_depth_format();
|
|
311
335
|
|
|
312
336
|
std::vector<SDL_GPUVertexAttribute> attributes;
|
|
313
337
|
std::vector<SDL_GPUVertexBufferDescription> buffers;
|
|
@@ -381,7 +405,7 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
381
405
|
bindings.push_back(binding);
|
|
382
406
|
}
|
|
383
407
|
|
|
384
|
-
begin_pass(false, false);
|
|
408
|
+
begin_pass(false, false, false);
|
|
385
409
|
if (pass_ == nullptr) return;
|
|
386
410
|
|
|
387
411
|
SDL_GPUViewport viewport;
|
|
@@ -431,6 +455,17 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
431
455
|
if (pipeline == nullptr) return;
|
|
432
456
|
|
|
433
457
|
SDL_BindGPUGraphicsPipeline(pass_, pipeline);
|
|
458
|
+
if (state_.stencil) {
|
|
459
|
+
SDL_SetGPUStencilReference(pass_, (Uint8)(stencil_reference() & 0xFF));
|
|
460
|
+
}
|
|
461
|
+
if (state_.blend) {
|
|
462
|
+
SDL_FColor constants;
|
|
463
|
+
constants.r = blend_color_[0];
|
|
464
|
+
constants.g = blend_color_[1];
|
|
465
|
+
constants.b = blend_color_[2];
|
|
466
|
+
constants.a = blend_color_[3];
|
|
467
|
+
SDL_SetGPUBlendConstants(pass_, constants);
|
|
468
|
+
}
|
|
434
469
|
if (!bindings.empty()) {
|
|
435
470
|
SDL_BindGPUVertexBuffers(pass_, 0, bindings.data(), (Uint32)bindings.size());
|
|
436
471
|
}
|
|
@@ -442,6 +477,28 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
442
477
|
index_size == 4 ? SDL_GPU_INDEXELEMENTSIZE_32BIT
|
|
443
478
|
: SDL_GPU_INDEXELEMENTSIZE_16BIT);
|
|
444
479
|
}
|
|
480
|
+
/* User uniform blocks live in the same std140 block; refresh their members
|
|
481
|
+
* from the CPU-side buffer bound to each block's binding point. */
|
|
482
|
+
for (const WebGLUniformBlock &block : program_->blocks) {
|
|
483
|
+
if (block.binding < 0 || block.binding >= 16) continue;
|
|
484
|
+
const WebGLUniformBinding &binding = uniform_bindings_[block.binding];
|
|
485
|
+
if (binding.buffer == 0) continue;
|
|
486
|
+
WebGLBuffer *uniform_buffer = buffer(binding.buffer);
|
|
487
|
+
if (uniform_buffer == nullptr) continue;
|
|
488
|
+
size_t offset = binding.offset;
|
|
489
|
+
size_t length = (size_t)block.data_size;
|
|
490
|
+
if (binding.size > 0 && length > binding.size) length = binding.size;
|
|
491
|
+
if (offset > uniform_buffer->data.size()) continue;
|
|
492
|
+
if (length > uniform_buffer->data.size() - offset) {
|
|
493
|
+
length = uniform_buffer->data.size() - offset;
|
|
494
|
+
}
|
|
495
|
+
if (block.base_offset >= 0 &&
|
|
496
|
+
block.base_offset + (int)length <= program_->block_size) {
|
|
497
|
+
memcpy(program_->block.data() + block.base_offset,
|
|
498
|
+
uniform_buffer->data.data() + offset, length);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
445
502
|
if (program_->vs_has_block && program_->block_size > 0) {
|
|
446
503
|
SDL_PushGPUVertexUniformData(cmd_, 0, program_->block.data(), (Uint32)program_->block.size());
|
|
447
504
|
}
|
|
@@ -457,7 +514,15 @@ void WebGLContext::draw(int mode, int first, int count, int index_type, int offs
|
|
|
457
514
|
const WebGLUniform &uniform = program_->uniforms[(size_t)uniform_index];
|
|
458
515
|
const int unit =
|
|
459
516
|
uniform.unit >= 0 && uniform.unit < kWebGLMaxTextureUnits ? uniform.unit : 0;
|
|
460
|
-
|
|
517
|
+
uint32_t texture_id = bound_textures_[unit];
|
|
518
|
+
if (uniform.layout.gl_type == GL_SAMPLER_CUBE) {
|
|
519
|
+
texture_id = bound_cube_textures_[unit];
|
|
520
|
+
} else if (uniform.layout.gl_type == GL_SAMPLER_3D) {
|
|
521
|
+
texture_id = bound_3d_textures_[unit];
|
|
522
|
+
} else if (uniform.layout.gl_type == GL_SAMPLER_2D_ARRAY) {
|
|
523
|
+
texture_id = bound_array_textures_[unit];
|
|
524
|
+
}
|
|
525
|
+
WebGLTexture *sampled = texture(texture_id);
|
|
461
526
|
SDL_GPUTexture *gpu = sampled != nullptr ? ensure_texture_gpu(sampled, sampled->as_target)
|
|
462
527
|
: nullptr;
|
|
463
528
|
WebGLSampler *sampler_object = this->sampler(bound_samplers_[unit]);
|