26
26
// Description: WebGPU driver for SDL_gpu using the emscripten WebGPU implementation
27
27
// Note: Compiling SDL GPU programs using emscripten will require -sUSE_WEBGPU=1 -sASYNCIFY=1
28
28
29
- #include "SDL_internal.h"
30
29
#include "../SDL_sysgpu.h"
30
+ #include "SDL_internal.h"
31
31
#include <emscripten/emscripten.h>
32
32
#include <emscripten/html5.h>
33
33
#include <regex.h>
34
34
35
35
// TODO: REMOVE
36
36
// Code compiles without these but my IDE is complaining without them
37
- #include "../../../include/SDL3/SDL_gpu.h"
38
37
#include "../../../include/SDL3/SDL_atomic.h"
38
+ #include "../../../include/SDL3/SDL_gpu.h"
39
39
40
40
// I currently have a copy of the webgpu.h file in the include directory:
41
41
// - usr/local/include/webgpu/webgpu.h
@@ -2082,6 +2082,88 @@ static void WebGPU_ReleaseFence(SDL_GPURenderer *driverData, SDL_GPUFence *fence
2082
2082
// There are no fences in WebGPU, so we don't need to do anything here
2083
2083
}
2084
2084
2085
+ void WebGPU_SetViewport (SDL_GPUCommandBuffer * renderPass , const SDL_GPUViewport * viewport )
2086
+ {
2087
+ if (renderPass == NULL ) {
2088
+ return ;
2089
+ }
2090
+
2091
+ WebGPUCommandBuffer * commandBuffer = (WebGPUCommandBuffer * )renderPass ;
2092
+
2093
+ Uint32 window_width = commandBuffer -> renderer -> claimedWindows [0 ]-> swapchainData .width ;
2094
+ Uint32 window_height = commandBuffer -> renderer -> claimedWindows [0 ]-> swapchainData .height ;
2095
+ WebGPUViewport * wgpuViewport = & commandBuffer -> currentViewport ;
2096
+
2097
+ float max_viewport_width = (float )window_width - viewport -> x ;
2098
+ float max_viewport_height = (float )window_height - viewport -> y ;
2099
+
2100
+ wgpuViewport = & (WebGPUViewport ){
2101
+ .x = viewport -> x ,
2102
+ .y = viewport -> y ,
2103
+ .width = viewport -> w > max_viewport_width ? max_viewport_width : viewport -> w ,
2104
+ .height = viewport -> h > max_viewport_height ? max_viewport_height : viewport -> h ,
2105
+ .minDepth = viewport -> min_depth > 0.0f ? viewport -> min_depth : 0.0f ,
2106
+ .maxDepth = viewport -> max_depth > wgpuViewport -> minDepth ? viewport -> max_depth : wgpuViewport -> minDepth ,
2107
+ };
2108
+
2109
+ // Set the viewport
2110
+ wgpuRenderPassEncoderSetViewport (commandBuffer -> renderPassEncoder , wgpuViewport -> x , wgpuViewport -> y , wgpuViewport -> width , wgpuViewport -> height , wgpuViewport -> minDepth , wgpuViewport -> maxDepth );
2111
+ }
2112
+
2113
+ void WebGPU_SetScissorRect (SDL_GPUCommandBuffer * renderPass , const SDL_Rect * scissorRect )
2114
+ {
2115
+ if (renderPass == NULL ) {
2116
+ return ;
2117
+ }
2118
+
2119
+ WebGPUCommandBuffer * commandBuffer = (WebGPUCommandBuffer * )renderPass ;
2120
+
2121
+ Uint32 window_width = commandBuffer -> renderer -> claimedWindows [0 ]-> swapchainData .width ;
2122
+ Uint32 window_height = commandBuffer -> renderer -> claimedWindows [0 ]-> swapchainData .height ;
2123
+
2124
+ Uint32 max_scissor_width = window_width - scissorRect -> x ;
2125
+ Uint32 max_scissor_height = window_height - scissorRect -> y ;
2126
+
2127
+ Uint32 clamped_width = (scissorRect -> w > max_scissor_width ) ? max_scissor_width : scissorRect -> w ;
2128
+ Uint32 clamped_height = (scissorRect -> h > max_scissor_height ) ? max_scissor_height : scissorRect -> h ;
2129
+
2130
+ commandBuffer -> currentScissor = (WebGPURect ){
2131
+ .x = scissorRect -> x ,
2132
+ .y = scissorRect -> y ,
2133
+ .width = clamped_width ,
2134
+ .height = clamped_height ,
2135
+ };
2136
+
2137
+ wgpuRenderPassEncoderSetScissorRect (commandBuffer -> renderPassEncoder , scissorRect -> x , scissorRect -> y , clamped_width , clamped_height );
2138
+ }
2139
+
2140
+ static void WebGPU_SetStencilReference (SDL_GPUCommandBuffer * commandBuffer ,
2141
+ Uint8 reference )
2142
+ {
2143
+ if (commandBuffer == NULL ) {
2144
+ return ;
2145
+ }
2146
+
2147
+ wgpuRenderPassEncoderSetStencilReference (((WebGPUCommandBuffer * )commandBuffer )-> renderPassEncoder , reference );
2148
+ }
2149
+
2150
+ static void WebGPU_SetBlendConstants (
2151
+ SDL_GPUCommandBuffer * commandBuffer ,
2152
+ SDL_FColor blendConstants )
2153
+ {
2154
+ if (commandBuffer == NULL ) {
2155
+ return ;
2156
+ }
2157
+
2158
+ wgpuRenderPassEncoderSetBlendConstant (((WebGPUCommandBuffer * )commandBuffer )-> renderPassEncoder ,
2159
+ & (WGPUColor ){
2160
+ .r = blendConstants .r ,
2161
+ .g = blendConstants .g ,
2162
+ .b = blendConstants .b ,
2163
+ .a = blendConstants .a ,
2164
+ });
2165
+ }
2166
+
2085
2167
static WGPUTextureView WebGPU_INTERNAL_CreateLayerView (WGPUTexture texture ,
2086
2168
WGPUTextureFormat format ,
2087
2169
SDL_GPUTextureType type ,
@@ -2111,23 +2193,40 @@ void WebGPU_BeginRenderPass(SDL_GPUCommandBuffer *commandBuffer,
2111
2193
uint32_t colorAttachmentCount ,
2112
2194
const SDL_GPUDepthStencilTargetInfo * depthStencilAttachmentInfo )
2113
2195
{
2196
+ Uint32 w , h ;
2197
+ SDL_GPUViewport defaultViewport ;
2198
+ SDL_Rect defaultScissor ;
2199
+ SDL_FColor defaultBlendConstants ;
2200
+ Uint32 framebufferWidth = SDL_MAX_UINT32 ;
2201
+ Uint32 framebufferHeight = SDL_MAX_UINT32 ;
2202
+
2114
2203
WebGPUCommandBuffer * wgpu_cmd_buf = (WebGPUCommandBuffer * )commandBuffer ;
2115
2204
if (!wgpu_cmd_buf || colorAttachmentCount == 0 ) {
2116
2205
return ;
2117
2206
}
2118
2207
2119
- int width , height ;
2120
- SDL_GetWindowSize (wgpu_cmd_buf -> renderer -> claimedWindows [0 ]-> window , & width , & height );
2121
- wgpu_cmd_buf -> currentViewport = (WebGPUViewport ){ 0 , 0 , width , height , 0.0 , 1.0 };
2122
- wgpu_cmd_buf -> currentScissor = (WebGPURect ){ 0 , 0 , width , height };
2123
-
2124
2208
// Handle color attachments
2125
2209
WGPURenderPassColorAttachment colorAttachments [colorAttachmentCount ];
2126
2210
for (uint32_t i = 0 ; i < colorAttachmentCount ; i ++ ) {
2211
+
2127
2212
const SDL_GPUColorTargetInfo * colorInfo = & colorAttachmentInfos [i ];
2128
2213
WebGPUTexture * texture = (WebGPUTexture * )colorInfo -> texture ;
2129
2214
WGPUTextureView textureView = texture -> fullView ;
2130
2215
2216
+ w = texture -> common .info .width >> colorInfo -> mip_level ;
2217
+ h = texture -> common .info .height >> colorInfo -> mip_level ;
2218
+
2219
+ // The framebuffer cannot be larger than the smallest attachment.
2220
+
2221
+ if (w < framebufferWidth ) {
2222
+ framebufferWidth = w ;
2223
+ }
2224
+
2225
+ if (h < framebufferHeight ) {
2226
+ framebufferHeight = h ;
2227
+ }
2228
+
2229
+ // If a layer is specified, create a layer view from the texture
2131
2230
if (colorInfo -> layer_or_depth_plane != ~0u && texture -> layerCount > 1 ) {
2132
2231
textureView = WebGPU_INTERNAL_CreateLayerView (texture -> texture ,
2133
2232
SDLToWGPUTextureFormat (texture -> format ),
@@ -2167,6 +2266,17 @@ void WebGPU_BeginRenderPass(SDL_GPUCommandBuffer *commandBuffer,
2167
2266
.stencilStoreOp = SDLToWGPUStoreOp (depthStencilAttachmentInfo -> stencil_store_op ),
2168
2267
.stencilClearValue = depthStencilAttachmentInfo -> clear_stencil
2169
2268
};
2269
+
2270
+ WebGPUTexture * tex = (WebGPUTexture * )depthStencilAttachmentInfo -> texture ;
2271
+ w = tex -> common .info .width ;
2272
+ h = tex -> common .info .height ;
2273
+
2274
+ if (w < framebufferWidth ) {
2275
+ framebufferWidth = w ;
2276
+ }
2277
+ if (h < framebufferHeight ) {
2278
+ framebufferHeight = h ;
2279
+ }
2170
2280
}
2171
2281
2172
2282
WGPURenderPassDescriptor renderPassDesc = {
@@ -2179,6 +2289,30 @@ void WebGPU_BeginRenderPass(SDL_GPUCommandBuffer *commandBuffer,
2179
2289
wgpu_cmd_buf -> renderPassEncoder =
2180
2290
wgpuCommandEncoderBeginRenderPass (wgpu_cmd_buf -> commandEncoder , & renderPassDesc );
2181
2291
2292
+ // Set sensible deafult states for the viewport, scissor, and blend constants
2293
+ defaultViewport .x = 0 ;
2294
+ defaultViewport .y = 0 ;
2295
+ defaultViewport .w = (float )framebufferWidth ;
2296
+ defaultViewport .h = (float )framebufferHeight ;
2297
+ defaultViewport .min_depth = 0 ;
2298
+ defaultViewport .max_depth = 1 ;
2299
+ wgpu_cmd_buf -> currentViewport = (WebGPUViewport ){ defaultViewport .x , defaultViewport .y , defaultViewport .w , defaultViewport .h , defaultViewport .min_depth , defaultViewport .max_depth };
2300
+
2301
+ WebGPU_SetViewport (commandBuffer , & defaultViewport );
2302
+
2303
+ defaultScissor .x = 0 ;
2304
+ defaultScissor .y = 0 ;
2305
+ defaultScissor .w = (Sint32 )framebufferWidth ;
2306
+ defaultScissor .h = (Sint32 )framebufferHeight ;
2307
+ wgpu_cmd_buf -> currentScissor = (WebGPURect ){ defaultScissor .x , defaultScissor .y , defaultScissor .w , defaultScissor .h };
2308
+
2309
+ WebGPU_SetScissorRect (commandBuffer , & defaultScissor );
2310
+
2311
+ defaultBlendConstants = (SDL_FColor ){ 0.0f , 0.0f , 0.0f , 0.0f };
2312
+ WebGPU_SetBlendConstants (commandBuffer , defaultBlendConstants );
2313
+
2314
+ WebGPU_SetStencilReference (commandBuffer , 0 );
2315
+
2182
2316
wgpu_cmd_buf -> common .render_pass = (Pass ){
2183
2317
.command_buffer = commandBuffer ,
2184
2318
.in_progress = true,
@@ -3811,87 +3945,6 @@ static void WebGPU_BindFragmentSamplers(SDL_GPUCommandBuffer *commandBuffer,
3811
3945
WebGPU_INTERNAL_BindSamplers (commandBuffer , firstSlot , textureSamplerBindings , numBindings );
3812
3946
}
3813
3947
3814
- void WebGPU_SetViewport (SDL_GPUCommandBuffer * renderPass , const SDL_GPUViewport * viewport )
3815
- {
3816
- if (renderPass == NULL ) {
3817
- return ;
3818
- }
3819
-
3820
- WebGPUCommandBuffer * commandBuffer = (WebGPUCommandBuffer * )renderPass ;
3821
-
3822
- Uint32 window_width = commandBuffer -> renderer -> claimedWindows [0 ]-> swapchainData .width ;
3823
- Uint32 window_height = commandBuffer -> renderer -> claimedWindows [0 ]-> swapchainData .height ;
3824
- WebGPUViewport * wgpuViewport = & commandBuffer -> currentViewport ;
3825
-
3826
- float max_viewport_width = (float )window_width - viewport -> x ;
3827
- float max_viewport_height = (float )window_height - viewport -> y ;
3828
-
3829
- wgpuViewport = & (WebGPUViewport ){
3830
- .x = viewport -> x ,
3831
- .y = viewport -> y ,
3832
- .width = viewport -> w > max_viewport_width ? max_viewport_width : viewport -> w ,
3833
- .height = viewport -> h > max_viewport_height ? max_viewport_height : viewport -> h ,
3834
- .minDepth = viewport -> min_depth > 0.0f ? viewport -> min_depth : 0.0f ,
3835
- .maxDepth = viewport -> max_depth > wgpuViewport -> minDepth ? viewport -> max_depth : wgpuViewport -> minDepth ,
3836
- };
3837
-
3838
- // Set the viewport
3839
- wgpuRenderPassEncoderSetViewport (commandBuffer -> renderPassEncoder , wgpuViewport -> x , wgpuViewport -> y , wgpuViewport -> width , wgpuViewport -> height , wgpuViewport -> minDepth , wgpuViewport -> maxDepth );
3840
- }
3841
-
3842
- void WebGPU_SetScissorRect (SDL_GPUCommandBuffer * renderPass , const SDL_Rect * scissorRect )
3843
- {
3844
- if (renderPass == NULL ) {
3845
- return ;
3846
- }
3847
-
3848
- WebGPUCommandBuffer * commandBuffer = (WebGPUCommandBuffer * )renderPass ;
3849
-
3850
- Uint32 window_width = commandBuffer -> renderer -> claimedWindows [0 ]-> swapchainData .width ;
3851
- Uint32 window_height = commandBuffer -> renderer -> claimedWindows [0 ]-> swapchainData .height ;
3852
-
3853
- Uint32 max_scissor_width = window_width - scissorRect -> x ;
3854
- Uint32 max_scissor_height = window_height - scissorRect -> y ;
3855
-
3856
- Uint32 clamped_width = (scissorRect -> w > max_scissor_width ) ? max_scissor_width : scissorRect -> w ;
3857
- Uint32 clamped_height = (scissorRect -> h > max_scissor_height ) ? max_scissor_height : scissorRect -> h ;
3858
-
3859
- commandBuffer -> currentScissor = (WebGPURect ){
3860
- .x = scissorRect -> x ,
3861
- .y = scissorRect -> y ,
3862
- .width = clamped_width ,
3863
- .height = clamped_height ,
3864
- };
3865
-
3866
- wgpuRenderPassEncoderSetScissorRect (commandBuffer -> renderPassEncoder , scissorRect -> x , scissorRect -> y , clamped_width , clamped_height );
3867
- }
3868
-
3869
- static void WebGPU_SetStencilReference (SDL_GPUCommandBuffer * commandBuffer ,
3870
- Uint8 reference )
3871
- {
3872
- if (commandBuffer == NULL ) {
3873
- return ;
3874
- }
3875
-
3876
- wgpuRenderPassEncoderSetStencilReference (((WebGPUCommandBuffer * )commandBuffer )-> renderPassEncoder , reference );
3877
- }
3878
-
3879
- static void WebGPU_SetBlendConstants (
3880
- SDL_GPUCommandBuffer * commandBuffer ,
3881
- SDL_FColor blendConstants )
3882
- {
3883
- if (commandBuffer == NULL ) {
3884
- return ;
3885
- }
3886
-
3887
- wgpuRenderPassEncoderSetBlendConstant (((WebGPUCommandBuffer * )commandBuffer )-> renderPassEncoder , & (WGPUColor ){
3888
- .r = blendConstants .r ,
3889
- .g = blendConstants .g ,
3890
- .b = blendConstants .b ,
3891
- .a = blendConstants .a ,
3892
- });
3893
- }
3894
-
3895
3948
static void WebGPU_BindGraphicsPipeline (
3896
3949
SDL_GPUCommandBuffer * commandBuffer ,
3897
3950
SDL_GPUGraphicsPipeline * graphicsPipeline )
@@ -4011,7 +4064,6 @@ static void WebGPU_DrawPrimitives(
4011
4064
wgpuRenderPassEncoderDraw (wgpu_cmd_buf -> renderPassEncoder , vertexCount , instanceCount , firstVertex , firstInstance );
4012
4065
}
4013
4066
4014
-
4015
4067
static void WebGPU_DrawIndexedPrimitives (
4016
4068
SDL_GPUCommandBuffer * commandBuffer ,
4017
4069
Uint32 numIndices ,
0 commit comments