Skip to content

Commit 58e6140

Browse files
committed
Refactor: Removed Emscripten specific Swapchain logic. Now I manually configure the surface. Elie Michel's surface configuration logic was added but the macros don't seem to want to work for me. I've added a temporary workaround since I am only testing Emscripten anyways.
1 parent c21747f commit 58e6140

File tree

3 files changed

+59
-63
lines changed

3 files changed

+59
-63
lines changed

src/gpu/webgpu/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SDL3 GPU WebGPU Backend
22
Status: Work In Progress
33

4-
Any general questions about this should probably be directed to kylelukaszek [at] gmail [dot] com since I wrote most of the base implementation.
4+
Author: Kyle Lukaszek
55

66
## Compiling with Emscripten
77
**Emscripten version 3.1.69+ is required to make use of SDL3 WebGPU.**

src/gpu/webgpu/SDL_WebGPU_Checklist.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ Getting my fork of the example suite merged with the original shouldn't be too m
88
The original example suite can be found at:
99
- https://github.com/TheSpydog/SDL_gpu_examples/
1010

11-
Currently, the WebGPU backend only supports Emscripten as the compilation target, though it should not be difficult to implement the code provided by @eliemichel.
12-
11+
Currently, the WebGPU backend only supports Emscripten as the compilation target, though I've added Elie Michel's cross-platform surface configuration logic to the backend. I have not tested it with any native implementations however.
1312

1413
# Checklist
1514

src/gpu/webgpu/SDL_gpu_webgpu.c

Lines changed: 57 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,10 @@
77

88
#include "../SDL_sysgpu.h"
99
#include "SDL_internal.h"
10-
#include "stdalign.h"
11-
#include <SDL3/SDL_events.h>
1210
#include <SDL3/SDL_gpu.h>
13-
#include <SDL3/SDL_hints.h>
14-
#include <SDL3/SDL_mutex.h>
15-
#include <SDL3/SDL_oldnames.h>
16-
#include <SDL3/SDL_pixels.h>
17-
#include <SDL3/SDL_properties.h>
18-
#include <SDL3/SDL_render.h>
19-
#include <SDL3/SDL_stdinc.h>
20-
#include <SDL3/SDL_video.h>
2111
#include <emscripten/emscripten.h>
2212
#include <emscripten/html5.h>
2313
#include <regex.h>
24-
#include <stdbool.h>
25-
#include <stdint.h>
26-
#include <stdio.h>
2714
#include <webgpu/webgpu.h>
2815

2916
#define MAX_UBO_SECTION_SIZE 4096 // 4 KiB
@@ -34,25 +21,6 @@
3421
#define MAX_PIPELINE_BINDINGS 32
3522
#define MAX_ENTRYPOINT_LENGTH 64
3623

37-
#define EXPAND_ELEMENTS_IF_NEEDED(arr, initialValue, type) \
38-
if (arr->count == arr->capacity) { \
39-
if (arr->capacity == 0) { \
40-
arr->capacity = initialValue; \
41-
} else { \
42-
arr->capacity *= 2; \
43-
} \
44-
arr->elements = (type *)SDL_realloc( \
45-
arr->elements, \
46-
arr->capacity * sizeof(type)); \
47-
}
48-
49-
#define MOVE_ARRAY_CONTENTS_AND_RESET(i, dstArr, dstCount, srcArr, srcCount) \
50-
for (i = 0; i < srcCount; i += 1) { \
51-
dstArr[i] = srcArr[i]; \
52-
} \
53-
dstCount = srcCount; \
54-
srcCount = 0;
55-
5624
#define TRACK_RESOURCE(resource, type, array, count, capacity) \
5725
Uint32 i; \
5826
\
@@ -86,7 +54,9 @@
8654
SDL_Log("%s", buffer); \
8755
} while (0)
8856

