Skip to content

Commit 5dd0e27

Browse files
committed
[WebGPU] Fix async render-target loss and buffer re-locking
Render into a separate texture to avoid loosing the framebuffer after an async wait and do not pre-lock buffers because it seems like they can't be locked again afterwards.
1 parent 08a309e commit 5dd0e27

3 files changed

Lines changed: 73 additions & 3 deletions

File tree

backends/gpu/webgpu/includes/kore3/webgpu/commandlist_structs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ typedef struct kore_webgpu_command_list {
3737
WGPUComputePipeline compute_pipeline;
3838
kore_webgpu_compute_bind_group compute_bind_groups[16];
3939
uint32_t compute_bind_groups_count;
40+
41+
bool present;
4042
} kore_webgpu_command_list;
4143

4244
#ifdef __cplusplus

backends/gpu/webgpu/sources/commandlist.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ void kore_webgpu_command_list_end_render_pass(kore_gpu_command_list *list) {
135135
list->webgpu.render_pass_encoder = NULL;
136136
}
137137

138-
void kore_webgpu_command_list_present(kore_gpu_command_list *list) {}
138+
void kore_webgpu_command_list_present(kore_gpu_command_list *list) {
139+
list->webgpu.present = true;
140+
}
139141

140142
void kore_webgpu_command_list_set_index_buffer(kore_gpu_command_list *list, kore_gpu_buffer *buffer, kore_gpu_index_format index_format, uint64_t offset) {
141143
kore_webgpu_buffer_schedule_uploads(&buffer->webgpu);

backends/gpu/webgpu/sources/device.c

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@
1616

1717
#include <assert.h>
1818

19+
#define FRAMEBUFFER_TEXTURE
20+
1921
static WGPUDevice wgpu_device;
2022
WGPUInstance wgpu_instance;
2123
static WGPUAdapter wgpu_adapter;
2224
static kore_gpu_texture_format framebuffer_format;
25+
#ifdef FRAMEBUFFER_TEXTURE
26+
static kore_gpu_texture framebuffer_texture;
27+
#endif
2328

2429
static void error_callback(WGPUDevice const *device, WGPUErrorType type, WGPUStringView message, void *userdata1, void *userdata2) {
2530
kore_log(KORE_LOG_LEVEL_ERROR, "%d: %s", type, message.data);
@@ -76,6 +81,20 @@ void kore_webgpu_device_create(kore_gpu_device *device, const kore_gpu_device_wi
7681
.presentMode = WGPUPresentMode_Fifo,
7782
};
7883
wgpuSurfaceConfigure(device->webgpu.surface, &surface_configuration);
84+
85+
#ifdef FRAMEBUFFER_TEXTURE
86+
kore_gpu_texture_parameters texture_parameters = {
87+
.format = framebuffer_format,
88+
.width = kore_window_width(0),
89+
.height = kore_window_height(0),
90+
.dimension = KORE_GPU_TEXTURE_DIMENSION_2D,
91+
.mip_level_count = 1,
92+
.depth_or_array_layers = 1,
93+
.sample_count = 1,
94+
.usage = KORE_GPU_TEXTURE_USAGE_RENDER_ATTACHMENT | KORE_GPU_TEXTURE_USAGE_COPY_SRC | KORE_GPU_TEXTURE_USAGE_COPY_DST,
95+
};
96+
kore_gpu_device_create_texture(device, &texture_parameters, &framebuffer_texture);
97+
#endif
7998
}
8099

81100
void kore_webgpu_device_destroy(kore_gpu_device *device) {}
@@ -141,7 +160,7 @@ void kore_webgpu_device_create_buffer(kore_gpu_device *device, const kore_gpu_bu
141160
WGPUBufferDescriptor buffer_descriptor = {
142161
.size = align_pow2(parameters->size, 4),
143162
.usage = WGPUBufferUsage_MapWrite | WGPUBufferUsage_CopySrc,
144-
.mappedAtCreation = true,
163+
.mappedAtCreation = false,
145164
};
146165

147166
buffer->webgpu.copy_buffer = wgpuDeviceCreateBuffer(device->webgpu.device, &buffer_descriptor);
@@ -156,7 +175,7 @@ void kore_webgpu_device_create_buffer(kore_gpu_device *device, const kore_gpu_bu
156175
WGPUBufferDescriptor buffer_descriptor = {
157176
.size = align_pow2(parameters->size, 4),
158177
.usage = convert_buffer_usage(usage),
159-
.mappedAtCreation = ((parameters->usage_flags & KORE_GPU_BUFFER_USAGE_CPU_WRITE) != 0) && !buffer->webgpu.has_copy_buffer,
178+
.mappedAtCreation = false,
160179
};
161180

162181
buffer->webgpu.buffer = wgpuDeviceCreateBuffer(device->webgpu.device, &buffer_descriptor);
@@ -199,6 +218,8 @@ void kore_webgpu_device_create_command_list(kore_gpu_device *device, kore_gpu_co
199218
list->webgpu.root_constants_offset = 0;
200219

201220
list->webgpu.compute_pipeline = NULL;
221+
222+
list->webgpu.present = false;
202223
}
203224

204225
void kore_webgpu_device_create_texture(kore_gpu_device *device, const kore_gpu_texture_parameters *parameters, kore_gpu_texture *texture) {
@@ -247,6 +268,9 @@ void kore_webgpu_device_create_texture(kore_gpu_device *device, const kore_gpu_t
247268
static kore_gpu_texture framebuffer;
248269

249270
kore_gpu_texture *kore_webgpu_device_get_framebuffer(kore_gpu_device *device) {
271+
#ifdef FRAMEBUFFER_TEXTURE
272+
return &framebuffer_texture;
273+
#else
250274
WGPUSurfaceTexture surface_texture;
251275
wgpuSurfaceGetCurrentTexture(device->webgpu.surface, &surface_texture);
252276
framebuffer.webgpu.texture = surface_texture.texture;
@@ -256,6 +280,7 @@ kore_gpu_texture *kore_webgpu_device_get_framebuffer(kore_gpu_device *device) {
256280
framebuffer.height = kore_window_height(0);
257281

258282
return &framebuffer;
283+
#endif
259284
}
260285

261286
kore_gpu_texture_format kore_webgpu_device_framebuffer_format(kore_gpu_device *device) {
@@ -294,12 +319,53 @@ void kore_webgpu_device_execute_command_list(kore_gpu_device *device, kore_gpu_c
294319
scheduled_buffer_uploads_count = 0;
295320
}
296321

322+
#ifdef FRAMEBUFFER_TEXTURE
323+
if (list->webgpu.present) {
324+
WGPUTexelCopyTextureInfo source_texture = {
325+
.texture = framebuffer_texture.webgpu.texture,
326+
.mipLevel = 0,
327+
.origin =
328+
{
329+
.x = 0,
330+
.y = 0,
331+
.z = 0,
332+
},
333+
.aspect = WGPUTextureAspect_All,
334+
};
335+
336+
WGPUSurfaceTexture surface_texture;
337+
wgpuSurfaceGetCurrentTexture(device->webgpu.surface, &surface_texture);
338+
339+
WGPUTexelCopyTextureInfo destination_texture = {
340+
.texture = surface_texture.texture,
341+
.mipLevel = 0,
342+
.origin =
343+
{
344+
.x = 0,
345+
.y = 0,
346+
.z = 0,
347+
},
348+
.aspect = WGPUTextureAspect_All,
349+
};
350+
351+
WGPUExtent3D size = {
352+
.width = framebuffer_texture.width,
353+
.height = framebuffer_texture.height,
354+
.depthOrArrayLayers = 1,
355+
};
356+
357+
wgpuCommandEncoderCopyTextureToTexture(list->webgpu.command_encoder, &source_texture, &destination_texture, &size);
358+
}
359+
#endif
360+
297361
WGPUCommandBufferDescriptor command_buffer_descriptor = {0};
298362
WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish(list->webgpu.command_encoder, &command_buffer_descriptor);
299363
wgpuQueueSubmit(device->webgpu.queue, 1, &command_buffer);
300364

301365
WGPUCommandEncoderDescriptor command_encoder_descriptor = {0};
302366
list->webgpu.command_encoder = wgpuDeviceCreateCommandEncoder(device->webgpu.device, &command_encoder_descriptor);
367+
368+
list->webgpu.present = false;
303369
}
304370

305371
static bool work_done = false;

0 commit comments

Comments
 (0)