89-
// Enums
57+
// Typedefs and Enums
58+
// ---------------------------------------------------
59+
9060
typedef enum WebGPUBindingType
9161
{
9262
WGPUBindingType_Undefined = 0x00000000,
@@ -270,7 +240,7 @@ typedef struct SwapchainSupportDetails
270240
typedef struct WebGPUSwapchainData
271241
{
272242
WGPUSurface surface;
273-
WGPUSwapChain swapchain;
243+
WGPUSurfaceDescriptor surfaceDesc;
274244
WGPUTextureFormat format;
275245
WGPUPresentMode presentMode;
276246

@@ -2340,7 +2310,7 @@ bool WebGPU_INTERNAL_CreateSurface(WebGPURenderer *renderer, WindowData *windowD
23402310
surfaceDescriptor.nextInChain = &fromWindowsHWND.chain;
23412311
surfaceDescriptor.label = NULL;
23422312
}
2343-
#elif defined(__EMSCRIPTEN__)
2313+
#elif defined(SDL_PLATFORM_EMSCRIPTEN)
23442314
{
23452315
#ifdef WEBGPU_BACKEND_DAWN
23462316
WGPUSurfaceSourceCanvasHTMLSelector_Emscripten fromCanvasHTMLSelector;
@@ -2360,13 +2330,20 @@ bool WebGPU_INTERNAL_CreateSurface(WebGPURenderer *renderer, WindowData *windowD
23602330
#error "Unsupported WGPU_TARGET"
23612331
#endif
23622332
windowData->swapchainData.surface = wgpuInstanceCreateSurface(renderer->instance, &surfaceDescriptor);
2333+
windowData->swapchainData.surfaceDesc = surfaceDescriptor;
23632334
return windowData->swapchainData.surface != NULL;
23642335
}
23652336

23662337
static void WebGPU_CreateSwapchain(WebGPURenderer *renderer, WindowData *windowData)
23672338
{
23682339
SDL_assert(WebGPU_INTERNAL_CreateSurface(renderer, windowData));
2340+
SDL_assert(windowData->swapchainData.surface);
2341+
2342+
WebGPUSwapchainData *swapchainData = &windowData->swapchainData;
23692343

2344+
// This is done as a temporary workaround until I can figure out why the macros in WebGPU_INTERNAL_CreateSurface are not working.
2345+
// Ideally we would just call WebGPU_INTERNAL_CreateSurface here and skip the lines between the dividers.
2346+
// -----
23702347
WGPUSurfaceDescriptorFromCanvasHTMLSelector canvas_desc = {
23712348
.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector,
23722349
.selector = "#canvas",
@@ -2375,11 +2352,20 @@ static void WebGPU_CreateSwapchain(WebGPURenderer *renderer, WindowData *windowD
23752352
.nextInChain = &canvas_desc.chain,
23762353
.label = "SDL_GPU Swapchain Surface",
23772354
};
2378-
2379-
WebGPUSwapchainData *swapchainData = &windowData->swapchainData;
23802355
swapchainData->surface = wgpuInstanceCreateSurface(renderer->instance, &surf_desc);
2356+
// -----
2357+
23812358
swapchainData->format = wgpuSurfaceGetPreferredFormat(swapchainData->surface, renderer->adapter);
23822359
swapchainData->presentMode = SDLToWGPUPresentMode(windowData->presentMode);
2360+
wgpuSurfaceConfigure(swapchainData->surface, &(WGPUSurfaceConfiguration){
2361+
.usage = WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst,
2362+
.format = swapchainData->format,
2363+
.width = windowData->window->w,
2364+
.height = windowData->window->h,
2365+
.presentMode = swapchainData->presentMode,
2366+
.alphaMode = WGPUCompositeAlphaMode_Opaque,
2367+
.device = renderer->device,
2368+
});
23832369

23842370
// Swapchain should be the size of whatever SDL_Window it is attached to
23852371
swapchainData->width = windowData->window->w;
@@ -2390,17 +2376,6 @@ static void WebGPU_CreateSwapchain(WebGPURenderer *renderer, WindowData *windowD
23902376
swapchainData->depthStencilView = NULL;
23912377
swapchainData->depthStencilTexture = NULL;
23922378

2393-
// Emscripten WebGPU swapchain
2394-
WGPUSwapChainDescriptor swapchainDesc = {
2395-
.usage = WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_CopySrc | WGPUTextureUsage_CopyDst,
2396-
.format = swapchainData->format,
2397-
.width = swapchainData->width,
2398-
.height = swapchainData->height,
2399-
.presentMode = swapchainData->presentMode,
2400-
};
2401-
2402-
swapchainData->swapchain = wgpuDeviceCreateSwapChain(renderer->device, swapchainData->surface, &swapchainDesc);
2403-
24042379
// Depth/stencil texture for swapchain
24052380
WGPUTextureDescriptor depthDesc = {
24062381
.usage = WGPUTextureUsage_RenderAttachment,
@@ -2444,7 +2419,7 @@ static void WebGPU_CreateSwapchain(WebGPURenderer *renderer, WindowData *windowD
24442419
swapchainData->msaaView = wgpuTextureCreateView(swapchainData->msaaTexture, NULL);
24452420
}
24462421

2447-
SDL_Log("WebGPU: Created swapchain %p of size %dx%d", swapchainData->swapchain, swapchainData->width, swapchainData->height);
2422+
SDL_Log("WebGPU: Created swapchain surface %p of size %dx%d", swapchainData->surface, swapchainData->width, swapchainData->height);
24482423
}
24492424

24502425
static SDL_GPUTextureFormat WebGPU_GetSwapchainTextureFormat(
@@ -2475,10 +2450,6 @@ static void WebGPU_DestroySwapchain(WebGPUSwapchainData *swapchainData)
24752450
wgpuTextureRelease(swapchainData->depthStencilTexture);
24762451
swapchainData->depthStencilTexture = NULL;
24772452
}
2478-
if (swapchainData->swapchain) {
2479-
wgpuSwapChainRelease(swapchainData->swapchain);
2480-
swapchainData->swapchain = NULL;
2481-
}
24822453
if (swapchainData->surface) {
24832454
wgpuSurfaceRelease(swapchainData->surface);
24842455
swapchainData->surface = NULL;
@@ -2492,6 +2463,32 @@ static void WebGPU_RecreateSwapchain(WebGPURenderer *renderer, WindowData *windo
24922463
windowData->needsSwapchainRecreate = false;
24932464
}
24942465

2466+
static WGPUTexture WebGPU_INTERNAL_AcquireSurfaceTexture(WebGPURenderer *renderer, WindowData *windowData)
2467+
{
2468+
WGPUSurfaceTexture surfaceTexture;
2469+
wgpuSurfaceGetCurrentTexture(windowData->swapchainData.surface, &surfaceTexture);
2470+
2471+
switch (surfaceTexture.status) {
2472+
case WGPUSurfaceGetCurrentTextureStatus_Success:
2473+
break;
2474+
case WGPUSurfaceGetCurrentTextureStatus_DeviceLost:
2475+
SDL_LogError(SDL_LOG_CATEGORY_GPU, "GPU DEVICE LOST");
2476+
SDL_SetError("GPU DEVICE LOST");
2477+
return NULL;
2478+
case WGPUSurfaceGetCurrentTextureStatus_OutOfMemory:
2479+
SDL_OutOfMemory();
2480+
return NULL;
2481+
case WGPUSurfaceGetCurrentTextureStatus_Timeout:
2482+
case WGPUSurfaceGetCurrentTextureStatus_Outdated:
2483+
case WGPUSurfaceGetCurrentTextureStatus_Lost:
2484+
default:
2485+
WebGPU_RecreateSwapchain(renderer, windowData);
2486+
return NULL;
2487+
}
2488+
2489+
return surfaceTexture.texture;
2490+
}
2491+
24952492
static bool WebGPU_AcquireSwapchainTexture(
24962493
SDL_GPUCommandBuffer *commandBuffer,
24972494
SDL_Window *window,
@@ -2516,11 +2513,11 @@ static bool WebGPU_AcquireSwapchainTexture(
25162513
}
25172514
}
25182515

2519-
// Get the current texture view from the swapchain
2520-
WGPUTextureView currentView = wgpuSwapChainGetCurrentTextureView(swapchainData->swapchain);
2521-
if (currentView == NULL) {
2522-
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to acquire texture view from swapchain");
2523-
SDL_SetError("Failed to acquire texture view from swapchain");
2516+
// Get the current texture from the swapchain
2517+
WGPUTexture currentTexture = WebGPU_INTERNAL_AcquireSurfaceTexture(renderer, windowData);
2518+
if (currentTexture == NULL) {
2519+
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to acquire texture from swapchain");
2520+
SDL_SetError("Failed to acquire texture from swapchain");
25242521
return false;
25252522
}
25262523

@@ -2531,8 +2528,8 @@ static bool WebGPU_AcquireSwapchainTexture(
25312528
return false;
25322529
}
25332530

2534-
texture->texture = wgpuSwapChainGetCurrentTexture(swapchainData->swapchain);
2535-
texture->fullView = currentView;
2531+
texture->texture = currentTexture;
2532+
texture->fullView = wgpuTextureCreateView(currentTexture, NULL);
25362533
texture->dimensions = (WGPUExtent3D){
25372534
.width = swapchainData->width,
25382535
.height = swapchainData->height,

0 commit comments

Comments
 (0)