From 858f6128a370ed9ae2f052b7f009f95877bf2965 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 30 Jul 2023 17:58:40 +0200 Subject: [PATCH 01/95] sokol_gfx.h: wgpu update wip --- sokol_gfx.h | 166 +++++++++++++++++++++++----------------------------- 1 file changed, 73 insertions(+), 93 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 19a29d6b4..4a31de7fe 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2902,11 +2902,6 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(METAL_FRAGMENT_SHADER_ENTRY_NOT_FOUND, "fragment shader entry not found (metal)") \ _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_FAILED, "failed to create render pipeline state (metal)") \ _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_OUTPUT, "") \ - _SG_LOGITEM_XMACRO(WGPU_MAP_UNIFORM_BUFFER_FAILED, "mapping uniform buffer failed (wgpu)") \ - _SG_LOGITEM_XMACRO(WGPU_STAGING_BUFFER_FULL_COPY_TO_BUFFER, "per frame staging buffer full when copying to buffer (wgpu)") \ - _SG_LOGITEM_XMACRO(WGPU_STAGING_BUFFER_FULL_COPY_TO_TEXTURE, "per frame staging buffer full when copying to texture (wgpu)") \ - _SG_LOGITEM_XMACRO(WGPU_RESET_STATE_CACHE_FIXME, "_sg_wgpu_reset_state_cache: fixme") \ - _SG_LOGITEM_XMACRO(WGPU_ACTIVATE_CONTEXT_FIXME, "_sg_wgpu_activate_context: fixme") \ _SG_LOGITEM_XMACRO(UNINIT_BUFFER_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in buffer uninit (must be same as for creation)") \ _SG_LOGITEM_XMACRO(UNINIT_IMAGE_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in image uninit (must be same as for creation)") \ _SG_LOGITEM_XMACRO(UNINIT_SAMPLER_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in sampler uninit (must be same as for creation)") \ @@ -3134,7 +3129,7 @@ typedef enum sg_log_item { .context.color_format: default value depends on selected backend: all GL backends: SG_PIXELFORMAT_RGBA8 Metal and D3D11: SG_PIXELFORMAT_BGRA8 - WGPU: *no default* (must be queried from WGPU swapchain) + WebGPU: *no default* (must be queried from swapchain) .context.depth_format SG_PIXELFORMAT_DEPTH_STENCIL .context.sample_count 1 @@ -3236,7 +3231,7 @@ typedef struct sg_wgpu_context_desc { const void* (*render_view_userdata_cb)(void*); const void* (*resolve_view_cb)(void); // returns WGPUTextureView const void* (*resolve_view_userdata_cb)(void*); - const void* (*depth_stencil_view_cb)(void); // returns WGPUTextureView, must be WGPUTextureFormat_Depth24Plus8 + const void* (*depth_stencil_view_cb)(void); // returns WGPUTextureView const void* (*depth_stencil_view_userdata_cb)(void*); void* user_data; } sg_wgpu_context_desc; @@ -3614,11 +3609,7 @@ inline int sg_append_buffer(sg_buffer buf_id, const sg_range& data) { return sg_ #endif #import #elif defined(SOKOL_WGPU) - #if defined(__EMSCRIPTEN__) - #include - #else - #include - #endif + #include #elif defined(SOKOL_GLCORE33) || defined(SOKOL_GLES3) #define _SOKOL_ANY_GL (1) @@ -4814,13 +4805,20 @@ typedef struct { _sg_image_common_t cmn; struct { WGPUTexture tex; - WGPUTextureView tex_view; - WGPUTexture msaa_tex; - WGPUSampler sampler; + WGPUTextureView view; } wgpu; } _sg_wgpu_image_t; typedef _sg_wgpu_image_t _sg_image_t; +typedef struct { + _sg_slot_t slot; + _sg_sampler_common_t cmn; + struct { + WGPUSampler smp; + } wgpu; +} _sg_wgpu_sampler_t; +typedef _sg_wgpu_sampler_t _sg_sampler_t; + typedef struct { WGPUShaderModule module; WGPUBindGroupLayout bind_group_layout; @@ -4849,8 +4847,7 @@ typedef _sg_wgpu_pipeline_t _sg_pipeline_t; typedef struct { _sg_image_t* image; - WGPUTextureView render_tex_view; - WGPUTextureView resolve_tex_view; + WGPUTextureView view; } _sg_wgpu_attachment_t; typedef struct { @@ -4858,6 +4855,7 @@ typedef struct { _sg_pass_common_t cmn; struct { _sg_wgpu_attachment_t color_atts[SG_MAX_COLOR_ATTACHMENTS]; + _sg_wgpu_attachment_t resolve_atts[SG_MAX_COLOR_ATTACHMENTS]; _sg_wgpu_attachment_t ds_att; } wgpu; } _sg_wgpu_pass_t; @@ -4885,23 +4883,9 @@ typedef struct { } stage; } _sg_wgpu_ubpool_t; -// ...a similar pool (like uniform buffer pool) of dynamic-resource staging buffers -typedef struct { - uint32_t num_bytes; - uint32_t offset; // current offset into current frame's staging buffer - int num; // number of staging buffers - int cur; // this frame's staging buffer - WGPUBuffer buf[_SG_WGPU_STAGING_PIPELINE_SIZE]; // CPU-side staging buffers - uint8_t* ptr[_SG_WGPU_STAGING_PIPELINE_SIZE]; // if != 0, staging buffer currently mapped -} _sg_wgpu_stagingpool_t; - // the WGPU backend state typedef struct { bool valid; - bool in_pass; - bool draw_indexed; - int cur_width; - int cur_height; WGPUDevice dev; WGPUTextureView (*render_view_cb)(void); WGPUTextureView (*render_view_userdata_cb)(void*); @@ -4910,6 +4894,10 @@ typedef struct { WGPUTextureView (*depth_stencil_view_cb)(void); WGPUTextureView (*depth_stencil_view_userdata_cb)(void*); void* user_data; + bool in_pass; + bool use_indexed_draw; + int cur_width; + int cur_height; WGPUQueue queue; WGPUCommandEncoder render_cmd_enc; WGPUCommandEncoder staging_cmd_enc; @@ -4918,7 +4906,6 @@ typedef struct { const _sg_pipeline_t* cur_pipeline; sg_pipeline cur_pipeline_id; _sg_wgpu_ubpool_t ub; - _sg_wgpu_stagingpool_t staging; } _sg_wgpu_backend_t; #endif @@ -11956,16 +11943,28 @@ _SOKOL_PRIVATE WGPUBufferUsageFlags _sg_wgpu_buffer_usage(sg_buffer_type t, sg_u return res; } -_SOKOL_PRIVATE WGPULoadOp _sg_wgpu_load_op(sg_action a) { +_SOKOL_PRIVATE WGPULoadOp _sg_wgpu_load_op(sg_load_action a) { switch (a) { - case SG_ACTION_CLEAR: - case SG_ACTION_DONTCARE: + case SG_LOADACTION_CLEAR: + case SG_LOADACTION_DONTCARE: return WGPULoadOp_Clear; - case SG_ACTION_LOAD: + case SG_LOADACTION_LOAD: return WGPULoadOp_Load; default: SOKOL_UNREACHABLE; - return (WGPULoadOp)0; + return WGPULoadOp_Force32; + } +} + +_SOKOL_PRIVATE WGPUStoreOp _sg_wgpu_store_op(sg_store_action a) { + switch (a) { + case SG_STOREACTION_STORE: + return WGPUStoreOp_Store; + case SG_STOREACTION_DONTCARE: + return WGPUStoreOp_Discard; + default: + SOKOL_UNREACHABLE; + return WGPUStoreOp_Force32; } } @@ -11979,13 +11978,13 @@ _SOKOL_PRIVATE WGPUTextureViewDimension _sg_wgpu_tex_viewdim(sg_image_type t) { } } -_SOKOL_PRIVATE WGPUTextureComponentType _sg_wgpu_tex_comptype(sg_image_sample_type t) { - // FIXME +_SOKOL_PRIVATE WGPUTextureSampleType _sg_wgpu_tex_sample_type(sg_image_sample_type t) { switch (t) { - case SG_IMAGESAMPLETYPE_FLOAT: return WGPUTextureComponentType_Float; - case SG_IMAGESAMPLETYPE_SINT: return WGPUTextureComponentType_Sint; - case SG_IMAGESAMPLETYPE_UINT: return WGPUTextureComponentType_Uint; - default: SOKOL_UNREACHABLE; return WGPUTextureComponentType_Force32; + case SG_IMAGESAMPLETYPE_FLOAT: return WGPUTextureSampleType_Float; + case SG_IMAGESAMPLETYPE_DEPTH: return WGPUTextureSampleType_Depth; + case SG_IMAGESAMPLETYPE_SINT: return WGPUTextureSampleType_Sint; + case SG_IMAGESAMPLETYPE_UINT: return WGPUTextureSampleType_Uint; + default: SOKOL_UNREACHABLE; return WGPUTextureSampleType_Force32; } } @@ -12015,12 +12014,8 @@ _SOKOL_PRIVATE WGPUAddressMode _sg_wgpu_sampler_addrmode(sg_wrap m) { _SOKOL_PRIVATE WGPUFilterMode _sg_wgpu_sampler_minmagfilter(sg_filter f) { switch (f) { case SG_FILTER_NEAREST: - case SG_FILTER_NEAREST_MIPMAP_NEAREST: - case SG_FILTER_NEAREST_MIPMAP_LINEAR: return WGPUFilterMode_Nearest; case SG_FILTER_LINEAR: - case SG_FILTER_LINEAR_MIPMAP_NEAREST: - case SG_FILTER_LINEAR_MIPMAP_LINEAR: return WGPUFilterMode_Linear; default: SOKOL_UNREACHABLE; @@ -12028,15 +12023,12 @@ _SOKOL_PRIVATE WGPUFilterMode _sg_wgpu_sampler_minmagfilter(sg_filter f) { } } -_SOKOL_PRIVATE WGPUFilterMode _sg_wgpu_sampler_mipfilter(sg_filter f) { +_SOKOL_PRIVATE WGPUFilterMode _sg_wgpu_sampler_mipmap_filter(sg_filter f) { switch (f) { + case SG_FILTER_NONE: case SG_FILTER_NEAREST: - case SG_FILTER_LINEAR: - case SG_FILTER_NEAREST_MIPMAP_NEAREST: - case SG_FILTER_LINEAR_MIPMAP_NEAREST: return WGPUFilterMode_Nearest; - case SG_FILTER_NEAREST_MIPMAP_LINEAR: - case SG_FILTER_LINEAR_MIPMAP_LINEAR: + case SG_FILTER_LINEAR: return WGPUFilterMode_Linear; default: SOKOL_UNREACHABLE; @@ -12049,28 +12041,28 @@ _SOKOL_PRIVATE WGPUIndexFormat _sg_wgpu_indexformat(sg_index_type t) { return (t == SG_INDEXTYPE_UINT16) ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32; } -_SOKOL_PRIVATE WGPUInputStepMode _sg_wgpu_stepmode(sg_vertex_step s) { - return (s == SG_VERTEXSTEP_PER_VERTEX) ? WGPUInputStepMode_Vertex : WGPUInputStepMode_Instance; +_SOKOL_PRIVATE WGPUVertexStepMode _sg_wgpu_stepmode(sg_vertex_step s) { + return (s == SG_VERTEXSTEP_PER_VERTEX) ? WGPUVertexStepMode_Vertex : WGPUVertexStepMode_Instance; } _SOKOL_PRIVATE WGPUVertexFormat _sg_wgpu_vertexformat(sg_vertex_format f) { switch (f) { - case SG_VERTEXFORMAT_FLOAT: return WGPUVertexFormat_Float; - case SG_VERTEXFORMAT_FLOAT2: return WGPUVertexFormat_Float2; - case SG_VERTEXFORMAT_FLOAT3: return WGPUVertexFormat_Float3; - case SG_VERTEXFORMAT_FLOAT4: return WGPUVertexFormat_Float4; - case SG_VERTEXFORMAT_BYTE4: return WGPUVertexFormat_Char4; - case SG_VERTEXFORMAT_BYTE4N: return WGPUVertexFormat_Char4Norm; - case SG_VERTEXFORMAT_UBYTE4: return WGPUVertexFormat_UChar4; - case SG_VERTEXFORMAT_UBYTE4N: return WGPUVertexFormat_UChar4Norm; - case SG_VERTEXFORMAT_SHORT2: return WGPUVertexFormat_Short2; - case SG_VERTEXFORMAT_SHORT2N: return WGPUVertexFormat_Short2Norm; - case SG_VERTEXFORMAT_USHORT2N: return WGPUVertexFormat_UShort2Norm; - case SG_VERTEXFORMAT_SHORT4: return WGPUVertexFormat_Short4; - case SG_VERTEXFORMAT_SHORT4N: return WGPUVertexFormat_Short4Norm; - case SG_VERTEXFORMAT_USHORT4N: return WGPUVertexFormat_UShort4Norm; - case SG_VERTEXFORMAT_HALF2: return WGPUVertexFormat_Half2; - case SG_VERTEXFORMAT_HALF3: return WGPUVertexFormat_Half4; + case SG_VERTEXFORMAT_FLOAT: return WGPUVertexFormat_Float32; + case SG_VERTEXFORMAT_FLOAT2: return WGPUVertexFormat_Float32x2; + case SG_VERTEXFORMAT_FLOAT3: return WGPUVertexFormat_Float32x3; + case SG_VERTEXFORMAT_FLOAT4: return WGPUVertexFormat_Float32x4; + case SG_VERTEXFORMAT_BYTE4: return WGPUVertexFormat_Sint8x4; + case SG_VERTEXFORMAT_BYTE4N: return WGPUVertexFormat_Snorm8x4; + case SG_VERTEXFORMAT_UBYTE4: return WGPUVertexFormat_Uint8x4; + case SG_VERTEXFORMAT_UBYTE4N: return WGPUVertexFormat_Unorm8x4; + case SG_VERTEXFORMAT_SHORT2: return WGPUVertexFormat_Sint16x2; + case SG_VERTEXFORMAT_SHORT2N: return WGPUVertexFormat_Snorm16x2; + case SG_VERTEXFORMAT_USHORT2N: return WGPUVertexFormat_Uint16x2; + case SG_VERTEXFORMAT_SHORT4: return WGPUVertexFormat_Sint16x4; + case SG_VERTEXFORMAT_SHORT4N: return WGPUVertexFormat_Snorm16x4; + case SG_VERTEXFORMAT_USHORT4N: return WGPUVertexFormat_Unorm16x4; + case SG_VERTEXFORMAT_HALF2: return WGPUVertexFormat_Float16x2; + case SG_VERTEXFORMAT_HALF4: return WGPUVertexFormat_Float16x4; // FIXME! UINT10_N2 case SG_VERTEXFORMAT_UINT10_N2: default: @@ -12129,7 +12121,7 @@ _SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) { case SG_PIXELFORMAT_RGBA8SI: return WGPUTextureFormat_RGBA8Sint; case SG_PIXELFORMAT_BGRA8: return WGPUTextureFormat_BGRA8Unorm; case SG_PIXELFORMAT_RGB10A2: return WGPUTextureFormat_RGB10A2Unorm; - case SG_PIXELFORMAT_RG11B10F: return WGPUTextureFormat_RG11B10Float; + case SG_PIXELFORMAT_RG11B10F: return WGPUTextureFormat_RG11B10Ufloat; case SG_PIXELFORMAT_RG32UI: return WGPUTextureFormat_RG32Uint; case SG_PIXELFORMAT_RG32SI: return WGPUTextureFormat_RG32Sint; case SG_PIXELFORMAT_RG32F: return WGPUTextureFormat_RG32Float; @@ -12148,7 +12140,7 @@ _SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) { case SG_PIXELFORMAT_BC4_RSN: return WGPUTextureFormat_BC4RSnorm; case SG_PIXELFORMAT_BC5_RG: return WGPUTextureFormat_BC5RGUnorm; case SG_PIXELFORMAT_BC5_RGSN: return WGPUTextureFormat_BC5RGSnorm; - case SG_PIXELFORMAT_BC6H_RGBF: return WGPUTextureFormat_BC6HRGBSfloat; + case SG_PIXELFORMAT_BC6H_RGBF: return WGPUTextureFormat_BC6HRGBFloat; case SG_PIXELFORMAT_BC6H_RGBUF: return WGPUTextureFormat_BC6HRGBUfloat; case SG_PIXELFORMAT_BC7_RGBA: return WGPUTextureFormat_BC7RGBAUnorm; @@ -12176,18 +12168,6 @@ _SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) { } } -/* -FIXME ??? this isn't needed anywhere? -_SOKOL_PRIVATE WGPUTextureAspect _sg_wgpu_texture_aspect(sg_pixel_format fmt) { - if (_sg_is_valid_rendertarget_depth_format(fmt)) { - if (!_sg_is_depth_stencil_format(fmt)) { - return WGPUTextureAspect_DepthOnly; - } - } - return WGPUTextureAspect_All; -} -*/ - _SOKOL_PRIVATE WGPUCompareFunction _sg_wgpu_comparefunc(sg_compare_func f) { switch (f) { case SG_COMPAREFUNC_NEVER: return WGPUCompareFunction_Never; @@ -12229,20 +12209,20 @@ _SOKOL_PRIVATE WGPUBlendFactor _sg_wgpu_blendfactor(sg_blend_factor f) { switch (f) { case SG_BLENDFACTOR_ZERO: return WGPUBlendFactor_Zero; case SG_BLENDFACTOR_ONE: return WGPUBlendFactor_One; - case SG_BLENDFACTOR_SRC_COLOR: return WGPUBlendFactor_SrcColor; - case SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR: return WGPUBlendFactor_OneMinusSrcColor; + case SG_BLENDFACTOR_SRC_COLOR: return WGPUBlendFactor_Src; + case SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR: return WGPUBlendFactor_OneMinusSrc; case SG_BLENDFACTOR_SRC_ALPHA: return WGPUBlendFactor_SrcAlpha; case SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA: return WGPUBlendFactor_OneMinusSrcAlpha; - case SG_BLENDFACTOR_DST_COLOR: return WGPUBlendFactor_DstColor; - case SG_BLENDFACTOR_ONE_MINUS_DST_COLOR: return WGPUBlendFactor_OneMinusDstColor; + case SG_BLENDFACTOR_DST_COLOR: return WGPUBlendFactor_Dst; + case SG_BLENDFACTOR_ONE_MINUS_DST_COLOR: return WGPUBlendFactor_OneMinusDst; case SG_BLENDFACTOR_DST_ALPHA: return WGPUBlendFactor_DstAlpha; case SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA: return WGPUBlendFactor_OneMinusDstAlpha; case SG_BLENDFACTOR_SRC_ALPHA_SATURATED: return WGPUBlendFactor_SrcAlphaSaturated; - case SG_BLENDFACTOR_BLEND_COLOR: return WGPUBlendFactor_BlendColor; - case SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR: return WGPUBlendFactor_OneMinusBlendColor; + case SG_BLENDFACTOR_BLEND_COLOR: return WGPUBlendFactor_Constant; + case SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR: return WGPUBlendFactor_OneMinusConstant; // FIXME: separate blend alpha value not supported? - case SG_BLENDFACTOR_BLEND_ALPHA: return WGPUBlendFactor_BlendColor; - case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA: return WGPUBlendFactor_OneMinusBlendColor; + case SG_BLENDFACTOR_BLEND_ALPHA: return WGPUBlendFactor_Constant; + case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA: return WGPUBlendFactor_OneMinusConstant; default: SOKOL_UNREACHABLE; return WGPUBlendFactor_Force32; } From 2083a4b25e1055e3802a3787ba2962306f44fba7 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 30 Jul 2023 23:22:22 +0200 Subject: [PATCH 02/95] sokol_gfx.h: wgpu update wip --- sokol_gfx.h | 249 ++++++++-------------------------------------------- 1 file changed, 38 insertions(+), 211 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 4a31de7fe..e283564e5 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2902,6 +2902,7 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(METAL_FRAGMENT_SHADER_ENTRY_NOT_FOUND, "fragment shader entry not found (metal)") \ _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_FAILED, "failed to create render pipeline state (metal)") \ _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_OUTPUT, "") \ + _SG_LOGITEM_XMACRO(WGPU_MAP_UNIFORM_BUFFER_FAILED, "failed to map uniform buffer (wgpu)") \ _SG_LOGITEM_XMACRO(UNINIT_BUFFER_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in buffer uninit (must be same as for creation)") \ _SG_LOGITEM_XMACRO(UNINIT_IMAGE_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in image uninit (must be same as for creation)") \ _SG_LOGITEM_XMACRO(UNINIT_SAMPLER_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in sampler uninit (must be same as for creation)") \ @@ -4898,7 +4899,6 @@ typedef struct { bool use_indexed_draw; int cur_width; int cur_height; - WGPUQueue queue; WGPUCommandEncoder render_cmd_enc; WGPUCommandEncoder staging_cmd_enc; WGPURenderPassEncoder pass_enc; @@ -12326,13 +12326,11 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { buffer, but this isn't currently allowed in Dawn. */ _SOKOL_PRIVATE void _sg_wgpu_ubpool_init(const sg_desc* desc) { - - /* Add the max-uniform-update size (64 KB) to the requested buffer size, - this is to prevent validation errors in the WebGPU implementation - if the entire buffer size is used per frame. 64 KB is the allowed - max uniform update size on NVIDIA - */ - _sg.wgpu.ub.num_bytes = desc->uniform_buffer_size + _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE; + // Add the max-uniform-update size (64 KB) to the requested buffer size, + // this is to prevent validation errors in the WebGPU implementation + // if the entire buffer size is used per frame. 64 KB is the allowed + // max uniform update size on NVIDIA + _sg.wgpu.ub.num_bytes = (uint32_t)desc->uniform_buffer_size + _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE; WGPUBufferDescriptor ub_desc; _sg_clear(&ub_desc, sizeof(ub_desc)); @@ -12341,42 +12339,42 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_init(const sg_desc* desc) { _sg.wgpu.ub.buf = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &ub_desc); SOKOL_ASSERT(_sg.wgpu.ub.buf); - WGPUBindGroupLayoutBinding ub_bglb_desc[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS]; - _sg_clear(ub_bglb_desc, sizeof(ub_bglb_desc)); - for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { + WGPUBindGroupLayoutEntry ub_bgle_desc[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS]; + _sg_clear(ub_bgle_desc, sizeof(ub_bgle_desc)); + for (uint32_t stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { WGPUShaderStage vis = (stage_index == SG_SHADERSTAGE_VS) ? WGPUShaderStage_Vertex : WGPUShaderStage_Fragment; - for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) { - int bind_index = stage_index * SG_MAX_SHADERSTAGE_UBS + ub_index; - ub_bglb_desc[stage_index][ub_index].binding = bind_index; - ub_bglb_desc[stage_index][ub_index].visibility = vis; - ub_bglb_desc[stage_index][ub_index].type = WGPUBindingType_UniformBuffer; - ub_bglb_desc[stage_index][ub_index].hasDynamicOffset = true; + for (uint32_t ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) { + uint32_t bind_index = stage_index * SG_MAX_SHADERSTAGE_UBS + ub_index; + ub_bgle_desc[stage_index][ub_index].binding = bind_index; + ub_bgle_desc[stage_index][ub_index].visibility = vis; + ub_bgle_desc[stage_index][ub_index].buffer.type = WGPUBufferBindingType_Uniform; + ub_bgle_desc[stage_index][ub_index].buffer.hasDynamicOffset = true; } } WGPUBindGroupLayoutDescriptor ub_bgl_desc; _sg_clear(&ub_bgl_desc, sizeof(ub_bgl_desc)); - ub_bgl_desc.bindingCount = SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS; - ub_bgl_desc.bindings = &ub_bglb_desc[0][0]; + ub_bgl_desc.entryCount = SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS; + ub_bgl_desc.entries = &ub_bgle_desc[0][0]; _sg.wgpu.ub.bindgroup_layout = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &ub_bgl_desc); SOKOL_ASSERT(_sg.wgpu.ub.bindgroup_layout); - WGPUBindGroupBinding ub_bgb[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS]; - _sg_clear(ub_bgb, sizeof(ub_bgb)); - for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { - for (int ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) { - int bind_index = stage_index * SG_MAX_SHADERSTAGE_UBS + ub_index; - ub_bgb[stage_index][ub_index].binding = bind_index; - ub_bgb[stage_index][ub_index].buffer = _sg.wgpu.ub.buf; + WGPUBindGroupEntry ub_bge[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS]; + _sg_clear(ub_bge, sizeof(ub_bge)); + for (uint32_t stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { + for (uint32_t ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) { + uint32_t bind_index = stage_index * SG_MAX_SHADERSTAGE_UBS + ub_index; + ub_bge[stage_index][ub_index].binding = bind_index; + ub_bge[stage_index][ub_index].buffer = _sg.wgpu.ub.buf; // FIXME FIXME FIXME FIXME: HACK FOR VALIDATION BUG IN DAWN - ub_bgb[stage_index][ub_index].size = (1<<16); + // ub_bge[stage_index][ub_index].size = (1<<16); } } WGPUBindGroupDescriptor bg_desc; _sg_clear(&bg_desc, sizeof(bg_desc)); bg_desc.layout = _sg.wgpu.ub.bindgroup_layout; - bg_desc.bindingCount = SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS; - bg_desc.bindings = &ub_bgb[0][0]; + bg_desc.entryCount = SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS; + bg_desc.entries = &ub_bge[0][0]; _sg.wgpu.ub.bindgroup = wgpuDeviceCreateBindGroup(_sg.wgpu.dev, &bg_desc); SOKOL_ASSERT(_sg.wgpu.ub.bindgroup); } @@ -12403,7 +12401,7 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_discard(void) { } } -_SOKOL_PRIVATE void _sg_wgpu_ubpool_mapped_callback(WGPUBufferMapAsyncStatus status, void* data, uint64_t data_len, void* user_data) { +_SOKOL_PRIVATE void _sg_wgpu_ubpool_mapped_callback(WGPUBufferMapAsyncStatus status, void* user_data) { if (!_sg.wgpu.valid) { return; } @@ -12412,8 +12410,9 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_mapped_callback(WGPUBufferMapAsyncStatus sta _SG_ERROR(WGPU_MAP_UNIFORM_BUFFER_FAILED); SOKOL_ASSERT(false); } - SOKOL_ASSERT(data && (data_len == _sg.wgpu.ub.num_bytes)); int index = (int)(intptr_t) user_data; + void* data = wgpuBufferGetMappedRange(_sg.wgpu.ub.stage.buf[index], 0, _sg.wgpu.ub.num_bytes); + SOKOL_ASSERT(data); SOKOL_ASSERT(index < _sg.wgpu.ub.stage.num); SOKOL_ASSERT(0 == _sg.wgpu.ub.stage.ptr[index]); _sg.wgpu.ub.stage.ptr[index] = (uint8_t*) data; @@ -12424,7 +12423,7 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_next_frame(bool first_frame) { // immediately request a new mapping for the last frame's current staging buffer if (!first_frame) { WGPUBuffer ub_src = _sg.wgpu.ub.stage.buf[_sg.wgpu.ub.stage.cur]; - wgpuBufferMapWriteAsync(ub_src, _sg_wgpu_ubpool_mapped_callback, (void*)(intptr_t)_sg.wgpu.ub.stage.cur); + wgpuBufferMapAsync(ub_src, WGPUMapMode_Write, 0, 0, _sg_wgpu_ubpool_mapped_callback, (void*)(intptr_t)_sg.wgpu.ub.stage.cur); } // rewind per-frame offsets @@ -12446,14 +12445,13 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_next_frame(bool first_frame) { WGPUBufferDescriptor desc; _sg_clear(&desc, sizeof(desc)); - desc.size = _sg.wgpu.ub.num_bytes; desc.usage = WGPUBufferUsage_CopySrc|WGPUBufferUsage_MapWrite; - WGPUCreateBufferMappedResult res = wgpuDeviceCreateBufferMapped(_sg.wgpu.dev, &desc); - _sg.wgpu.ub.stage.buf[cur] = res.buffer; - _sg.wgpu.ub.stage.ptr[cur] = (uint8_t*) res.data; + desc.size = _sg.wgpu.ub.num_bytes; + desc.mappedAtCreation = true; + _sg.wgpu.ub.stage.buf[cur] = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &desc); + _sg.wgpu.ub.stage.ptr[cur] = wgpuBufferGetMappedRange(_sg.wgpu.ub.stage.buf[cur], 0, _sg.wgpu.ub.num_bytes); SOKOL_ASSERT(_sg.wgpu.ub.stage.buf[cur]); SOKOL_ASSERT(_sg.wgpu.ub.stage.ptr[cur]); - SOKOL_ASSERT(res.dataLength == _sg.wgpu.ub.num_bytes); } _SOKOL_PRIVATE void _sg_wgpu_ubpool_flush(void) { @@ -12469,6 +12467,7 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_flush(void) { } } +/* // helper function to compute number of bytes needed in staging buffer to copy image data _SOKOL_PRIVATE uint32_t _sg_wgpu_image_data_buffer_size(const _sg_image_t* img) { uint32_t num_bytes = 0; @@ -12484,9 +12483,6 @@ _SOKOL_PRIVATE uint32_t _sg_wgpu_image_data_buffer_size(const _sg_image_t* img) return num_bytes; } -/* helper function to copy image data into a texture via a staging buffer, returns number of - bytes copied -*/ _SOKOL_PRIVATE uint32_t _sg_wgpu_copy_image_data(WGPUBuffer stg_buf, uint8_t* stg_base_ptr, uint32_t stg_base_offset, _sg_image_t* img, const sg_image_data* data) { SOKOL_ASSERT(_sg.wgpu.staging_cmd_enc); SOKOL_ASSERT(stg_buf && stg_base_ptr); @@ -12567,168 +12563,8 @@ _SOKOL_PRIVATE uint32_t _sg_wgpu_copy_image_data(WGPUBuffer stg_buf, uint8_t* st SOKOL_ASSERT(stg_offset >= stg_base_offset); return (stg_offset - stg_base_offset); } - -/* - The WGPU staging buffer implementation: - - Very similar to the uniform buffer pool, there's a pool of big - per-frame staging buffers, each must be big enough to hold - all data uploaded to dynamic resources for one frame. - - Staging buffers are created on demand and reused, because the - 'frame pipeline depth' of WGPU isn't predictable. - - The difference to the uniform buffer system is that there isn't - a 1:1 relationship for source- and destination for the - data-copy operation. There's always one staging buffer as copy-source - per frame, but many copy-destinations (regular vertex/index buffers - or images). Instead of one big copy-operation at the end of the frame, - multiple copy-operations will be written throughout the frame. */ -_SOKOL_PRIVATE void _sg_wgpu_staging_init(const sg_desc* desc) { - SOKOL_ASSERT(desc && (desc->staging_buffer_size > 0)); - _sg.wgpu.staging.num_bytes = desc->staging_buffer_size; - // there's actually nothing more to do here -} - -_SOKOL_PRIVATE void _sg_wgpu_staging_discard(void) { - for (int i = 0; i < _sg.wgpu.staging.num; i++) { - if (_sg.wgpu.staging.buf[i]) { - wgpuBufferRelease(_sg.wgpu.staging.buf[i]); - _sg.wgpu.staging.buf[i] = 0; - _sg.wgpu.staging.ptr[i] = 0; - } - } -} - -_SOKOL_PRIVATE void _sg_wgpu_staging_mapped_callback(WGPUBufferMapAsyncStatus status, void* data, uint64_t data_len, void* user_data) { - if (!_sg.wgpu.valid) { - return; - } - // FIXME: better handling for this - if (WGPUBufferMapAsyncStatus_Success != status) { - SOKOL_ASSERT("Mapping staging buffer failed!\n"); - SOKOL_ASSERT(false); - } - SOKOL_ASSERT(data && (data_len == _sg.wgpu.staging.num_bytes)); - int index = (int)(intptr_t) user_data; - SOKOL_ASSERT(index < _sg.wgpu.staging.num); - SOKOL_ASSERT(0 == _sg.wgpu.staging.ptr[index]); - _sg.wgpu.staging.ptr[index] = (uint8_t*) data; -} - -_SOKOL_PRIVATE void _sg_wgpu_staging_next_frame(bool first_frame) { - - // immediately request a new mapping for the last frame's current staging buffer - if (!first_frame) { - WGPUBuffer cur_buf = _sg.wgpu.staging.buf[_sg.wgpu.staging.cur]; - wgpuBufferMapWriteAsync(cur_buf, _sg_wgpu_staging_mapped_callback, (void*)(intptr_t)_sg.wgpu.staging.cur); - } - - // rewind staging-buffer offset - _sg.wgpu.staging.offset = 0; - - // check if mapped staging buffer is available, otherwise create one - for (int i = 0; i < _sg.wgpu.staging.num; i++) { - if (_sg.wgpu.staging.ptr[i]) { - _sg.wgpu.staging.cur = i; - return; - } - } - - // no mapped buffer available, create one - SOKOL_ASSERT(_sg.wgpu.staging.num < _SG_WGPU_STAGING_PIPELINE_SIZE); - _sg.wgpu.staging.cur = _sg.wgpu.staging.num++; - const int cur = _sg.wgpu.staging.cur; - WGPUBufferDescriptor desc; - _sg_clear(&desc, sizeof(desc)); - desc.size = _sg.wgpu.staging.num_bytes; - desc.usage = WGPUBufferUsage_CopySrc|WGPUBufferUsage_MapWrite; - WGPUCreateBufferMappedResult res = wgpuDeviceCreateBufferMapped(_sg.wgpu.dev, &desc); - _sg.wgpu.staging.buf[cur] = res.buffer; - _sg.wgpu.staging.ptr[cur] = (uint8_t*) res.data; - SOKOL_ASSERT(_sg.wgpu.staging.buf[cur]); - SOKOL_ASSERT(_sg.wgpu.staging.ptr[cur]); - SOKOL_ASSERT(res.dataLength == _sg.wgpu.staging.num_bytes); -} - -_SOKOL_PRIVATE uint32_t _sg_wgpu_staging_copy_to_buffer(WGPUBuffer dst_buf, uint32_t dst_buf_offset, const void* data, uint32_t data_num_bytes) { - /* Copy a chunk of data into the staging buffer, and record a blit-operation into - the command encoder, bump the offset for the next data chunk, return 0 if there - was not enough room in the staging buffer, return the number of actually - copied bytes on success. - - NOTE: that the number of staging bytes to be copied must be a multiple of 4. - - */ - SOKOL_ASSERT(_sg.wgpu.staging_cmd_enc); - SOKOL_ASSERT((dst_buf_offset & 3) == 0); - SOKOL_ASSERT(data_num_bytes > 0); - uint32_t copy_num_bytes = _sg_roundup(data_num_bytes, 4); - if ((_sg.wgpu.staging.offset + copy_num_bytes) >= _sg.wgpu.staging.num_bytes) { - _SG_ERROR(WGPU_STAGING_BUFFER_FULL_COPY_TO_BUFFER); - return false; - } - const int cur = _sg.wgpu.staging.cur; - SOKOL_ASSERT(_sg.wgpu.staging.ptr[cur]); - uint32_t stg_buf_offset = _sg.wgpu.staging.offset; - uint8_t* stg_ptr = _sg.wgpu.staging.ptr[cur] + stg_buf_offset; - memcpy(stg_ptr, data, data_num_bytes); - WGPUBuffer stg_buf = _sg.wgpu.staging.buf[cur]; - wgpuCommandEncoderCopyBufferToBuffer(_sg.wgpu.staging_cmd_enc, stg_buf, stg_buf_offset, dst_buf, dst_buf_offset, copy_num_bytes); - _sg.wgpu.staging.offset = stg_buf_offset + copy_num_bytes; - return copy_num_bytes; -} - -_SOKOL_PRIVATE bool _sg_wgpu_staging_copy_to_texture(_sg_image_t* img, const sg_image_data* data) { - // similar to _sg_wgpu_staging_copy_to_buffer(), but with image data instead - SOKOL_ASSERT(_sg.wgpu.staging_cmd_enc); - uint32_t num_bytes = _sg_wgpu_image_data_buffer_size(img); - if ((_sg.wgpu.staging.offset + num_bytes) >= _sg.wgpu.staging.num_bytes) { - _SG_ERROR(WGPU_STAGING_BUFFER_FULL_COPY_TO_TEXTURE); - return false; - } - const int cur = _sg.wgpu.staging.cur; - SOKOL_ASSERT(_sg.wgpu.staging.ptr[cur]); - uint32_t stg_offset = _sg.wgpu.staging.offset; - uint8_t* stg_ptr = _sg.wgpu.staging.ptr[cur]; - WGPUBuffer stg_buf = _sg.wgpu.staging.buf[cur]; - uint32_t bytes_copied = _sg_wgpu_copy_image_data(stg_buf, stg_ptr, stg_offset, img, data); - _SOKOL_UNUSED(bytes_copied); - SOKOL_ASSERT(bytes_copied == num_bytes); - _sg.wgpu.staging.offset = _sg_roundup(stg_offset + num_bytes, _SG_WGPU_STAGING_ALIGN); - return true; -} - -_SOKOL_PRIVATE void _sg_wgpu_staging_unmap(void) { - // called at end of frame before queue-submit - const int cur = _sg.wgpu.staging.cur; - SOKOL_ASSERT(_sg.wgpu.staging.ptr[cur]); - _sg.wgpu.staging.ptr[cur] = 0; - wgpuBufferUnmap(_sg.wgpu.staging.buf[cur]); -} - -_SOKOL_PRIVATE WGPUSampler _sg_wgpu_create_sampler(const sg_image_desc* img_desc) { - SOKOL_ASSERT(img_desc); - // create a new WGPU sampler - // FIXME: anisotropic filtering not supported? - WGPUSamplerDescriptor smp_desc; - _sg_clear(&smp_desc, sizeof(smp_desc)); - smp_desc.addressModeU = _sg_wgpu_sampler_addrmode(img_desc->wrap_u); - smp_desc.addressModeV = _sg_wgpu_sampler_addrmode(img_desc->wrap_v); - smp_desc.addressModeW = _sg_wgpu_sampler_addrmode(img_desc->wrap_w); - smp_desc.magFilter = _sg_wgpu_sampler_minmagfilter(img_desc->mag_filter); - smp_desc.minFilter = _sg_wgpu_sampler_minmagfilter(img_desc->min_filter); - smp_desc.mipmapFilter = _sg_wgpu_sampler_mipfilter(img_desc->min_filter); - smp_desc.lodMinClamp = img_desc->min_lod; - smp_desc.lodMaxClamp = img_desc->max_lod; - WGPUSampler smp = wgpuDeviceCreateSampler(_sg.wgpu.dev, &smp_desc); - SOKOL_ASSERT(smp); - return smp; -} - -//--- WGPU backend API functions --- _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { SOKOL_ASSERT(desc); SOKOL_ASSERT(desc->context.wgpu.device); @@ -12747,8 +12583,6 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg.wgpu.depth_stencil_view_cb = (WGPUTextureView(*)(void)) desc->context.wgpu.depth_stencil_view_cb; _sg.wgpu.depth_stencil_view_userdata_cb = (WGPUTextureView(*)(void*)) desc->context.wgpu.depth_stencil_view_userdata_cb; _sg.wgpu.user_data = desc->context.wgpu.user_data; - _sg.wgpu.queue = wgpuDeviceCreateQueue(_sg.wgpu.dev); - SOKOL_ASSERT(_sg.wgpu.queue); // setup WebGPU features and limits _sg_wgpu_init_caps(); @@ -12756,8 +12590,6 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { // setup the uniform and staging buffer pools _sg_wgpu_ubpool_init(desc); _sg_wgpu_ubpool_next_frame(true); - _sg_wgpu_staging_init(desc); - _sg_wgpu_staging_next_frame(true); // create an empty bind group for shader stages without bound images WGPUBindGroupLayoutDescriptor bgl_desc; @@ -12786,20 +12618,15 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_backend(void) { SOKOL_ASSERT(_sg.wgpu.staging_cmd_enc); _sg.wgpu.valid = false; _sg_wgpu_ubpool_discard(); - _sg_wgpu_staging_discard(); wgpuBindGroupRelease(_sg.wgpu.empty_bind_group); wgpuCommandEncoderRelease(_sg.wgpu.render_cmd_enc); _sg.wgpu.render_cmd_enc = 0; wgpuCommandEncoderRelease(_sg.wgpu.staging_cmd_enc); _sg.wgpu.staging_cmd_enc = 0; - if (_sg.wgpu.queue) { - wgpuQueueRelease(_sg.wgpu.queue); - _sg.wgpu.queue = 0; - } } _SOKOL_PRIVATE void _sg_wgpu_reset_state_cache(void) { - _SG_WARN(WGPU_RESET_STATE_CACHE_FIXME); + // FIXME } _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_context(_sg_context_t* ctx) { @@ -12815,7 +12642,7 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_context(_sg_context_t* ctx) { _SOKOL_PRIVATE void _sg_wgpu_activate_context(_sg_context_t* ctx) { (void)ctx; - _SG_WARN(WGPU_ACTIVATE_CONTEXT_FIXME); + // FIXME } _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) { From fee8b6fa86bf6148f6cfe83875a0b0acb7ec2035 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 31 Jul 2023 20:39:20 +0200 Subject: [PATCH 03/95] sokol_gfx.h: wgpu update wip --- sokol_gfx.h | 227 +++++++++++++++++++++++++++------------------------- 1 file changed, 120 insertions(+), 107 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index e283564e5..37c4c3b07 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -3119,7 +3119,6 @@ typedef enum sg_log_item { .pass_pool_size 16 .context_pool_size 16 .uniform_buffer_size 4 MB (4*1024*1024) - .staging_buffer_size 8 MB (8*1024*1024) .max_commit_listeners 1024 .disable_validation false @@ -3306,7 +3305,6 @@ typedef struct sg_desc { int pass_pool_size; int context_pool_size; int uniform_buffer_size; - int staging_buffer_size; int max_commit_listeners; bool disable_validation; // disable validation layer even in debug mode, useful for tests bool mtl_force_managed_storage_mode; // for debugging: use Metal managed storage mode for resources even with UMA @@ -4900,7 +4898,6 @@ typedef struct { int cur_width; int cur_height; WGPUCommandEncoder render_cmd_enc; - WGPUCommandEncoder staging_cmd_enc; WGPURenderPassEncoder pass_enc; WGPUBindGroup empty_bind_group; const _sg_pipeline_t* cur_pipeline; @@ -12572,7 +12569,6 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { SOKOL_ASSERT(desc->context.wgpu.resolve_view_cb || desc->context.wgpu.resolve_view_userdata_cb); SOKOL_ASSERT(desc->context.wgpu.depth_stencil_view_cb || desc->context.wgpu.depth_stencil_view_userdata_cb); SOKOL_ASSERT(desc->uniform_buffer_size > 0); - SOKOL_ASSERT(desc->staging_buffer_size > 0); _sg.backend = SG_BACKEND_WGPU; _sg.wgpu.valid = true; _sg.wgpu.dev = (WGPUDevice) desc->context.wgpu.device; @@ -12608,21 +12604,16 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg_clear(&cmd_enc_desc, sizeof(cmd_enc_desc)); _sg.wgpu.render_cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); - _sg.wgpu.staging_cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); - SOKOL_ASSERT(_sg.wgpu.staging_cmd_enc); } _SOKOL_PRIVATE void _sg_wgpu_discard_backend(void) { SOKOL_ASSERT(_sg.wgpu.valid); SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); - SOKOL_ASSERT(_sg.wgpu.staging_cmd_enc); _sg.wgpu.valid = false; _sg_wgpu_ubpool_discard(); wgpuBindGroupRelease(_sg.wgpu.empty_bind_group); wgpuCommandEncoderRelease(_sg.wgpu.render_cmd_enc); _sg.wgpu.render_cmd_enc = 0; - wgpuCommandEncoderRelease(_sg.wgpu.staging_cmd_enc); - _sg.wgpu.staging_cmd_enc = 0; } _SOKOL_PRIVATE void _sg_wgpu_reset_state_cache(void) { @@ -12647,6 +12638,7 @@ _SOKOL_PRIVATE void _sg_wgpu_activate_context(_sg_context_t* ctx) { _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) { SOKOL_ASSERT(buf && desc); +/* const bool injected = (0 != desc->wgpu_buffer); if (injected) { buf->wgpu.buf = (WGPUBuffer) desc->wgpu_buffer; @@ -12667,17 +12659,21 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_buffer(_sg_buffer_t* buf, const buf->wgpu.buf = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &wgpu_buf_desc); } } +*/ return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_buffer(_sg_buffer_t* buf) { SOKOL_ASSERT(buf); +/* WGPUBuffer wgpu_buf = buf->wgpu.buf; if (0 != wgpu_buf) { wgpuBufferRelease(wgpu_buf); } +*/ } +/* _SOKOL_PRIVATE void _sg_wgpu_init_texdesc_common(WGPUTextureDescriptor* wgpu_tex_desc, const sg_image_desc* desc) { wgpu_tex_desc->usage = WGPUTextureUsage_Sampled|WGPUTextureUsage_CopyDst; wgpu_tex_desc->dimension = _sg_wgpu_tex_dim(desc->type); @@ -12697,10 +12693,12 @@ _SOKOL_PRIVATE void _sg_wgpu_init_texdesc_common(WGPUTextureDescriptor* wgpu_tex wgpu_tex_desc->mipLevelCount = desc->num_mipmaps; wgpu_tex_desc->sampleCount = 1; } +*/ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const sg_image_desc* desc) { SOKOL_ASSERT(img && desc); SOKOL_ASSERT(_sg.wgpu.dev); +/* SOKOL_ASSERT(_sg.wgpu.staging_cmd_enc); const bool injected = (0 != desc->wgpu_texture); @@ -12713,9 +12711,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s SOKOL_ASSERT(img->cmn.type == SG_IMAGETYPE_2D); SOKOL_ASSERT(img->cmn.num_mipmaps == 1); SOKOL_ASSERT(!injected); - /* NOTE: a depth-stencil texture will never be MSAA-resolved, so there - won't be a separate MSAA- and resolve-texture - */ wgpu_tex_desc.usage = WGPUTextureUsage_OutputAttachment; wgpu_tex_desc.sampleCount = desc->sample_count; img->wgpu.tex = wgpuDeviceCreateTexture(_sg.wgpu.dev, &wgpu_tex_desc); @@ -12725,9 +12720,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s img->wgpu.tex = (WGPUTexture) desc->wgpu_texture; wgpuTextureReference(img->wgpu.tex); } else { - /* NOTE: in the MSAA-rendertarget case, both the MSAA texture *and* - the resolve texture need OutputAttachment usage - */ if (img->cmn.render_target) { wgpu_tex_desc.usage = WGPUTextureUsage_Sampled|WGPUTextureUsage_OutputAttachment; } @@ -12756,10 +12748,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s wgpu_view_desc.dimension = _sg_wgpu_tex_viewdim(desc->type); img->wgpu.tex_view = wgpuTextureCreateView(img->wgpu.tex, &wgpu_view_desc); - /* if render target and MSAA, then a separate texture in MSAA format is needed - which will be resolved into the regular texture at the end of the - offscreen-render pass - */ if (desc->render_target && is_msaa) { wgpu_tex_desc.dimension = WGPUTextureDimension_2D; wgpu_tex_desc.size.depth = 1; @@ -12775,11 +12763,13 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s img->wgpu.sampler = _sg_wgpu_create_sampler(desc); SOKOL_ASSERT(img->wgpu.sampler); } +*/ return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_image(_sg_image_t* img) { SOKOL_ASSERT(img); +/* if (img->wgpu.tex) { wgpuTextureRelease(img->wgpu.tex); img->wgpu.tex = 0; @@ -12794,6 +12784,19 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_image(_sg_image_t* img) { } // NOTE: do *not* destroy the sampler from the shared-sampler-cache img->wgpu.sampler = 0; +*/ +} + +_SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) { + SOKOL_ASSERT(smp && desc); + SOKOL_ASSERT(_sg.wgpu.dev); + // FIXME + return SG_RESOURCESTATE_VALID; +} + +_SOKOL_PRIVATE void _sg_wgpu_discard_sampler(_sg_sampler_t* smp) { + SOKOL_ASSERT(smp); + // FIXME } /* @@ -12828,6 +12831,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const SOKOL_ASSERT(desc->vs.bytecode.ptr && desc->fs.bytecode.ptr); bool success = true; +/* for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS) ? &desc->vs : &desc->fs; SOKOL_ASSERT((stage_desc->bytecode.size & 3) == 0); @@ -12875,11 +12879,13 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const wgpu_stage->bind_group_layout = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &img_bgl_desc); SOKOL_ASSERT(wgpu_stage->bind_group_layout); } +*/ return success ? SG_RESOURCESTATE_VALID : SG_RESOURCESTATE_FAILED; } _SOKOL_PRIVATE void _sg_wgpu_discard_shader(_sg_shader_t* shd) { SOKOL_ASSERT(shd); +/* for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { _sg_wgpu_shader_stage_t* wgpu_stage = &shd->wgpu.stage[stage_index]; if (wgpu_stage->module) { @@ -12891,10 +12897,12 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_shader(_sg_shader_t* shd) { wgpu_stage->bind_group_layout = 0; } } +*/ } _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) { SOKOL_ASSERT(pip && shd && desc); +/* SOKOL_ASSERT(desc->shader.id == shd->slot.id); SOKOL_ASSERT(shd->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout); SOKOL_ASSERT(shd->wgpu.stage[SG_SHADERSTAGE_FS].bind_group_layout); @@ -12924,9 +12932,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ } vb_desc[vb_idx].arrayStride = src_vb_desc->stride; vb_desc[vb_idx].stepMode = _sg_wgpu_stepmode(src_vb_desc->step_func); - /* NOTE: WebGPU has no support for vertex step rate (because that's - not supported by Core Vulkan - */ int va_idx = 0; for (int va_loc = 0; va_loc < SG_MAX_VERTEX_ATTRIBUTES; va_loc++) { const sg_vertex_attr_desc* src_va_desc = &desc->layout.attrs[va_loc]; @@ -13012,12 +13017,13 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ pip->wgpu.pip = wgpuDeviceCreateRenderPipeline(_sg.wgpu.dev, &pip_desc); SOKOL_ASSERT(0 != pip->wgpu.pip); wgpuPipelineLayoutRelease(pip_layout); - +*/ return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_pipeline(_sg_pipeline_t* pip) { SOKOL_ASSERT(pip); +/* if (pip == _sg.wgpu.cur_pipeline) { _sg.wgpu.cur_pipeline = 0; _Sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID; @@ -13026,12 +13032,13 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_pipeline(_sg_pipeline_t* pip) { wgpuRenderPipelineRelease(pip->wgpu.pip); pip->wgpu.pip = 0; } +*/ } -_SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pass(_sg_pass_t* pass, _sg_image_t** att_images, const sg_pass_desc* desc) { +_SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pass(_sg_pass_t* pass, _sg_image_t** color_images, _sg_image_t** resolve_images, _sg_image_t* ds_img, const sg_pass_desc* desc) { SOKOL_ASSERT(pass && desc); - SOKOL_ASSERT(att_images && att_images[0]); - + SOKOL_ASSERT(color_images && resolve_images); +/* // copy image pointers and create render-texture views const sg_pass_attachment_desc* att_desc; for (uint32_t i = 0; i < pass->cmn.num_color_atts; i++) { @@ -13083,11 +13090,13 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pass(_sg_pass_t* pass, _sg_imag pass->wgpu.ds_att.render_tex_view = wgpuTextureCreateView(wgpu_tex, &view_desc); SOKOL_ASSERT(pass->wgpu.ds_att.render_tex_view); } +*/ return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_pass(_sg_pass_t* pass) { SOKOL_ASSERT(pass); +/* for (uint32_t i = 0; i < pass->cmn.num_color_atts; i++) { if (pass->wgpu.color_atts[i].render_tex_view) { wgpuTextureViewRelease(pass->wgpu.color_atts[i].render_tex_view); @@ -13102,6 +13111,7 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_pass(_sg_pass_t* pass) { wgpuTextureViewRelease(pass->wgpu.ds_att.render_tex_view); pass->wgpu.ds_att.render_tex_view = 0; } +*/ } _SOKOL_PRIVATE _sg_image_t* _sg_wgpu_pass_color_image(const _sg_pass_t* pass, int index) { @@ -13110,12 +13120,41 @@ _SOKOL_PRIVATE _sg_image_t* _sg_wgpu_pass_color_image(const _sg_pass_t* pass, in return pass->wgpu.color_atts[index].image; } +_SOKOL_PRIVATE _sg_image_t* _sg_wgpu_pass_resolve_image(const _sg_pass_t* pass, int index) { + SOKOL_ASSERT(pass && (index >= 0) && (index < SG_MAX_COLOR_ATTACHMENTS)); + // NOTE: may return null + return pass->wgpu.resolve_atts[index].image; +} + _SOKOL_PRIVATE _sg_image_t* _sg_wgpu_pass_ds_image(const _sg_pass_t* pass) { // NOTE: may return null SOKOL_ASSERT(pass); return pass->wgpu.ds_att.image; } +_SOKOL_PRIVATE void _sg_wgpu_init_color_att(WGPURenderPassColorAttachment* wgpu_att, const sg_color_attachment_action* action, WGPUTextureView color_view, WGPUTextureView resolve_view) { + wgpu_att->view = color_view; + wgpu_att->resolveTarget = resolve_view; + wgpu_att->loadOp = _sg_wgpu_load_op(action->load_action); + wgpu_att->storeOp = _sg_wgpu_store_op(action->store_action); + wgpu_att->clearValue.r = action->clear_value.r; + wgpu_att->clearValue.g = action->clear_value.g; + wgpu_att->clearValue.b = action->clear_value.b; + wgpu_att->clearValue.a = action->clear_value.a; +} + +_SOKOL_PRIVATE void _sg_wgpu_init_ds_att(WGPURenderPassDepthStencilAttachment* wgpu_att, const sg_pass_action* action, WGPUTextureView view) { + wgpu_att->view = view; + wgpu_att->depthLoadOp = _sg_wgpu_load_op(action->depth.load_action); + wgpu_att->depthStoreOp = _sg_wgpu_store_op(action->depth.store_action); + wgpu_att->depthClearValue = action->depth.clear_value; + wgpu_att->depthReadOnly = false; + wgpu_att->stencilLoadOp = _sg_wgpu_load_op(action->stencil.load_action); + wgpu_att->stencilStoreOp = _sg_wgpu_store_op(action->stencil.store_action); + wgpu_att->stencilClearValue = action->stencil.clear_value; + wgpu_att->stencilReadOnly = false; +} + _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* action, int w, int h) { SOKOL_ASSERT(action); SOKOL_ASSERT(!_sg.wgpu.in_pass); @@ -13131,68 +13170,36 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* _sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID; SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); + WGPURenderPassDescriptor wgpu_pass_desc; + WGPURenderPassColorAttachment wgpu_color_att[SG_MAX_COLOR_ATTACHMENTS]; + WGPURenderPassDepthStencilAttachment wgpu_ds_att; + _sg_clear(&wgpu_pass_desc, sizeof(wgpu_pass_desc)); + _sg_clear(&wgpu_color_att, sizeof(wgpu_color_att)); + _sg_clear(&wgpu_ds_att, sizeof(wgpu_ds_att)); if (pass) { - WGPURenderPassDescriptor wgpu_pass_desc; - _sg_clear(&wgpu_pass_desc, sizeof(wgpu_pass_desc)); - WGPURenderPassColorAttachmentDescriptor wgpu_color_att_desc[SG_MAX_COLOR_ATTACHMENTS]; - _sg_clear(&wgpu_color_att_desc, sizeof(wgpu_color_att_desc)); SOKOL_ASSERT(pass->slot.state == SG_RESOURCESTATE_VALID); - for (uint32_t i = 0; i < pass->cmn.num_color_atts; i++) { - const _sg_wgpu_attachment_t* wgpu_att = &pass->wgpu.color_atts[i]; - wgpu_color_att_desc[i].loadOp = _sg_wgpu_load_op(action->colors[i].action); - wgpu_color_att_desc[i].storeOp = WGPUStoreOp_Store; - wgpu_color_att_desc[i].clearColor.r = action->colors[i].value.r; - wgpu_color_att_desc[i].clearColor.g = action->colors[i].value.g; - wgpu_color_att_desc[i].clearColor.b = action->colors[i].value.b; - wgpu_color_att_desc[i].clearColor.a = action->colors[i].value.a; - wgpu_color_att_desc[i].attachment = wgpu_att->render_tex_view; - if (wgpu_att->image->cmn.sample_count > 1) { - wgpu_color_att_desc[i].resolveTarget = wgpu_att->resolve_tex_view; - } + for (int i = 0; i < pass->cmn.num_color_atts; i++) { + _sg_wgpu_init_color_att(&wgpu_color_att[i], &action->colors[i], pass->wgpu.color_atts[i].view, pass->wgpu.resolve_atts[i].view); } - wgpu_pass_desc.colorAttachmentCount = pass->cmn.num_color_atts; - wgpu_pass_desc.colorAttachments = &wgpu_color_att_desc[0]; + wgpu_pass_desc.colorAttachmentCount = (size_t)pass->cmn.num_color_atts; + wgpu_pass_desc.colorAttachments = &wgpu_color_att[0]; if (pass->wgpu.ds_att.image) { - WGPURenderPassDepthStencilAttachmentDescriptor wgpu_ds_att_desc; - _sg_clear(&wgpu_ds_att_desc, sizeof(wgpu_ds_att_desc)); - wgpu_ds_att_desc.depthLoadOp = _sg_wgpu_load_op(action->depth.action); - wgpu_ds_att_desc.clearDepth = action->depth.value; - wgpu_ds_att_desc.stencilLoadOp = _sg_wgpu_load_op(action->stencil.action); - wgpu_ds_att_desc.clearStencil = action->stencil.value; - wgpu_ds_att_desc.attachment = pass->wgpu.ds_att.render_tex_view; - wgpu_pass_desc.depthStencilAttachment = &wgpu_ds_att_desc; - _sg.wgpu.pass_enc = wgpuCommandEncoderBeginRenderPass(_sg.wgpu.render_cmd_enc, &wgpu_pass_desc); + _sg_wgpu_init_ds_att(&wgpu_ds_att, action, pass->wgpu.ds_att.view); + wgpu_pass_desc.depthStencilAttachment = &wgpu_ds_att; } } else { - // default render pass - WGPUTextureView wgpu_render_view = _sg.wgpu.render_view_cb ? _sg.wgpu.render_view_cb() : _sg.wgpu.render_view_userdata_cb(_sg.wgpu.user_data); + WGPUTextureView wgpu_color_view = _sg.wgpu.render_view_cb ? _sg.wgpu.render_view_cb() : _sg.wgpu.render_view_userdata_cb(_sg.wgpu.user_data); WGPUTextureView wgpu_resolve_view = _sg.wgpu.resolve_view_cb ? _sg.wgpu.resolve_view_cb() : _sg.wgpu.resolve_view_userdata_cb(_sg.wgpu.user_data); WGPUTextureView wgpu_depth_stencil_view = _sg.wgpu.depth_stencil_view_cb ? _sg.wgpu.depth_stencil_view_cb() : _sg.wgpu.depth_stencil_view_userdata_cb(_sg.wgpu.user_data); - - WGPURenderPassDescriptor pass_desc; - _sg_clear(&pass_desc, sizeof(pass_desc)); - WGPURenderPassColorAttachmentDescriptor color_att_desc; - _sg_clear(&color_att_desc, sizeof(color_att_desc)); - color_att_desc.loadOp = _sg_wgpu_load_op(action->colors[0].action); - color_att_desc.clearColor.r = action->colors[0].value.r; - color_att_desc.clearColor.g = action->colors[0].value.g; - color_att_desc.clearColor.b = action->colors[0].value.b; - color_att_desc.clearColor.a = action->colors[0].value.a; - color_att_desc.attachment = wgpu_render_view; - color_att_desc.resolveTarget = wgpu_resolve_view; // null if no MSAA rendering - pass_desc.colorAttachmentCount = 1; - pass_desc.colorAttachments = &color_att_desc; - WGPURenderPassDepthStencilAttachmentDescriptor ds_att_desc; - _sg_clear(&ds_att_desc, sizeof(ds_att_desc)); - ds_att_desc.attachment = wgpu_depth_stencil_view; - SOKOL_ASSERT(0 != ds_att_desc.attachment); - ds_att_desc.depthLoadOp = _sg_wgpu_load_op(action->depth.action); - ds_att_desc.clearDepth = action->depth.value; - ds_att_desc.stencilLoadOp = _sg_wgpu_load_op(action->stencil.action); - ds_att_desc.clearStencil = action->stencil.value; - pass_desc.depthStencilAttachment = &ds_att_desc; - _sg.wgpu.pass_enc = wgpuCommandEncoderBeginRenderPass(_sg.wgpu.render_cmd_enc, &pass_desc); + _sg_wgpu_init_color_att(&wgpu_color_att[0], &action->colors[0], wgpu_color_view, wgpu_resolve_view); + wgpu_pass_desc.colorAttachmentCount = 1; + wgpu_pass_desc.colorAttachments = &wgpu_color_att[0]; + if (wgpu_depth_stencil_view) { + _sg_wgpu_init_ds_att(&wgpu_ds_att, action, wgpu_depth_stencil_view); + } + wgpu_pass_desc.depthStencilAttachment = &wgpu_ds_att; } + _sg.wgpu.pass_enc = wgpuCommandEncoderBeginRenderPass(_sg.wgpu.render_cmd_enc, &wgpu_pass_desc); SOKOL_ASSERT(_sg.wgpu.pass_enc); // initial uniform buffer binding (required even if no uniforms are set in the frame) @@ -13207,49 +13214,38 @@ _SOKOL_PRIVATE void _sg_wgpu_end_pass(void) { SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); _sg.wgpu.in_pass = false; - wgpuRenderPassEncoderEndPass(_sg.wgpu.pass_enc); + wgpuRenderPassEncoderEnd(_sg.wgpu.pass_enc); wgpuRenderPassEncoderRelease(_sg.wgpu.pass_enc); _sg.wgpu.pass_enc = 0; } _SOKOL_PRIVATE void _sg_wgpu_commit(void) { SOKOL_ASSERT(!_sg.wgpu.in_pass); - SOKOL_ASSERT(_sg.wgpu.queue); SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); - SOKOL_ASSERT(_sg.wgpu.staging_cmd_enc); // finish and submit this frame's work _sg_wgpu_ubpool_flush(); - _sg_wgpu_staging_unmap(); - - WGPUCommandBuffer cmd_bufs[2]; WGPUCommandBufferDescriptor cmd_buf_desc; _sg_clear(&cmd_buf_desc, sizeof(cmd_buf_desc)); - cmd_bufs[0] = wgpuCommandEncoderFinish(_sg.wgpu.staging_cmd_enc, &cmd_buf_desc); - SOKOL_ASSERT(cmd_bufs[0]); - wgpuCommandEncoderRelease(_sg.wgpu.staging_cmd_enc); - _sg.wgpu.staging_cmd_enc = 0; - - cmd_bufs[1] = wgpuCommandEncoderFinish(_sg.wgpu.render_cmd_enc, &cmd_buf_desc); - SOKOL_ASSERT(cmd_bufs[1]); + WGPUCommandBuffer wgpu_cmd_buf = wgpuCommandEncoderFinish(_sg.wgpu.render_cmd_enc, &cmd_buf_desc); + SOKOL_ASSERT(wgpu_cmd_buf); wgpuCommandEncoderRelease(_sg.wgpu.render_cmd_enc); _sg.wgpu.render_cmd_enc = 0; - wgpuQueueSubmit(_sg.wgpu.queue, 2, &cmd_bufs[0]); - - wgpuCommandBufferRelease(cmd_bufs[0]); - wgpuCommandBufferRelease(cmd_bufs[1]); + WGPUQueue wgpu_queue = wgpuDeviceGetQueue(_sg.wgpu.dev); + SOKOL_ASSERT(wgpu_queue); + wgpuQueueSubmit(wgpu_queue, 1, &wgpu_cmd_buf); + wgpuCommandBufferRelease(wgpu_cmd_buf); + wgpuQueueRelease(wgpu_queue); - // create a new render- and staging-command-encoders for next frame + // create a new render-command-encoder for next frame WGPUCommandEncoderDescriptor cmd_enc_desc; _sg_clear(&cmd_enc_desc, sizeof(cmd_enc_desc)); - _sg.wgpu.staging_cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); _sg.wgpu.render_cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); // grab new staging buffers for uniform- and vertex/image-updates _sg_wgpu_ubpool_next_frame(false); - _sg_wgpu_staging_next_frame(false); } _SOKOL_PRIVATE void _sg_wgpu_apply_viewport(int x, int y, int w, int h, bool origin_top_left) { @@ -13281,13 +13277,14 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_scissor_rect(int x, int y, int w, int h, bool h = _sg_max(h, 1); uint32_t sx = (uint32_t) x; - uint32_t sy = origin_top_left ? y : (_sg.wgpu.cur_height - (y + h)); - uint32_t sw = w; - uint32_t sh = h; + uint32_t sy = (uint32_t) (origin_top_left ? y : (_sg.wgpu.cur_height - (y + h))); + uint32_t sw = (uint32_t) w; + uint32_t sh = (uint32_t) h; wgpuRenderPassEncoderSetScissorRect(_sg.wgpu.pass_enc, sx, sy, sw, sh); } _SOKOL_PRIVATE void _sg_wgpu_apply_pipeline(_sg_pipeline_t* pip) { +/* SOKOL_ASSERT(pip); SOKOL_ASSERT(pip->wgpu.pip); SOKOL_ASSERT(_sg.wgpu.in_pass); @@ -13298,8 +13295,10 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_pipeline(_sg_pipeline_t* pip) { wgpuRenderPassEncoderSetPipeline(_sg.wgpu.pass_enc, pip->wgpu.pip); wgpuRenderPassEncoderSetBlendColor(_sg.wgpu.pass_enc, (WGPUColor*)&pip->cmn.blend_color); wgpuRenderPassEncoderSetStencilReference(_sg.wgpu.pass_enc, pip->wgpu.stencil_ref); +*/ } +/* _SOKOL_PRIVATE WGPUBindGroup _sg_wgpu_create_images_bindgroup(WGPUBindGroupLayout bgl, _sg_image_t** imgs, int num_imgs) { SOKOL_ASSERT(_sg.wgpu.dev); SOKOL_ASSERT(num_imgs <= _SG_WGPU_MAX_SHADERSTAGE_IMAGES); @@ -13322,15 +13321,19 @@ _SOKOL_PRIVATE WGPUBindGroup _sg_wgpu_create_images_bindgroup(WGPUBindGroupLayou SOKOL_ASSERT(bg); return bg; } +*/ _SOKOL_PRIVATE void _sg_wgpu_apply_bindings( _sg_pipeline_t* pip, _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, _sg_buffer_t* ib, int ib_offset, _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_image_t** fs_imgs, int num_fs_imgs) + _sg_image_t** fs_imgs, int num_fs_imgs, + _sg_sampler_t** vs_smps, int num_vs_smps, + _sg_sampler_t** fs_smps, int num_fs_smps) { SOKOL_ASSERT(_sg.wgpu.in_pass); +/* SOKOL_ASSERT(_sg.wgpu.pass_enc); SOKOL_ASSERT(pip->shader && (pip->cmn.shader_id.id == pip->shader->slot.id)); @@ -13369,9 +13372,11 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_bindings( } else { wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, 2, _sg.wgpu.empty_bind_group, 0, 0); } +*/ } _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) { +/* SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); SOKOL_ASSERT((_sg.wgpu.ub.offset + data->size) <= _sg.wgpu.ub.num_bytes); @@ -13393,37 +13398,46 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS, &_sg.wgpu.ub.bind_offsets[0][0]); _sg.wgpu.ub.offset = _sg_roundup(_sg.wgpu.ub.offset + data->size, _SG_WGPU_STAGING_ALIGN); +*/ } _SOKOL_PRIVATE void _sg_wgpu_draw(int base_element, int num_elements, int num_instances) { SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); - if (_sg.wgpu.draw_indexed) { - wgpuRenderPassEncoderDrawIndexed(_sg.wgpu.pass_enc, num_elements, num_instances, base_element, 0, 0); + SOKOL_ASSERT(_sg.wgpu.cur_pipeline && (_sg.wgpu.cur_pipeline->slot.id == _sg.wgpu.cur_pipeline_id.id)); + if (SG_INDEXTYPE_NONE != _sg.wgpu.cur_pipeline->cmn.index_type) { + wgpuRenderPassEncoderDrawIndexed(_sg.wgpu.pass_enc, (uint32_t)num_elements, (uint32_t)num_instances, (uint32_t)base_element, 0, 0); } else { - wgpuRenderPassEncoderDraw(_sg.wgpu.pass_enc, num_elements, num_instances, base_element, 0); + wgpuRenderPassEncoderDraw(_sg.wgpu.pass_enc, (uint32_t)num_elements, (uint32_t)num_instances, (uint32_t)base_element, 0); } } _SOKOL_PRIVATE void _sg_wgpu_update_buffer(_sg_buffer_t* buf, const sg_range* data) { +/* SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); uint32_t copied_num_bytes = _sg_wgpu_staging_copy_to_buffer(buf->wgpu.buf, 0, data->ptr, data->size); SOKOL_ASSERT(copied_num_bytes > 0); _SOKOL_UNUSED(copied_num_bytes); +*/ } _SOKOL_PRIVATE int _sg_wgpu_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { +return 0; +/* SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); _SOKOL_UNUSED(new_frame); uint32_t copied_num_bytes = _sg_wgpu_staging_copy_to_buffer(buf->wgpu.buf, buf->cmn.append_pos, data->ptr, data->size); SOKOL_ASSERT(copied_num_bytes > 0); _SOKOL_UNUSED(copied_num_bytes); return (int)copied_num_bytes; +*/ } _SOKOL_PRIVATE void _sg_wgpu_update_image(_sg_image_t* img, const sg_image_data* data) { + /* SOKOL_ASSERT(img && data); bool success = _sg_wgpu_staging_copy_to_texture(img, data); SOKOL_ASSERT(success); _SOKOL_UNUSED(success); +*/ } #endif @@ -15742,7 +15756,6 @@ _SOKOL_PRIVATE sg_desc _sg_desc_defaults(const sg_desc* desc) { res.pass_pool_size = _sg_def(res.pass_pool_size, _SG_DEFAULT_PASS_POOL_SIZE); res.context_pool_size = _sg_def(res.context_pool_size, _SG_DEFAULT_CONTEXT_POOL_SIZE); res.uniform_buffer_size = _sg_def(res.uniform_buffer_size, _SG_DEFAULT_UB_SIZE); - res.staging_buffer_size = _sg_def(res.staging_buffer_size, _SG_DEFAULT_STAGING_SIZE); res.max_commit_listeners = _sg_def(res.max_commit_listeners, _SG_DEFAULT_MAX_COMMIT_LISTENERS); return res; } From d551b7a9d3efc67e92e820ad426eeaff0fd85bbd Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 1 Aug 2023 20:16:41 +0200 Subject: [PATCH 04/95] sokol_gfx.h: wgpu update wip --- sokol_gfx.h | 85 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 37c4c3b07..5b59d6c4a 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -1649,6 +1649,7 @@ typedef enum sg_image_sample_type { SG_IMAGESAMPLETYPE_DEPTH, SG_IMAGESAMPLETYPE_SINT, SG_IMAGESAMPLETYPE_UINT, + SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT, _SG_IMAGESAMPLETYPE_NUM, _SG_IMAGESAMPLETYPE_FORCE_U32 = 0x7FFFFFFF } sg_image_sample_type; @@ -3609,6 +3610,9 @@ inline int sg_append_buffer(sg_buffer buf_id, const sg_range& data) { return sg_ #import #elif defined(SOKOL_WGPU) #include + #if defined(__EMSCRIPTEN__) + #include + #endif #elif defined(SOKOL_GLCORE33) || defined(SOKOL_GLES3) #define _SOKOL_ANY_GL (1) @@ -4878,8 +4882,8 @@ typedef struct { int num; int cur; WGPUBuffer buf[_SG_WGPU_STAGING_PIPELINE_SIZE]; // CPU-side staging buffers - uint8_t* ptr[_SG_WGPU_STAGING_PIPELINE_SIZE]; // if != 0, staging buffer currently mapped - } stage; + void* ptr[_SG_WGPU_STAGING_PIPELINE_SIZE]; // non-null if currently mapped + } staging; } _sg_wgpu_ubpool_t; // the WGPU backend state @@ -11981,6 +11985,7 @@ _SOKOL_PRIVATE WGPUTextureSampleType _sg_wgpu_tex_sample_type(sg_image_sample_ty case SG_IMAGESAMPLETYPE_DEPTH: return WGPUTextureSampleType_Depth; case SG_IMAGESAMPLETYPE_SINT: return WGPUTextureSampleType_Sint; case SG_IMAGESAMPLETYPE_UINT: return WGPUTextureSampleType_Uint; + case SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT: return WGPUTextureSampleType_UnfilterableFloat; default: SOKOL_UNREACHABLE; return WGPUTextureSampleType_Force32; } } @@ -12254,7 +12259,7 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { _sg.limits.max_image_size_cube = 8 * 1024; _sg.limits.max_image_size_3d = 2 * 1024; _sg.limits.max_image_size_array = 8 * 1024; - _sg.limits.max_image_array_layers = 2 * 1024; + _sg.limits.max_image_array_layers = 256; _sg.limits.max_vertex_attrs = SG_MAX_VERTEX_ATTRIBUTES; _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8]); @@ -12270,7 +12275,7 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8SI]); _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32UI]); _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32SI]); - _sg_pixelformat_sbr(&_sg.formats[SG_PIXELFORMAT_R32F]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32F]); _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16UI]); _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16SI]); _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16F]); @@ -12283,7 +12288,7 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { // FIXME: missing SG_PIXELFORMAT_RG11B10F _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32UI]); _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32SI]); - _sg_pixelformat_sbr(&_sg.formats[SG_PIXELFORMAT_RG32F]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32F]); _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16UI]); _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16SI]); _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16F]); @@ -12327,7 +12332,7 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_init(const sg_desc* desc) { // this is to prevent validation errors in the WebGPU implementation // if the entire buffer size is used per frame. 64 KB is the allowed // max uniform update size on NVIDIA - _sg.wgpu.ub.num_bytes = (uint32_t)desc->uniform_buffer_size + _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE; + _sg.wgpu.ub.num_bytes = (uint32_t)(desc->uniform_buffer_size + _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); WGPUBufferDescriptor ub_desc; _sg_clear(&ub_desc, sizeof(ub_desc)); @@ -12363,8 +12368,7 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_init(const sg_desc* desc) { uint32_t bind_index = stage_index * SG_MAX_SHADERSTAGE_UBS + ub_index; ub_bge[stage_index][ub_index].binding = bind_index; ub_bge[stage_index][ub_index].buffer = _sg.wgpu.ub.buf; - // FIXME FIXME FIXME FIXME: HACK FOR VALIDATION BUG IN DAWN - // ub_bge[stage_index][ub_index].size = (1<<16); + ub_bge[stage_index][ub_index].size = _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE; } } WGPUBindGroupDescriptor bg_desc; @@ -12389,11 +12393,11 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_discard(void) { wgpuBindGroupLayoutRelease(_sg.wgpu.ub.bindgroup_layout); _sg.wgpu.ub.bindgroup_layout = 0; } - for (int i = 0; i < _sg.wgpu.ub.stage.num; i++) { - if (_sg.wgpu.ub.stage.buf[i]) { - wgpuBufferRelease(_sg.wgpu.ub.stage.buf[i]); - _sg.wgpu.ub.stage.buf[i] = 0; - _sg.wgpu.ub.stage.ptr[i] = 0; + for (int i = 0; i < _sg.wgpu.ub.staging.num; i++) { + if (_sg.wgpu.ub.staging.buf[i]) { + wgpuBufferRelease(_sg.wgpu.ub.staging.buf[i]); + _sg.wgpu.ub.staging.buf[i] = 0; + _sg.wgpu.ub.staging.ptr[i] = 0; } } } @@ -12407,20 +12411,27 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_mapped_callback(WGPUBufferMapAsyncStatus sta _SG_ERROR(WGPU_MAP_UNIFORM_BUFFER_FAILED); SOKOL_ASSERT(false); } - int index = (int)(intptr_t) user_data; - void* data = wgpuBufferGetMappedRange(_sg.wgpu.ub.stage.buf[index], 0, _sg.wgpu.ub.num_bytes); - SOKOL_ASSERT(data); - SOKOL_ASSERT(index < _sg.wgpu.ub.stage.num); - SOKOL_ASSERT(0 == _sg.wgpu.ub.stage.ptr[index]); - _sg.wgpu.ub.stage.ptr[index] = (uint8_t*) data; + const int staging_index = (int)(intptr_t) user_data; + SOKOL_ASSERT(staging_index < _sg.wgpu.ub.staging.num); + SOKOL_ASSERT(0 == _sg.wgpu.ub.staging.ptr[staging_index]); + _sg.wgpu.ub.staging.ptr[staging_index] = (uint8_t*) wgpuBufferGetMappedRange(_sg.wgpu.ub.staging.buf[staging_index], 0, _sg.wgpu.ub.num_bytes); + SOKOL_ASSERT(0 != _sg.wgpu.ub.staging.ptr[staging_index]); } _SOKOL_PRIVATE void _sg_wgpu_ubpool_next_frame(bool first_frame) { // immediately request a new mapping for the last frame's current staging buffer if (!first_frame) { - WGPUBuffer ub_src = _sg.wgpu.ub.stage.buf[_sg.wgpu.ub.stage.cur]; - wgpuBufferMapAsync(ub_src, WGPUMapMode_Write, 0, 0, _sg_wgpu_ubpool_mapped_callback, (void*)(intptr_t)_sg.wgpu.ub.stage.cur); + WGPUBuffer ub_src = _sg.wgpu.ub.staging.buf[_sg.wgpu.ub.staging.cur]; + SOKOL_ASSERT(ub_src); + wgpuBufferMapAsync( + ub_src, // buffer + WGPUMapMode_Write, // mode + 0, // offset + _sg.wgpu.ub.num_bytes, // size + _sg_wgpu_ubpool_mapped_callback, // callback + (void*)(intptr_t)_sg.wgpu.ub.staging.cur // usedata + ); } // rewind per-frame offsets @@ -12428,38 +12439,38 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_next_frame(bool first_frame) { _sg_clear(&_sg.wgpu.ub.bind_offsets, sizeof(_sg.wgpu.ub.bind_offsets)); // check if a mapped staging buffer is available, otherwise create one - for (int i = 0; i < _sg.wgpu.ub.stage.num; i++) { - if (_sg.wgpu.ub.stage.ptr[i]) { - _sg.wgpu.ub.stage.cur = i; + for (int i = 0; i < _sg.wgpu.ub.staging.num; i++) { + if (_sg.wgpu.ub.staging.ptr[i]) { + _sg.wgpu.ub.staging.cur = i; return; } } // no mapped uniform buffer available, create one - SOKOL_ASSERT(_sg.wgpu.ub.stage.num < _SG_WGPU_STAGING_PIPELINE_SIZE); - _sg.wgpu.ub.stage.cur = _sg.wgpu.ub.stage.num++; - const int cur = _sg.wgpu.ub.stage.cur; + SOKOL_ASSERT(_sg.wgpu.ub.staging.num < _SG_WGPU_STAGING_PIPELINE_SIZE); + _sg.wgpu.ub.staging.cur = _sg.wgpu.ub.staging.num++; + const int cur = _sg.wgpu.ub.staging.cur; WGPUBufferDescriptor desc; _sg_clear(&desc, sizeof(desc)); - desc.usage = WGPUBufferUsage_CopySrc|WGPUBufferUsage_MapWrite; desc.size = _sg.wgpu.ub.num_bytes; + desc.usage = WGPUBufferUsage_CopySrc|WGPUBufferUsage_MapWrite; desc.mappedAtCreation = true; - _sg.wgpu.ub.stage.buf[cur] = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &desc); - _sg.wgpu.ub.stage.ptr[cur] = wgpuBufferGetMappedRange(_sg.wgpu.ub.stage.buf[cur], 0, _sg.wgpu.ub.num_bytes); - SOKOL_ASSERT(_sg.wgpu.ub.stage.buf[cur]); - SOKOL_ASSERT(_sg.wgpu.ub.stage.ptr[cur]); + _sg.wgpu.ub.staging.buf[cur] = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &desc); + _sg.wgpu.ub.staging.ptr[cur] = wgpuBufferGetMappedRange(_sg.wgpu.ub.staging.buf[cur], 0, _sg.wgpu.ub.num_bytes); + SOKOL_ASSERT(_sg.wgpu.ub.staging.buf[cur]); + SOKOL_ASSERT(_sg.wgpu.ub.staging.ptr[cur]); } _SOKOL_PRIVATE void _sg_wgpu_ubpool_flush(void) { // unmap staging buffer and copy to uniform buffer - const int cur = _sg.wgpu.ub.stage.cur; - SOKOL_ASSERT(_sg.wgpu.ub.stage.ptr[cur]); - _sg.wgpu.ub.stage.ptr[cur] = 0; - WGPUBuffer src_buf = _sg.wgpu.ub.stage.buf[cur]; + const int cur = _sg.wgpu.ub.staging.cur; + SOKOL_ASSERT(_sg.wgpu.ub.staging.ptr[cur]); + _sg.wgpu.ub.staging.ptr[cur] = 0; + WGPUBuffer src_buf = _sg.wgpu.ub.staging.buf[cur]; wgpuBufferUnmap(src_buf); if (_sg.wgpu.ub.offset > 0) { - WGPUBuffer dst_buf = _sg.wgpu.ub.buf; + const WGPUBuffer dst_buf = _sg.wgpu.ub.buf; wgpuCommandEncoderCopyBufferToBuffer(_sg.wgpu.render_cmd_enc, src_buf, 0, dst_buf, 0, _sg.wgpu.ub.offset); } } From ff67fdb6d6681c33889fc742fe9378c351124f41 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 2 Aug 2023 19:10:42 +0200 Subject: [PATCH 05/95] sokol_gfx wgpu: implement create/discard buffer --- sokol_gfx.h | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 5b59d6c4a..13a5c61a3 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2904,6 +2904,7 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_FAILED, "failed to create render pipeline state (metal)") \ _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_OUTPUT, "") \ _SG_LOGITEM_XMACRO(WGPU_MAP_UNIFORM_BUFFER_FAILED, "failed to map uniform buffer (wgpu)") \ + _SG_LOGITEM_XMACRO(WGPU_CREATE_BUFFER_FAILED, "failed to create buffer (wgpu)") \ _SG_LOGITEM_XMACRO(UNINIT_BUFFER_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in buffer uninit (must be same as for creation)") \ _SG_LOGITEM_XMACRO(UNINIT_IMAGE_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in image uninit (must be same as for creation)") \ _SG_LOGITEM_XMACRO(UNINIT_SAMPLER_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in sampler uninit (must be same as for creation)") \ @@ -5330,6 +5331,10 @@ _SOKOL_PRIVATE int _sg_roundup(int val, int round_to) { return (val+(round_to-1)) & ~(round_to-1); } +_SOKOL_PRIVATE uint64_t _sg_roundup_u64(uint64_t val, uint64_t round_to) { + return (val+(round_to-1)) & ~(round_to-1); +} + /* return row pitch for an image see ComputePitch in https://github.com/microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexUtil.cpp @@ -12649,39 +12654,44 @@ _SOKOL_PRIVATE void _sg_wgpu_activate_context(_sg_context_t* ctx) { _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_buffer(_sg_buffer_t* buf, const sg_buffer_desc* desc) { SOKOL_ASSERT(buf && desc); -/* const bool injected = (0 != desc->wgpu_buffer); if (injected) { buf->wgpu.buf = (WGPUBuffer) desc->wgpu_buffer; wgpuBufferReference(buf->wgpu.buf); } else { + // buffer mapping size must be multiple of 4, so round up buffer size (only a problem + // with index buffers containing odd number of indices) + const uint64_t wgpu_buf_size = _sg_roundup_u64((uint64_t)buf->cmn.size, 4); + const bool map_at_creation = (SG_USAGE_IMMUTABLE == buf->cmn.usage); + WGPUBufferDescriptor wgpu_buf_desc; _sg_clear(&wgpu_buf_desc, sizeof(wgpu_buf_desc)); wgpu_buf_desc.usage = _sg_wgpu_buffer_usage(buf->cmn.type, buf->cmn.usage); - wgpu_buf_desc.size = buf->cmn.size; - if (SG_USAGE_IMMUTABLE == buf->cmn.usage) { - SOKOL_ASSERT(desc->data.ptr); - WGPUCreateBufferMappedResult res = wgpuDeviceCreateBufferMapped(_sg.wgpu.dev, &wgpu_buf_desc); - buf->wgpu.buf = res.buffer; - SOKOL_ASSERT(res.data && (res.dataLength == buf->cmn.size)); - memcpy(res.data, desc->data.ptr, buf->cmn.size); - wgpuBufferUnmap(res.buffer); - } else { - buf->wgpu.buf = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &wgpu_buf_desc); + wgpu_buf_desc.size = wgpu_buf_size; + wgpu_buf_desc.mappedAtCreation = map_at_creation; + buf->wgpu.buf = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &wgpu_buf_desc); + if (0 == buf->wgpu.buf) { + _SG_ERROR(WGPU_CREATE_BUFFER_FAILED); + return SG_RESOURCESTATE_FAILED; + } + if (map_at_creation) { + SOKOL_ASSERT(desc->data.ptr && (desc->data.size > 0)); + SOKOL_ASSERT(desc->data.size <= (size_t)buf->cmn.size); + // FIXME: inefficient on WASM + void* ptr = wgpuBufferGetMappedRange(buf->wgpu.buf, 0, wgpu_buf_size); + SOKOL_ASSERT(ptr); + memcpy(ptr, desc->data.ptr, desc->data.size); + wgpuBufferUnmap(buf->wgpu.buf); } } -*/ return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_buffer(_sg_buffer_t* buf) { SOKOL_ASSERT(buf); -/* - WGPUBuffer wgpu_buf = buf->wgpu.buf; - if (0 != wgpu_buf) { - wgpuBufferRelease(wgpu_buf); + if (buf->wgpu.buf) { + wgpuBufferRelease(buf->wgpu.buf); } -*/ } /* From a05f17fe22339511c7875e1e98f77d5d1fbb4cf2 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 2 Aug 2023 19:45:17 +0200 Subject: [PATCH 06/95] sokol_gfx wgpu: initialize limits from actual wgpu limits --- sokol_gfx.h | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 13a5c61a3..508213c96 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4902,6 +4902,8 @@ typedef struct { bool use_indexed_draw; int cur_width; int cur_height; + WGPUSupportedLimits limits; + WGPUQueue queue; WGPUCommandEncoder render_cmd_enc; WGPURenderPassEncoder pass_enc; WGPUBindGroup empty_bind_group; @@ -12259,12 +12261,15 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { _sg.features.mrt_independent_blend_state = true; _sg.features.mrt_independent_write_mask = true; - // FIXME: max images size??? - _sg.limits.max_image_size_2d = 8 * 1024; - _sg.limits.max_image_size_cube = 8 * 1024; - _sg.limits.max_image_size_3d = 2 * 1024; - _sg.limits.max_image_size_array = 8 * 1024; - _sg.limits.max_image_array_layers = 256; + bool success = wgpuDeviceGetLimits(_sg.wgpu.dev, &_sg.wgpu.limits); + SOKOL_ASSERT(success); + + const WGPULimits* l = &_sg.wgpu.limits.limits; + _sg.limits.max_image_size_2d = (int) l->maxTextureDimension2D; + _sg.limits.max_image_size_cube = (int) l->maxTextureDimension2D; // not a bug, see: https://github.com/gpuweb/gpuweb/issues/1327 + _sg.limits.max_image_size_3d = (int) l->maxTextureDimension3D; + _sg.limits.max_image_size_array = (int) l->maxTextureDimension2D; + _sg.limits.max_image_array_layers = (int) l->maxTextureArrayLayers; _sg.limits.max_vertex_attrs = SG_MAX_VERTEX_ATTRIBUTES; _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8]); @@ -12595,6 +12600,8 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg.wgpu.depth_stencil_view_cb = (WGPUTextureView(*)(void)) desc->context.wgpu.depth_stencil_view_cb; _sg.wgpu.depth_stencil_view_userdata_cb = (WGPUTextureView(*)(void*)) desc->context.wgpu.depth_stencil_view_userdata_cb; _sg.wgpu.user_data = desc->context.wgpu.user_data; + _sg.wgpu.queue = wgpuDeviceGetQueue(_sg.wgpu.dev); + SOKOL_ASSERT(_sg.wgpu.queue); // setup WebGPU features and limits _sg_wgpu_init_caps(); @@ -12627,9 +12634,10 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_backend(void) { SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); _sg.wgpu.valid = false; _sg_wgpu_ubpool_discard(); - wgpuBindGroupRelease(_sg.wgpu.empty_bind_group); - wgpuCommandEncoderRelease(_sg.wgpu.render_cmd_enc); - _sg.wgpu.render_cmd_enc = 0; + wgpuBindGroupRelease(_sg.wgpu.empty_bind_group); _sg.wgpu.empty_bind_group = 0; + wgpuCommandEncoderRelease(_sg.wgpu.render_cmd_enc); _sg.wgpu.render_cmd_enc = 0; + wgpuQueueRelease(_sg.wgpu.queue); _sg.wgpu.queue = 0; + } _SOKOL_PRIVATE void _sg_wgpu_reset_state_cache(void) { @@ -12669,6 +12677,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_buffer(_sg_buffer_t* buf, const wgpu_buf_desc.usage = _sg_wgpu_buffer_usage(buf->cmn.type, buf->cmn.usage); wgpu_buf_desc.size = wgpu_buf_size; wgpu_buf_desc.mappedAtCreation = map_at_creation; + wgpu_buf_desc.label = desc->label; buf->wgpu.buf = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &wgpu_buf_desc); if (0 == buf->wgpu.buf) { _SG_ERROR(WGPU_CREATE_BUFFER_FAILED); @@ -12849,7 +12858,7 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_sampler(_sg_sampler_t* smp) { */ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) { SOKOL_ASSERT(shd && desc); - SOKOL_ASSERT(desc->vs.bytecode.ptr && desc->fs.bytecode.ptr); + SOKOL_ASSERT(desc->vs.source && desc->fs.source); bool success = true; /* @@ -13254,11 +13263,8 @@ _SOKOL_PRIVATE void _sg_wgpu_commit(void) { wgpuCommandEncoderRelease(_sg.wgpu.render_cmd_enc); _sg.wgpu.render_cmd_enc = 0; - WGPUQueue wgpu_queue = wgpuDeviceGetQueue(_sg.wgpu.dev); - SOKOL_ASSERT(wgpu_queue); - wgpuQueueSubmit(wgpu_queue, 1, &wgpu_cmd_buf); + wgpuQueueSubmit(_sg.wgpu.queue, 1, &wgpu_cmd_buf); wgpuCommandBufferRelease(wgpu_cmd_buf); - wgpuQueueRelease(wgpu_queue); // create a new render-command-encoder for next frame WGPUCommandEncoderDescriptor cmd_enc_desc; @@ -14580,18 +14586,14 @@ _SOKOL_PRIVATE bool _sg_validate_shader_desc(const sg_shader_desc* desc) { #if defined(SOKOL_D3D11) _SG_VALIDATE(0 != desc->attrs[0].sem_name, VALIDATE_SHADERDESC_ATTR_SEMANTICS); #endif - #if defined(SOKOL_GLCORE33) || defined(SOKOL_GLES3) - // on GL, must provide shader source code + #if defined(SOKOL_GLCORE33) || defined(SOKOL_GLES3) || defined(SOKOL_WGPU) + // on GL or WebGPU, must provide shader source code _SG_VALIDATE(0 != desc->vs.source, VALIDATE_SHADERDESC_SOURCE); _SG_VALIDATE(0 != desc->fs.source, VALIDATE_SHADERDESC_SOURCE); #elif defined(SOKOL_METAL) || defined(SOKOL_D3D11) // on Metal or D3D11, must provide shader source code or byte code _SG_VALIDATE((0 != desc->vs.source)||(0 != desc->vs.bytecode.ptr), VALIDATE_SHADERDESC_SOURCE_OR_BYTECODE); _SG_VALIDATE((0 != desc->fs.source)||(0 != desc->fs.bytecode.ptr), VALIDATE_SHADERDESC_SOURCE_OR_BYTECODE); - #elif defined(SOKOL_WGPU) - // on WGPU byte code must be provided - _SG_VALIDATE((0 != desc->vs.bytecode.ptr), VALIDATE_SHADERDESC_BYTECODE); - _SG_VALIDATE((0 != desc->fs.bytecode.ptr), VALIDATE_SHADERDESC_BYTECODE); #else // Dummy Backend, don't require source or bytecode #endif From 30824ccfc0b3054aad8ae3f903c3cd62752c88fe Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 3 Aug 2023 19:33:18 +0200 Subject: [PATCH 07/95] sokol_gfx wgpu: create shader module and bind group --- sokol_gfx.h | 110 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 42 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 508213c96..3ee670974 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2904,7 +2904,11 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_FAILED, "failed to create render pipeline state (metal)") \ _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_OUTPUT, "") \ _SG_LOGITEM_XMACRO(WGPU_MAP_UNIFORM_BUFFER_FAILED, "failed to map uniform buffer (wgpu)") \ - _SG_LOGITEM_XMACRO(WGPU_CREATE_BUFFER_FAILED, "failed to create buffer (wgpu)") \ + _SG_LOGITEM_XMACRO(WGPU_CREATE_BUFFER_FAILED, "wgpuDeviceCreateBuffer() failed") \ + _SG_LOGITEM_XMACRO(WGPU_CREATE_SHADER_MODULE_FAILED, "wgpuDeviceCreateShaderModule failed") \ + _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_IMAGES, "shader uses too many sampled images on shader stage (wgpu)") \ + _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_SAMPLERS, "shader uses too many samplers on shader stage (wgpu)") \ + _SG_LOGITEM_XMACRO(WGPU_SHADER_CREATE_BINDGROUP_LAYOUT_FAILED, "wgpuDeviceCreateBindGroupLayout for shader stage failed") \ _SG_LOGITEM_XMACRO(UNINIT_BUFFER_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in buffer uninit (must be same as for creation)") \ _SG_LOGITEM_XMACRO(UNINIT_IMAGE_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in image uninit (must be same as for creation)") \ _SG_LOGITEM_XMACRO(UNINIT_SAMPLER_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in sampler uninit (must be same as for creation)") \ @@ -11976,7 +11980,7 @@ _SOKOL_PRIVATE WGPUStoreOp _sg_wgpu_store_op(sg_store_action a) { } } -_SOKOL_PRIVATE WGPUTextureViewDimension _sg_wgpu_tex_viewdim(sg_image_type t) { +_SOKOL_PRIVATE WGPUTextureViewDimension _sg_wgpu_tex_view_dimension(sg_image_type t) { switch (t) { case SG_IMAGETYPE_2D: return WGPUTextureViewDimension_2D; case SG_IMAGETYPE_CUBE: return WGPUTextureViewDimension_Cube; @@ -12005,6 +12009,15 @@ _SOKOL_PRIVATE WGPUTextureDimension _sg_wgpu_tex_dim(sg_image_type t) { } } +_SOKOL_PRIVATE WGPUSamplerBindingType _sg_wgpu_sampler_binding_type(sg_sampler_type t) { + switch (t) { + // FIXME: NonFiltering + case SG_SAMPLERTYPE_SAMPLE: return WGPUSamplerBindingType_Filtering; + case SG_SAMPLERTYPE_COMPARE: return WGPUSamplerBindingType_Comparison; + default: SOKOL_UNREACHABLE; return WGPUSamplerBindingType_Force32; + } +} + _SOKOL_PRIVATE WGPUAddressMode _sg_wgpu_sampler_addrmode(sg_wrap m) { switch (m) { case SG_WRAP_REPEAT: @@ -12860,62 +12873,76 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const SOKOL_ASSERT(shd && desc); SOKOL_ASSERT(desc->vs.source && desc->fs.source); - bool success = true; -/* for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS) ? &desc->vs : &desc->fs; - SOKOL_ASSERT((stage_desc->bytecode.size & 3) == 0); _sg_shader_stage_t* cmn_stage = &shd->cmn.stage[stage_index]; _sg_wgpu_shader_stage_t* wgpu_stage = &shd->wgpu.stage[stage_index]; - _sg_strcpy(&wgpu_stage->entry, stage_desc->entry); + + WGPUShaderModuleWGSLDescriptor wgpu_shdmod_wgsl_desc; + _sg_clear(&wgpu_shdmod_wgsl_desc, sizeof(wgpu_shdmod_wgsl_desc)); + wgpu_shdmod_wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; + wgpu_shdmod_wgsl_desc.code = stage_desc->source; + WGPUShaderModuleDescriptor wgpu_shdmod_desc; _sg_clear(&wgpu_shdmod_desc, sizeof(wgpu_shdmod_desc)); - wgpu_shdmod_desc.codeSize = stage_desc->bytecode.size >> 2; - wgpu_shdmod_desc.code = (const uint32_t*) stage_desc->bytecode.ptr; + wgpu_shdmod_desc.nextInChain = &wgpu_shdmod_wgsl_desc.chain; + wgpu_shdmod_desc.label = desc->label; + wgpu_stage->module = wgpuDeviceCreateShaderModule(_sg.wgpu.dev, &wgpu_shdmod_desc); if (0 == wgpu_stage->module) { - success = false; + _SG_ERROR(WGPU_CREATE_SHADER_MODULE_FAILED); + return SG_RESOURCESTATE_FAILED; } - // create image/sampler bind group for the shader stage - WGPUShaderStage vis = (stage_index == SG_SHADERSTAGE_VS) ? WGPUShaderStage_Vertex : WGPUShaderStage_Fragment; - int num_imgs = cmn_stage->num_images; - if (num_imgs > _SG_WGPU_MAX_SHADERSTAGE_IMAGES) { - num_imgs = _SG_WGPU_MAX_SHADERSTAGE_IMAGES; - } - WGPUBindGroupLayoutBinding bglb_desc[_SG_WGPU_MAX_SHADERSTAGE_IMAGES * 2]; - _sg_clear(bglb_desc, sizeof(bglb_desc)); - for (int img_index = 0; img_index < num_imgs; img_index++) { - // texture- and sampler-bindings - WGPUBindGroupLayoutBinding* tex_desc = &bglb_desc[img_index*2 + 0]; - WGPUBindGroupLayoutBinding* smp_desc = &bglb_desc[img_index*2 + 1]; - - tex_desc->binding = img_index; - tex_desc->visibility = vis; - tex_desc->type = WGPUBindingType_SampledTexture; - tex_desc->textureDimension = _sg_wgpu_tex_viewdim(cmn_stage->images[img_index].image_type); - tex_desc->textureComponentType = _sg_wgpu_tex_comptype(cmn_stage->images[img_index].sampler_type); - - smp_desc->binding = img_index + _SG_WGPU_MAX_SHADERSTAGE_IMAGES; - smp_desc->visibility = vis; - smp_desc->type = WGPUBindingType_Sampler; - } - WGPUBindGroupLayoutDescriptor img_bgl_desc; - _sg_clear(&img_bgl_desc, sizeof(img_bgl_desc)); - img_bgl_desc.bindingCount = num_imgs * 2; - img_bgl_desc.bindings = &bglb_desc[0]; - wgpu_stage->bind_group_layout = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &img_bgl_desc); - SOKOL_ASSERT(wgpu_stage->bind_group_layout); + // create image/sampler bind group + WGPUShaderStage wgpu_shader_stage = (stage_index == SG_SHADERSTAGE_VS) ? WGPUShaderStage_Vertex : WGPUShaderStage_Fragment; + const int num_images = cmn_stage->num_images; + if (num_images > (int)_sg.wgpu.limits.limits.maxSampledTexturesPerShaderStage) { + _SG_ERROR(WGPU_SHADER_TOO_MANY_IMAGES); + return SG_RESOURCESTATE_FAILED; + } + const int num_samplers = cmn_stage->num_samplers; + if (num_samplers > (int)_sg.wgpu.limits.limits.maxSamplersPerShaderStage) { + _SG_ERROR(WGPU_SHADER_TOO_MANY_SAMPLERS); + return SG_RESOURCESTATE_FAILED; + } + WGPUBindGroupLayoutEntry wgpu_bgl_entries[SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS]; + _sg_clear(wgpu_bgl_entries, sizeof(wgpu_bgl_entries)); + for (int img_index = 0; img_index < num_images; img_index++) { + const int bind_index = img_index; + WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bind_index]; + const sg_shader_image_desc* img_desc = &stage_desc->images[img_index]; + wgpu_bgl_entry->binding = (uint32_t)bind_index; + wgpu_bgl_entry->visibility = wgpu_shader_stage; + wgpu_bgl_entry->texture.viewDimension = _sg_wgpu_tex_view_dimension(img_desc->image_type); + wgpu_bgl_entry->texture.sampleType = _sg_wgpu_tex_sample_type(img_desc->sample_type); + wgpu_bgl_entry->texture.multisampled = img_desc->multisampled; + } + for (int smp_index = 0; smp_index < num_samplers; smp_index++) { + const int bind_index = smp_index; + WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bind_index]; + const sg_shader_sampler_desc* smp_desc = &stage_desc->samplers[smp_index]; + wgpu_bgl_entry->binding = (uint32_t)bind_index; + wgpu_bgl_entry->visibility = wgpu_shader_stage; + wgpu_bgl_entry->sampler.type = _sg_wgpu_sampler_binding_type(smp_desc->sampler_type); + } + WGPUBindGroupLayoutDescriptor wgpu_bgl_desc; + _sg_clear(&wgpu_bgl_desc, sizeof(wgpu_bgl_desc)); + wgpu_bgl_desc.entryCount = (size_t)(num_images + num_samplers); + wgpu_bgl_desc.entries = &wgpu_bgl_entries[0]; + wgpu_stage->bind_group_layout = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &wgpu_bgl_desc); + if (wgpu_stage->bind_group_layout == 0) { + _SG_ERROR(WGPU_SHADER_CREATE_BINDGROUP_LAYOUT_FAILED); + return SG_RESOURCESTATE_FAILED; + } } -*/ - return success ? SG_RESOURCESTATE_VALID : SG_RESOURCESTATE_FAILED; + return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_shader(_sg_shader_t* shd) { SOKOL_ASSERT(shd); -/* for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { _sg_wgpu_shader_stage_t* wgpu_stage = &shd->wgpu.stage[stage_index]; if (wgpu_stage->module) { @@ -12927,7 +12954,6 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_shader(_sg_shader_t* shd) { wgpu_stage->bind_group_layout = 0; } } -*/ } _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) { From ab4525377a92c29e9c8745527deccd4b0893235e Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 7 Aug 2023 18:16:37 +0200 Subject: [PATCH 08/95] sokol_gfx wgpu: create/destroy render pipeline --- sokol_gfx.h | 232 +++++++++++++++++++++++++++------------------------- 1 file changed, 122 insertions(+), 110 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 3ee670974..d2f42a84d 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4798,6 +4798,7 @@ typedef struct { #define _SG_WGPU_ROWPITCH_ALIGN (256) #define _SG_WGPU_MAX_SHADERSTAGE_IMAGES (8) #define _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE (1<<16) +#define _SG_WGPU_NUM_BINDGROUPS (3) // 1: uniforms, 2: vertex stage images & samplers, 3: fragment stage images & samplers typedef struct { _sg_slot_t slot; @@ -4848,7 +4849,7 @@ typedef struct { _sg_shader_t* shader; struct { WGPURenderPipeline pip; - uint32_t stencil_ref; + WGPUColor blend_color; } wgpu; } _sg_wgpu_pipeline_t; typedef _sg_wgpu_pipeline_t _sg_pipeline_t; @@ -12063,6 +12064,16 @@ _SOKOL_PRIVATE WGPUIndexFormat _sg_wgpu_indexformat(sg_index_type t) { return (t == SG_INDEXTYPE_UINT16) ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32; } +_SOKOL_PRIVATE WGPUIndexFormat _sg_wgpu_stripindexformat(sg_primitive_type prim_type, sg_index_type idx_type) { + if (idx_type == SG_INDEXTYPE_NONE) { + return WGPUIndexFormat_Undefined; + } else if ((prim_type == SG_PRIMITIVETYPE_LINE_STRIP) || (prim_type == SG_PRIMITIVETYPE_TRIANGLE_STRIP)) { + return _sg_wgpu_indexformat(idx_type); + } else { + return WGPUIndexFormat_Undefined; + } +} + _SOKOL_PRIVATE WGPUVertexStepMode _sg_wgpu_stepmode(sg_vertex_step s) { return (s == SG_VERTEXSTEP_PER_VERTEX) ? WGPUVertexStepMode_Vertex : WGPUVertexStepMode_Instance; } @@ -12958,137 +12969,140 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_shader(_sg_shader_t* shd) { _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) { SOKOL_ASSERT(pip && shd && desc); -/* SOKOL_ASSERT(desc->shader.id == shd->slot.id); SOKOL_ASSERT(shd->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout); SOKOL_ASSERT(shd->wgpu.stage[SG_SHADERSTAGE_FS].bind_group_layout); pip->shader = shd; - pip->wgpu.stencil_ref = (uint32_t) desc->stencil.ref; - WGPUBindGroupLayout pip_bgl[3] = { + pip->wgpu.blend_color.r = (double) desc->blend_color.r; + pip->wgpu.blend_color.g = (double) desc->blend_color.g; + pip->wgpu.blend_color.b = (double) desc->blend_color.b; + pip->wgpu.blend_color.a = (double) desc->blend_color.a; + + // - 1 bindgroup for uniform block, + // - 1 bindgroup for vertex shader resources + // - 1 bindgroup for fragment shader resources + WGPUBindGroupLayout wgpu_bgl[_SG_WGPU_NUM_BINDGROUPS] = { _sg.wgpu.ub.bindgroup_layout, shd->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout, shd->wgpu.stage[SG_SHADERSTAGE_FS].bind_group_layout }; - WGPUPipelineLayoutDescriptor pl_desc; - _sg_clear(&pl_desc, sizeof(pl_desc)); - pl_desc.bindGroupLayoutCount = 3; - pl_desc.bindGroupLayouts = &pip_bgl[0]; - WGPUPipelineLayout pip_layout = wgpuDeviceCreatePipelineLayout(_sg.wgpu.dev, &pl_desc); - - WGPUVertexBufferLayoutDescriptor vb_desc[SG_MAX_VERTEX_BUFFERS]; - _sg_clear(&vb_desc, sizeof(vb_desc)); - WGPUVertexAttributeDescriptor va_desc[SG_MAX_VERTEX_BUFFERS][SG_MAX_VERTEX_ATTRIBUTES]; - _sg_clear(&va_desc, sizeof(va_desc)); - int vb_idx = 0; - for (; vb_idx < SG_MAX_VERTEX_BUFFERS; vb_idx++) { - const sg_buffer_layout_desc* src_vb_desc = &desc->layout.buffers[vb_idx]; - if (0 == src_vb_desc->stride) { + WGPUPipelineLayoutDescriptor wgpu_pl_desc; + _sg_clear(&wgpu_pl_desc, sizeof(wgpu_pl_desc)); + wgpu_pl_desc.bindGroupLayoutCount = _SG_WGPU_NUM_BINDGROUPS; + wgpu_pl_desc.bindGroupLayouts = &wgpu_bgl[0]; + const WGPUPipelineLayout wgpu_pip_layout = wgpuDeviceCreatePipelineLayout(_sg.wgpu.dev, &wgpu_pl_desc); + SOKOL_ASSERT(wgpu_pip_layout); + + WGPUVertexBufferLayout wgpu_vb_layouts[SG_MAX_VERTEX_BUFFERS]; + _sg_clear(wgpu_vb_layouts, sizeof(wgpu_vb_layouts)); + WGPUVertexAttribute wgpu_vtx_attrs[SG_MAX_VERTEX_BUFFERS][SG_MAX_VERTEX_ATTRIBUTES]; + _sg_clear(wgpu_vtx_attrs, sizeof(wgpu_vtx_attrs)); + int wgpu_vb_num = 0; + for (int vb_idx = 0; vb_idx < SG_MAX_VERTEX_BUFFERS; vb_idx++, wgpu_vb_num++) { + const sg_vertex_buffer_layout_state* vbl_state = &desc->layout.buffers[vb_idx]; + if (0 == vbl_state->stride) { break; } - vb_desc[vb_idx].arrayStride = src_vb_desc->stride; - vb_desc[vb_idx].stepMode = _sg_wgpu_stepmode(src_vb_desc->step_func); - int va_idx = 0; - for (int va_loc = 0; va_loc < SG_MAX_VERTEX_ATTRIBUTES; va_loc++) { - const sg_vertex_attr_desc* src_va_desc = &desc->layout.attrs[va_loc]; - if (SG_VERTEXFORMAT_INVALID == src_va_desc->format) { - break; - } - pip->cmn.vertex_buffer_layout_active[src_va_desc->buffer_index] = true; - if (vb_idx == src_va_desc->buffer_index) { - va_desc[vb_idx][va_idx].format = _sg_wgpu_vertexformat(src_va_desc->format); - va_desc[vb_idx][va_idx].offset = src_va_desc->offset; - va_desc[vb_idx][va_idx].shaderLocation = va_loc; - va_idx++; - } - } - vb_desc[vb_idx].attributeCount = va_idx; - vb_desc[vb_idx].attributes = &va_desc[vb_idx][0]; + wgpu_vb_layouts[vb_idx].arrayStride = (uint64_t)vbl_state->stride; + wgpu_vb_layouts[vb_idx].stepMode = _sg_wgpu_stepmode(vbl_state->step_func); + wgpu_vb_layouts[vb_idx].attributes = &wgpu_vtx_attrs[vb_idx][0]; } - WGPUVertexStateDescriptor vx_state_desc; - _sg_clear(&vx_state_desc, sizeof(vx_state_desc)); - vx_state_desc.indexFormat = _sg_wgpu_indexformat(desc->index_type); - vx_state_desc.vertexBufferCount = vb_idx; - vx_state_desc.vertexBuffers = vb_desc; - - WGPURasterizationStateDescriptor rs_desc; - _sg_clear(&rs_desc, sizeof(rs_desc)); - rs_desc.frontFace = _sg_wgpu_frontface(desc->face_winding); - rs_desc.cullMode = _sg_wgpu_cullmode(desc->cull_mode); - rs_desc.depthBias = (int32_t) desc->depth.bias; - rs_desc.depthBiasClamp = desc->depth.bias_clamp; - rs_desc.depthBiasSlopeScale = desc->depth.bias_slope_scale; - - WGPUDepthStencilStateDescriptor ds_desc; - _sg_clear(&ds_desc, sizeof(ds_desc)); - ds_desc.format = _sg_wgpu_textureformat(desc->depth.pixel_format); - ds_desc.depthWriteEnabled = desc->depth.write_enabled; - ds_desc.depthCompare = _sg_wgpu_comparefunc(desc->depth.compare); - ds_desc.stencilReadMask = desc->stencil.read_mask; - ds_desc.stencilWriteMask = desc->stencil.write_mask; - ds_desc.stencilFront.compare = _sg_wgpu_comparefunc(desc->stencil.front.compare); - ds_desc.stencilFront.failOp = _sg_wgpu_stencilop(desc->stencil.front.fail_op); - ds_desc.stencilFront.depthFailOp = _sg_wgpu_stencilop(desc->stencil.front.depth_fail_op); - ds_desc.stencilFront.passOp = _sg_wgpu_stencilop(desc->stencil.front.pass_op); - ds_desc.stencilBack.compare = _sg_wgpu_comparefunc(desc->stencil.back.compare); - ds_desc.stencilBack.failOp = _sg_wgpu_stencilop(desc->stencil.back.fail_op); - ds_desc.stencilBack.depthFailOp = _sg_wgpu_stencilop(desc->stencil.back.depth_fail_op); - ds_desc.stencilBack.passOp = _sg_wgpu_stencilop(desc->stencil.back.pass_op); - - WGPUProgrammableStageDescriptor fs_desc; - _sg_clear(&fs_desc, sizeof(fs_desc)); - fs_desc.module = shd->wgpu.stage[SG_SHADERSTAGE_FS].module; - fs_desc.entryPoint = shd->wgpu.stage[SG_SHADERSTAGE_VS].entry.buf; - - WGPUColorStateDescriptor cs_desc[SG_MAX_COLOR_ATTACHMENTS]; - _sg_clear(cs_desc, sizeof(cs_desc)); - for (uint32_t i = 0; i < desc->color_count; i++) { - SOKOL_ASSERT(i < SG_MAX_COLOR_ATTACHMENTS); - cs_desc[i].format = _sg_wgpu_textureformat(desc->colors[i].pixel_format); - cs_desc[i].colorBlend.operation = _sg_wgpu_blendop(desc->colors[i].blend.op_rgb); - cs_desc[i].colorBlend.srcFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.src_factor_rgb); - cs_desc[i].colorBlend.dstFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.dst_factor_rgb); - cs_desc[i].alphaBlend.operation = _sg_wgpu_blendop(desc->colors[i].blend.op_alpha); - cs_desc[i].alphaBlend.srcFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.src_factor_alpha); - cs_desc[i].alphaBlend.dstFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.dst_factor_alpha); - cs_desc[i].writeMask = _sg_wgpu_colorwritemask(desc->colors[i].write_mask); - } - - WGPURenderPipelineDescriptor pip_desc; - _sg_clear(&pip_desc, sizeof(pip_desc)); - pip_desc.layout = pip_layout; - pip_desc.vertexStage.module = shd->wgpu.stage[SG_SHADERSTAGE_VS].module; - pip_desc.vertexStage.entryPoint = shd->wgpu.stage[SG_SHADERSTAGE_VS].entry.buf; - pip_desc.fragmentStage = &fs_desc; - pip_desc.vertexState = &vx_state_desc; - pip_desc.primitiveTopology = _sg_wgpu_topology(desc->primitive_type); - pip_desc.rasterizationState = &rs_desc; - pip_desc.sampleCount = desc->sample_count; + for (int va_idx = 0; va_idx < SG_MAX_VERTEX_ATTRIBUTES; va_idx++) { + const sg_vertex_attr_state* va_state = &desc->layout.attrs[va_idx]; + if (SG_VERTEXFORMAT_INVALID == va_state->format) { + break; + } + const int vb_idx = va_state->buffer_index; + SOKOL_ASSERT(vb_idx < SG_MAX_VERTEX_BUFFERS); + pip->cmn.vertex_buffer_layout_active[vb_idx] = true; + const uint32_t wgpu_attr_idx = wgpu_vb_layouts[vb_idx].attributeCount; + wgpu_vb_layouts[vb_idx].attributeCount += 1; + wgpu_vtx_attrs[vb_idx][wgpu_attr_idx].format = _sg_wgpu_vertexformat(va_state->format); + wgpu_vtx_attrs[vb_idx][wgpu_attr_idx].offset = (uint64_t)va_state->offset; + wgpu_vtx_attrs[vb_idx][wgpu_attr_idx].shaderLocation = (uint32_t)va_idx; + } + + WGPURenderPipelineDescriptor wgpu_pip_desc; + _sg_clear(&wgpu_pip_desc, sizeof(wgpu_pip_desc)); + wgpu_pip_desc.label = desc->label; + wgpu_pip_desc.layout = wgpu_pip_layout; + wgpu_pip_desc.vertex.module = shd->wgpu.stage[SG_SHADERSTAGE_VS].module; + wgpu_pip_desc.vertex.entryPoint = shd->wgpu.stage[SG_SHADERSTAGE_VS].entry.buf; + wgpu_pip_desc.vertex.bufferCount = (size_t)wgpu_vb_num; + wgpu_pip_desc.vertex.buffers = &wgpu_vb_layouts[0]; + wgpu_pip_desc.primitive.topology = _sg_wgpu_topology(desc->primitive_type); + wgpu_pip_desc.primitive.stripIndexFormat = _sg_wgpu_stripindexformat(desc->primitive_type, desc->index_type); + wgpu_pip_desc.primitive.frontFace = _sg_wgpu_frontface(desc->face_winding); + wgpu_pip_desc.primitive.cullMode = _sg_wgpu_cullmode(desc->cull_mode); if (SG_PIXELFORMAT_NONE != desc->depth.pixel_format) { - pip_desc.depthStencilState = &ds_desc; + WGPUDepthStencilState wgpu_ds_state; + _sg_clear(&wgpu_ds_state, sizeof(wgpu_ds_state)); + wgpu_ds_state.format = _sg_wgpu_textureformat(desc->depth.pixel_format); + wgpu_ds_state.depthWriteEnabled = desc->depth.write_enabled; + wgpu_ds_state.depthCompare = _sg_wgpu_comparefunc(desc->depth.compare); + wgpu_ds_state.stencilFront.compare = _sg_wgpu_comparefunc(desc->stencil.front.compare); + wgpu_ds_state.stencilFront.failOp = _sg_wgpu_stencilop(desc->stencil.front.fail_op); + wgpu_ds_state.stencilFront.depthFailOp = _sg_wgpu_stencilop(desc->stencil.front.depth_fail_op); + wgpu_ds_state.stencilFront.passOp = _sg_wgpu_stencilop(desc->stencil.front.pass_op); + wgpu_ds_state.stencilBack.compare = _sg_wgpu_comparefunc(desc->stencil.back.compare); + wgpu_ds_state.stencilBack.failOp = _sg_wgpu_stencilop(desc->stencil.back.fail_op); + wgpu_ds_state.stencilBack.depthFailOp = _sg_wgpu_stencilop(desc->stencil.back.depth_fail_op); + wgpu_ds_state.stencilBack.passOp = _sg_wgpu_stencilop(desc->stencil.back.pass_op); + wgpu_ds_state.stencilReadMask = desc->stencil.read_mask; + wgpu_ds_state.stencilWriteMask = desc->stencil.write_mask; + wgpu_ds_state.depthBias = (int32_t)desc->depth.bias; + wgpu_ds_state.depthBiasSlopeScale = desc->depth.bias_slope_scale; + wgpu_ds_state.depthBiasClamp = desc->depth.bias_clamp; + wgpu_pip_desc.depthStencil = &wgpu_ds_state; + } + wgpu_pip_desc.multisample.count = (uint32_t)desc->sample_count; + wgpu_pip_desc.multisample.mask = 0xFFFFFFFF; + wgpu_pip_desc.multisample.alphaToCoverageEnabled = desc->alpha_to_coverage_enabled; + if (desc->color_count > 0) { + WGPUFragmentState wgpu_frag_state; + _sg_clear(&wgpu_frag_state, sizeof(wgpu_frag_state)); + WGPUColorTargetState wgpu_ctgt_state[SG_MAX_COLOR_ATTACHMENTS]; + _sg_clear(&wgpu_ctgt_state, sizeof(wgpu_ctgt_state)); + WGPUBlendState wgpu_blend_state[SG_MAX_COLOR_ATTACHMENTS]; + _sg_clear(&wgpu_blend_state, sizeof(wgpu_blend_state)); + wgpu_frag_state.module = shd->wgpu.stage[SG_SHADERSTAGE_FS].module; + wgpu_frag_state.entryPoint = shd->wgpu.stage[SG_SHADERSTAGE_FS].entry.buf; + wgpu_frag_state.targetCount = (size_t)desc->color_count; + wgpu_frag_state.targets = &wgpu_ctgt_state[0]; + for (int i = 0; i < desc->color_count; i++) { + SOKOL_ASSERT(i < SG_MAX_COLOR_ATTACHMENTS); + wgpu_ctgt_state[i].format = _sg_wgpu_textureformat(desc->colors[i].pixel_format); + wgpu_ctgt_state[i].writeMask = _sg_wgpu_colorwritemask(desc->colors[i].write_mask); + if (desc->colors[i].blend.enabled) { + wgpu_ctgt_state[i].blend = &wgpu_blend_state[i]; + wgpu_blend_state[i].color.operation = _sg_wgpu_blendop(desc->colors[i].blend.op_rgb); + wgpu_blend_state[i].color.srcFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.src_factor_rgb); + wgpu_blend_state[i].color.dstFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.dst_factor_rgb); + wgpu_blend_state[i].alpha.operation = _sg_wgpu_blendop(desc->colors[i].blend.op_alpha); + wgpu_blend_state[i].alpha.srcFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.src_factor_alpha); + wgpu_blend_state[i].alpha.dstFactor = _sg_wgpu_blendfactor(desc->colors[i].blend.dst_factor_alpha); + } + } + wgpu_pip_desc.fragment = &wgpu_frag_state; } - pip_desc.colorStateCount = desc->color_count; - pip_desc.colorStates = cs_desc; - pip_desc.sampleMask = 0xFFFFFFFF; // FIXME: ??? - pip->wgpu.pip = wgpuDeviceCreateRenderPipeline(_sg.wgpu.dev, &pip_desc); + pip->wgpu.pip = wgpuDeviceCreateRenderPipeline(_sg.wgpu.dev, &wgpu_pip_desc); SOKOL_ASSERT(0 != pip->wgpu.pip); - wgpuPipelineLayoutRelease(pip_layout); -*/ + wgpuPipelineLayoutRelease(wgpu_pip_layout); + return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_pipeline(_sg_pipeline_t* pip) { SOKOL_ASSERT(pip); -/* if (pip == _sg.wgpu.cur_pipeline) { _sg.wgpu.cur_pipeline = 0; - _Sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID; + _sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID; } if (pip->wgpu.pip) { wgpuRenderPipelineRelease(pip->wgpu.pip); pip->wgpu.pip = 0; } -*/ } _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pass(_sg_pass_t* pass, _sg_image_t** color_images, _sg_image_t** resolve_images, _sg_image_t* ds_img, const sg_pass_desc* desc) { @@ -13337,18 +13351,16 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_scissor_rect(int x, int y, int w, int h, bool } _SOKOL_PRIVATE void _sg_wgpu_apply_pipeline(_sg_pipeline_t* pip) { -/* SOKOL_ASSERT(pip); SOKOL_ASSERT(pip->wgpu.pip); SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); - _sg.wgpu.draw_indexed = (pip->cmn.index_type != SG_INDEXTYPE_NONE); + _sg.wgpu.use_indexed_draw = (pip->cmn.index_type != SG_INDEXTYPE_NONE); _sg.wgpu.cur_pipeline = pip; _sg.wgpu.cur_pipeline_id.id = pip->slot.id; wgpuRenderPassEncoderSetPipeline(_sg.wgpu.pass_enc, pip->wgpu.pip); - wgpuRenderPassEncoderSetBlendColor(_sg.wgpu.pass_enc, (WGPUColor*)&pip->cmn.blend_color); - wgpuRenderPassEncoderSetStencilReference(_sg.wgpu.pass_enc, pip->wgpu.stencil_ref); -*/ + wgpuRenderPassEncoderSetBlendConstant(_sg.wgpu.pass_enc, &pip->wgpu.blend_color); + wgpuRenderPassEncoderSetStencilReference(_sg.wgpu.pass_enc, pip->cmn.stencil.ref); } /* From 3634c90068e487b14ffc1faeb38705a2cec9d946 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 12 Aug 2023 17:02:22 +0200 Subject: [PATCH 09/95] sokol_gfx wgpu: implement sg_apply_bindings() --- sokol_gfx.h | 101 +++++++++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 44 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index d2f42a84d..2f369f8cc 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4796,9 +4796,12 @@ typedef struct { #define _SG_WGPU_STAGING_ALIGN (256) #define _SG_WGPU_STAGING_PIPELINE_SIZE (8) #define _SG_WGPU_ROWPITCH_ALIGN (256) -#define _SG_WGPU_MAX_SHADERSTAGE_IMAGES (8) #define _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE (1<<16) -#define _SG_WGPU_NUM_BINDGROUPS (3) // 1: uniforms, 2: vertex stage images & samplers, 3: fragment stage images & samplers +#define _SG_WGPU_NUM_BINDGROUPS (3) // 0: uniforms, 1: vertex stage images & samplers, 2: fragment stage images & samplers +#define _SG_WGPU_UNIFORMS_BINDGROUP_INDEX (0) +#define _SG_WGPU_VS_BINDGROUP_INDEX (1) +#define _SG_WGPU_FS_BINDGROUP_INDEX (2) + typedef struct { _sg_slot_t slot; @@ -12907,7 +12910,9 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const return SG_RESOURCESTATE_FAILED; } - // create image/sampler bind group + // create image/sampler bind group layout: + // - first all images + // - followed by all samplers WGPUShaderStage wgpu_shader_stage = (stage_index == SG_SHADERSTAGE_VS) ? WGPUShaderStage_Vertex : WGPUShaderStage_Fragment; const int num_images = cmn_stage->num_images; if (num_images > (int)_sg.wgpu.limits.limits.maxSampledTexturesPerShaderStage) { @@ -12932,7 +12937,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const wgpu_bgl_entry->texture.multisampled = img_desc->multisampled; } for (int smp_index = 0; smp_index < num_samplers; smp_index++) { - const int bind_index = smp_index; + const int bind_index = num_images + smp_index; WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bind_index]; const sg_shader_sampler_desc* smp_desc = &stage_desc->samplers[smp_index]; wgpu_bgl_entry->binding = (uint32_t)bind_index; @@ -12982,11 +12987,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ // - 1 bindgroup for uniform block, // - 1 bindgroup for vertex shader resources // - 1 bindgroup for fragment shader resources - WGPUBindGroupLayout wgpu_bgl[_SG_WGPU_NUM_BINDGROUPS] = { - _sg.wgpu.ub.bindgroup_layout, - shd->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout, - shd->wgpu.stage[SG_SHADERSTAGE_FS].bind_group_layout - }; + WGPUBindGroupLayout wgpu_bgl[_SG_WGPU_NUM_BINDGROUPS]; + wgpu_bgl[_SG_WGPU_UNIFORMS_BINDGROUP_INDEX] = _sg.wgpu.ub.bindgroup_layout; + wgpu_bgl[_SG_WGPU_VS_BINDGROUP_INDEX] = shd->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout; + wgpu_bgl[_SG_WGPU_FS_BINDGROUP_INDEX] = shd->wgpu.stage[SG_SHADERSTAGE_FS].bind_group_layout; WGPUPipelineLayoutDescriptor wgpu_pl_desc; _sg_clear(&wgpu_pl_desc, sizeof(wgpu_pl_desc)); wgpu_pl_desc.bindGroupLayoutCount = _SG_WGPU_NUM_BINDGROUPS; @@ -13363,30 +13367,38 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_pipeline(_sg_pipeline_t* pip) { wgpuRenderPassEncoderSetStencilReference(_sg.wgpu.pass_enc, pip->cmn.stencil.ref); } -/* -_SOKOL_PRIVATE WGPUBindGroup _sg_wgpu_create_images_bindgroup(WGPUBindGroupLayout bgl, _sg_image_t** imgs, int num_imgs) { +_SOKOL_PRIVATE WGPUBindGroup _sg_wgpu_create_bindgroup( + WGPUBindGroupLayout bgl, + _sg_image_t** imgs, int num_imgs, + _sg_sampler_t** smps, int num_smps) +{ SOKOL_ASSERT(_sg.wgpu.dev); - SOKOL_ASSERT(num_imgs <= _SG_WGPU_MAX_SHADERSTAGE_IMAGES); - WGPUBindGroupBinding img_bgb[_SG_WGPU_MAX_SHADERSTAGE_IMAGES * 2]; - _sg_clear(&img_bgb, sizeof(img_bgb)); + SOKOL_ASSERT(imgs && (num_imgs <= SG_MAX_SHADERSTAGE_IMAGES)); + SOKOL_ASSERT(smps && (num_smps <= SG_MAX_SHADERSTAGE_SAMPLERS)); + + WGPUBindGroupEntry wgpu_entries[SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS]; + _sg_clear(&wgpu_entries, sizeof(wgpu_entries)); for (int img_index = 0; img_index < num_imgs; img_index++) { - WGPUBindGroupBinding* tex_bdg = &img_bgb[img_index*2 + 0]; - WGPUBindGroupBinding* smp_bdg = &img_bgb[img_index*2 + 1]; - tex_bdg->binding = img_index; - tex_bdg->textureView = imgs[img_index]->wgpu.tex_view; - smp_bdg->binding = img_index + _SG_WGPU_MAX_SHADERSTAGE_IMAGES; - smp_bdg->sampler = imgs[img_index]->wgpu.sampler; + uint32_t wgpu_bind_index = (uint32_t)img_index; + WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[wgpu_bind_index]; + wgpu_entry->binding = wgpu_bind_index; + wgpu_entry->textureView = imgs[img_index]->wgpu.view; + } + for (int smp_index = 0; smp_index < num_smps; smp_index++) { + uint32_t wgpu_bind_index = (uint32_t)(num_imgs + smp_index); + WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[wgpu_bind_index]; + wgpu_entry->binding = wgpu_bind_index; + wgpu_entry->sampler = smps[smp_index]->wgpu.smp; } WGPUBindGroupDescriptor bg_desc; _sg_clear(&bg_desc, sizeof(bg_desc)); bg_desc.layout = bgl; - bg_desc.bindingCount = 2 * num_imgs; - bg_desc.bindings = &img_bgb[0]; + bg_desc.entryCount = (size_t)(num_imgs + num_smps); + bg_desc.entries = &wgpu_entries[0]; WGPUBindGroup bg = wgpuDeviceCreateBindGroup(_sg.wgpu.dev, &bg_desc); SOKOL_ASSERT(bg); return bg; } -*/ _SOKOL_PRIVATE void _sg_wgpu_apply_bindings( _sg_pipeline_t* pip, @@ -13398,46 +13410,47 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_bindings( _sg_sampler_t** fs_smps, int num_fs_smps) { SOKOL_ASSERT(_sg.wgpu.in_pass); -/* SOKOL_ASSERT(_sg.wgpu.pass_enc); SOKOL_ASSERT(pip->shader && (pip->cmn.shader_id.id == pip->shader->slot.id)); // index buffer if (ib) { - wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, ib->wgpu.buf, ib_offset); + const WGPUIndexFormat format = _sg_wgpu_indexformat(pip->cmn.index_type); + const uint64_t buf_size = (uint64_t)ib->cmn.size; + const uint64_t offset = (uint64_t)ib_offset; + SOKOL_ASSERT(buf_size > offset); + const uint64_t max_bytes = buf_size - offset; + wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, ib->wgpu.buf, format, offset, max_bytes); } // vertex buffers for (uint32_t slot = 0; slot < (uint32_t)num_vbs; slot++) { - wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, slot, vbs[slot]->wgpu.buf, (uint64_t)vb_offsets[slot]); + const uint64_t buf_size = (uint64_t)vbs[slot]->cmn.size; + const uint64_t offset = (uint64_t)vb_offsets[slot]; + SOKOL_ASSERT(buf_size > offset); + const uint64_t max_bytes = buf_size - offset; + wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, slot, vbs[slot]->wgpu.buf, offset, max_bytes); } - // need to create throw-away bind groups for images - if (num_vs_imgs > 0) { - if (num_vs_imgs > _SG_WGPU_MAX_SHADERSTAGE_IMAGES) { - num_vs_imgs = _SG_WGPU_MAX_SHADERSTAGE_IMAGES; - } + // FIXME: create adhoc bind group objects for images and samplers per stage + if ((num_vs_imgs + num_vs_smps) > 0) { WGPUBindGroupLayout vs_bgl = pip->shader->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout; SOKOL_ASSERT(vs_bgl); - WGPUBindGroup vs_img_bg = _sg_wgpu_create_images_bindgroup(vs_bgl, vs_imgs, num_vs_imgs); - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, 1, vs_img_bg, 0, 0); - wgpuBindGroupRelease(vs_img_bg); + WGPUBindGroup vs_bg = _sg_wgpu_create_bindgroup(vs_bgl, vs_imgs, num_vs_imgs, vs_smps, num_vs_smps); + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_VS_BINDGROUP_INDEX, vs_bg, 0, 0); + wgpuBindGroupRelease(vs_bg); } else { - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, 1, _sg.wgpu.empty_bind_group, 0, 0); + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_VS_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); } - if (num_fs_imgs > 0) { - if (num_fs_imgs > _SG_WGPU_MAX_SHADERSTAGE_IMAGES) { - num_fs_imgs = _SG_WGPU_MAX_SHADERSTAGE_IMAGES; - } + if ((num_fs_imgs + num_fs_smps) > 0) { WGPUBindGroupLayout fs_bgl = pip->shader->wgpu.stage[SG_SHADERSTAGE_FS].bind_group_layout; SOKOL_ASSERT(fs_bgl); - WGPUBindGroup fs_img_bg = _sg_wgpu_create_images_bindgroup(fs_bgl, fs_imgs, num_fs_imgs); - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, 2, fs_img_bg, 0, 0); - wgpuBindGroupRelease(fs_img_bg); + WGPUBindGroup fs_bg = _sg_wgpu_create_bindgroup(fs_bgl, fs_imgs, num_fs_imgs, fs_smps, num_fs_smps); + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_FS_BINDGROUP_INDEX, fs_bg, 0, 0); + wgpuBindGroupRelease(fs_bg); } else { - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, 2, _sg.wgpu.empty_bind_group, 0, 0); + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_FS_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); } -*/ } _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) { From 893ba7b01082e4058c4b87e9c806f038bdd92b0c Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 13 Aug 2023 15:19:29 +0200 Subject: [PATCH 10/95] sokol_gfx.h wgpu: code cleanup and remove uniform buffer conveyor belt --- sokol_gfx.h | 214 +++++++++++++++------------------------------------- 1 file changed, 62 insertions(+), 152 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 2f369f8cc..afd5cccf0 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4794,7 +4794,6 @@ typedef struct { #elif defined(SOKOL_WGPU) #define _SG_WGPU_STAGING_ALIGN (256) -#define _SG_WGPU_STAGING_PIPELINE_SIZE (8) #define _SG_WGPU_ROWPITCH_ALIGN (256) #define _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE (1<<16) #define _SG_WGPU_NUM_BINDGROUPS (3) // 0: uniforms, 1: vertex stage images & samplers, 2: fragment stage images & samplers @@ -4881,19 +4880,15 @@ typedef _sg_wgpu_context_t _sg_context_t; // a pool of per-frame uniform buffers typedef struct { - WGPUBindGroupLayout bindgroup_layout; uint32_t num_bytes; - uint32_t offset; // current offset into current frame's mapped uniform buffer - uint32_t bind_offsets[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS]; + uint32_t offset; // current offset into buf WGPUBuffer buf; // the GPU-side uniform buffer - WGPUBindGroup bindgroup; struct { - int num; - int cur; - WGPUBuffer buf[_SG_WGPU_STAGING_PIPELINE_SIZE]; // CPU-side staging buffers - void* ptr[_SG_WGPU_STAGING_PIPELINE_SIZE]; // non-null if currently mapped - } staging; -} _sg_wgpu_ubpool_t; + WGPUBindGroupLayout group_layout; + WGPUBindGroup group; + uint32_t offsets[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS]; + } bind; +} _sg_wgpu_uniform_buffer_t; // the WGPU backend state typedef struct { @@ -4917,7 +4912,7 @@ typedef struct { WGPUBindGroup empty_bind_group; const _sg_pipeline_t* cur_pipeline; sg_pipeline cur_pipeline_id; - _sg_wgpu_ubpool_t ub; + _sg_wgpu_uniform_buffer_t uniform; } _sg_wgpu_backend_t; #endif @@ -11943,7 +11938,8 @@ _SOKOL_PRIVATE void _sg_mtl_update_image(_sg_image_t* img, const sg_image_data* // ██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ // ███ ███ ███████ ██████ ██████ ██ ██████ ██████ ██ ██ ██████ ██ ██ ███████ ██ ████ ██████ // -// >>webgpu backend +// >>webgpu +// >>wgpu #elif defined(SOKOL_WGPU) _SOKOL_PRIVATE WGPUBufferUsageFlags _sg_wgpu_buffer_usage(sg_buffer_type t, sg_usage u) { @@ -11984,7 +11980,7 @@ _SOKOL_PRIVATE WGPUStoreOp _sg_wgpu_store_op(sg_store_action a) { } } -_SOKOL_PRIVATE WGPUTextureViewDimension _sg_wgpu_tex_view_dimension(sg_image_type t) { +_SOKOL_PRIVATE WGPUTextureViewDimension _sg_wgpu_texture_view_dimension(sg_image_type t) { switch (t) { case SG_IMAGETYPE_2D: return WGPUTextureViewDimension_2D; case SG_IMAGETYPE_CUBE: return WGPUTextureViewDimension_Cube; @@ -11994,7 +11990,15 @@ _SOKOL_PRIVATE WGPUTextureViewDimension _sg_wgpu_tex_view_dimension(sg_image_typ } } -_SOKOL_PRIVATE WGPUTextureSampleType _sg_wgpu_tex_sample_type(sg_image_sample_type t) { +_SOKOL_PRIVATE WGPUTextureDimension _sg_wgpu_texture_dim(sg_image_type t) { + if (SG_IMAGETYPE_3D == t) { + return WGPUTextureDimension_3D; + } else { + return WGPUTextureDimension_2D; + } +} + +_SOKOL_PRIVATE WGPUTextureSampleType _sg_wgpu_texture_sample_type(sg_image_sample_type t) { switch (t) { case SG_IMAGESAMPLETYPE_FLOAT: return WGPUTextureSampleType_Float; case SG_IMAGESAMPLETYPE_DEPTH: return WGPUTextureSampleType_Depth; @@ -12005,14 +12009,6 @@ _SOKOL_PRIVATE WGPUTextureSampleType _sg_wgpu_tex_sample_type(sg_image_sample_ty } } -_SOKOL_PRIVATE WGPUTextureDimension _sg_wgpu_tex_dim(sg_image_type t) { - if (SG_IMAGETYPE_3D == t) { - return WGPUTextureDimension_3D; - } else { - return WGPUTextureDimension_2D; - } -} - _SOKOL_PRIVATE WGPUSamplerBindingType _sg_wgpu_sampler_binding_type(sg_sampler_type t) { switch (t) { // FIXME: NonFiltering @@ -12037,7 +12033,7 @@ _SOKOL_PRIVATE WGPUAddressMode _sg_wgpu_sampler_addrmode(sg_wrap m) { } } -_SOKOL_PRIVATE WGPUFilterMode _sg_wgpu_sampler_minmagfilter(sg_filter f) { +_SOKOL_PRIVATE WGPUFilterMode _sg_wgpu_sampler_minmag_filter(sg_filter f) { switch (f) { case SG_FILTER_NEAREST: return WGPUFilterMode_Nearest; @@ -12350,33 +12346,21 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_RGBA]); } -/* - WGPU uniform buffer pool implementation: - - At start of frame, a mapped buffer is grabbed from the pool, - or a new buffer is created if there is no mapped buffer available. - - At end of frame, the current buffer is unmapped before queue submit, - and async-mapped immediately again. - - UNIFORM BUFFER FIXME: - - - As per WebGPU spec, it should be possible to create a Uniform|MapWrite - buffer, but this isn't currently allowed in Dawn. -*/ -_SOKOL_PRIVATE void _sg_wgpu_ubpool_init(const sg_desc* desc) { +_SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_init(const sg_desc* desc) { // Add the max-uniform-update size (64 KB) to the requested buffer size, // this is to prevent validation errors in the WebGPU implementation // if the entire buffer size is used per frame. 64 KB is the allowed // max uniform update size on NVIDIA - _sg.wgpu.ub.num_bytes = (uint32_t)(desc->uniform_buffer_size + _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); + // + // FIXME: is this still needed? + _sg.wgpu.uniform.num_bytes = (uint32_t)(desc->uniform_buffer_size + _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); WGPUBufferDescriptor ub_desc; _sg_clear(&ub_desc, sizeof(ub_desc)); - ub_desc.size = _sg.wgpu.ub.num_bytes; + ub_desc.size = _sg.wgpu.uniform.num_bytes; ub_desc.usage = WGPUBufferUsage_Uniform|WGPUBufferUsage_CopyDst; - _sg.wgpu.ub.buf = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &ub_desc); - SOKOL_ASSERT(_sg.wgpu.ub.buf); + _sg.wgpu.uniform.buf = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &ub_desc); + SOKOL_ASSERT(_sg.wgpu.uniform.buf); WGPUBindGroupLayoutEntry ub_bgle_desc[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS]; _sg_clear(ub_bgle_desc, sizeof(ub_bgle_desc)); @@ -12395,8 +12379,8 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_init(const sg_desc* desc) { _sg_clear(&ub_bgl_desc, sizeof(ub_bgl_desc)); ub_bgl_desc.entryCount = SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS; ub_bgl_desc.entries = &ub_bgle_desc[0][0]; - _sg.wgpu.ub.bindgroup_layout = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &ub_bgl_desc); - SOKOL_ASSERT(_sg.wgpu.ub.bindgroup_layout); + _sg.wgpu.uniform.bind.group_layout = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &ub_bgl_desc); + SOKOL_ASSERT(_sg.wgpu.uniform.bind.group_layout); WGPUBindGroupEntry ub_bge[SG_NUM_SHADER_STAGES][SG_MAX_SHADERSTAGE_UBS]; _sg_clear(ub_bge, sizeof(ub_bge)); @@ -12404,112 +12388,47 @@ _SOKOL_PRIVATE void _sg_wgpu_ubpool_init(const sg_desc* desc) { for (uint32_t ub_index = 0; ub_index < SG_MAX_SHADERSTAGE_UBS; ub_index++) { uint32_t bind_index = stage_index * SG_MAX_SHADERSTAGE_UBS + ub_index; ub_bge[stage_index][ub_index].binding = bind_index; - ub_bge[stage_index][ub_index].buffer = _sg.wgpu.ub.buf; + ub_bge[stage_index][ub_index].buffer = _sg.wgpu.uniform.buf; ub_bge[stage_index][ub_index].size = _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE; } } WGPUBindGroupDescriptor bg_desc; _sg_clear(&bg_desc, sizeof(bg_desc)); - bg_desc.layout = _sg.wgpu.ub.bindgroup_layout; + bg_desc.layout = _sg.wgpu.uniform.bind.group_layout; bg_desc.entryCount = SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS; bg_desc.entries = &ub_bge[0][0]; - _sg.wgpu.ub.bindgroup = wgpuDeviceCreateBindGroup(_sg.wgpu.dev, &bg_desc); - SOKOL_ASSERT(_sg.wgpu.ub.bindgroup); + _sg.wgpu.uniform.bind.group = wgpuDeviceCreateBindGroup(_sg.wgpu.dev, &bg_desc); + SOKOL_ASSERT(_sg.wgpu.uniform.bind.group); } -_SOKOL_PRIVATE void _sg_wgpu_ubpool_discard(void) { - if (_sg.wgpu.ub.buf) { - wgpuBufferRelease(_sg.wgpu.ub.buf); - _sg.wgpu.ub.buf = 0; +_SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_discard(void) { + if (_sg.wgpu.uniform.buf) { + wgpuBufferRelease(_sg.wgpu.uniform.buf); + _sg.wgpu.uniform.buf = 0; } - if (_sg.wgpu.ub.bindgroup) { - wgpuBindGroupRelease(_sg.wgpu.ub.bindgroup); - _sg.wgpu.ub.bindgroup = 0; + if (_sg.wgpu.uniform.bind.group) { + wgpuBindGroupRelease(_sg.wgpu.uniform.bind.group); + _sg.wgpu.uniform.bind.group = 0; } - if (_sg.wgpu.ub.bindgroup_layout) { - wgpuBindGroupLayoutRelease(_sg.wgpu.ub.bindgroup_layout); - _sg.wgpu.ub.bindgroup_layout = 0; - } - for (int i = 0; i < _sg.wgpu.ub.staging.num; i++) { - if (_sg.wgpu.ub.staging.buf[i]) { - wgpuBufferRelease(_sg.wgpu.ub.staging.buf[i]); - _sg.wgpu.ub.staging.buf[i] = 0; - _sg.wgpu.ub.staging.ptr[i] = 0; - } + if (_sg.wgpu.uniform.bind.group_layout) { + wgpuBindGroupLayoutRelease(_sg.wgpu.uniform.bind.group_layout); + _sg.wgpu.uniform.bind.group_layout = 0; } } -_SOKOL_PRIVATE void _sg_wgpu_ubpool_mapped_callback(WGPUBufferMapAsyncStatus status, void* user_data) { - if (!_sg.wgpu.valid) { - return; - } - // FIXME: better handling for this - if (WGPUBufferMapAsyncStatus_Success != status) { - _SG_ERROR(WGPU_MAP_UNIFORM_BUFFER_FAILED); - SOKOL_ASSERT(false); - } - const int staging_index = (int)(intptr_t) user_data; - SOKOL_ASSERT(staging_index < _sg.wgpu.ub.staging.num); - SOKOL_ASSERT(0 == _sg.wgpu.ub.staging.ptr[staging_index]); - _sg.wgpu.ub.staging.ptr[staging_index] = (uint8_t*) wgpuBufferGetMappedRange(_sg.wgpu.ub.staging.buf[staging_index], 0, _sg.wgpu.ub.num_bytes); - SOKOL_ASSERT(0 != _sg.wgpu.ub.staging.ptr[staging_index]); -} - -_SOKOL_PRIVATE void _sg_wgpu_ubpool_next_frame(bool first_frame) { - - // immediately request a new mapping for the last frame's current staging buffer - if (!first_frame) { - WGPUBuffer ub_src = _sg.wgpu.ub.staging.buf[_sg.wgpu.ub.staging.cur]; - SOKOL_ASSERT(ub_src); - wgpuBufferMapAsync( - ub_src, // buffer - WGPUMapMode_Write, // mode - 0, // offset - _sg.wgpu.ub.num_bytes, // size - _sg_wgpu_ubpool_mapped_callback, // callback - (void*)(intptr_t)_sg.wgpu.ub.staging.cur // usedata - ); - } - - // rewind per-frame offsets - _sg.wgpu.ub.offset = 0; - _sg_clear(&_sg.wgpu.ub.bind_offsets, sizeof(_sg.wgpu.ub.bind_offsets)); - - // check if a mapped staging buffer is available, otherwise create one - for (int i = 0; i < _sg.wgpu.ub.staging.num; i++) { - if (_sg.wgpu.ub.staging.ptr[i]) { - _sg.wgpu.ub.staging.cur = i; - return; - } - } - - // no mapped uniform buffer available, create one - SOKOL_ASSERT(_sg.wgpu.ub.staging.num < _SG_WGPU_STAGING_PIPELINE_SIZE); - _sg.wgpu.ub.staging.cur = _sg.wgpu.ub.staging.num++; - const int cur = _sg.wgpu.ub.staging.cur; - - WGPUBufferDescriptor desc; - _sg_clear(&desc, sizeof(desc)); - desc.size = _sg.wgpu.ub.num_bytes; - desc.usage = WGPUBufferUsage_CopySrc|WGPUBufferUsage_MapWrite; - desc.mappedAtCreation = true; - _sg.wgpu.ub.staging.buf[cur] = wgpuDeviceCreateBuffer(_sg.wgpu.dev, &desc); - _sg.wgpu.ub.staging.ptr[cur] = wgpuBufferGetMappedRange(_sg.wgpu.ub.staging.buf[cur], 0, _sg.wgpu.ub.num_bytes); - SOKOL_ASSERT(_sg.wgpu.ub.staging.buf[cur]); - SOKOL_ASSERT(_sg.wgpu.ub.staging.ptr[cur]); +_SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_begin_pass(void) { + // FIXME: is this still needed? + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, + 0, // groupIndex 0 is reserved for uniform buffers + _sg.wgpu.uniform.bind.group, + SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS, + &_sg.wgpu.uniform.bind.offsets[0][0]); } -_SOKOL_PRIVATE void _sg_wgpu_ubpool_flush(void) { - // unmap staging buffer and copy to uniform buffer - const int cur = _sg.wgpu.ub.staging.cur; - SOKOL_ASSERT(_sg.wgpu.ub.staging.ptr[cur]); - _sg.wgpu.ub.staging.ptr[cur] = 0; - WGPUBuffer src_buf = _sg.wgpu.ub.staging.buf[cur]; - wgpuBufferUnmap(src_buf); - if (_sg.wgpu.ub.offset > 0) { - const WGPUBuffer dst_buf = _sg.wgpu.ub.buf; - wgpuCommandEncoderCopyBufferToBuffer(_sg.wgpu.render_cmd_enc, src_buf, 0, dst_buf, 0, _sg.wgpu.ub.offset); - } +_SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { + // clear offsets + _sg.wgpu.uniform.offset = 0; + _sg_clear(&_sg.wgpu.uniform.bind.offsets[0][0], sizeof(_sg.wgpu.uniform.bind.offsets)); } /* @@ -12634,8 +12553,7 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg_wgpu_init_caps(); // setup the uniform and staging buffer pools - _sg_wgpu_ubpool_init(desc); - _sg_wgpu_ubpool_next_frame(true); + _sg_wgpu_uniform_buffer_init(desc); // create an empty bind group for shader stages without bound images WGPUBindGroupLayoutDescriptor bgl_desc; @@ -12660,11 +12578,10 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_backend(void) { SOKOL_ASSERT(_sg.wgpu.valid); SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); _sg.wgpu.valid = false; - _sg_wgpu_ubpool_discard(); + _sg_wgpu_uniform_buffer_discard(); wgpuBindGroupRelease(_sg.wgpu.empty_bind_group); _sg.wgpu.empty_bind_group = 0; wgpuCommandEncoderRelease(_sg.wgpu.render_cmd_enc); _sg.wgpu.render_cmd_enc = 0; wgpuQueueRelease(_sg.wgpu.queue); _sg.wgpu.queue = 0; - } _SOKOL_PRIVATE void _sg_wgpu_reset_state_cache(void) { @@ -12932,8 +12849,8 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const const sg_shader_image_desc* img_desc = &stage_desc->images[img_index]; wgpu_bgl_entry->binding = (uint32_t)bind_index; wgpu_bgl_entry->visibility = wgpu_shader_stage; - wgpu_bgl_entry->texture.viewDimension = _sg_wgpu_tex_view_dimension(img_desc->image_type); - wgpu_bgl_entry->texture.sampleType = _sg_wgpu_tex_sample_type(img_desc->sample_type); + wgpu_bgl_entry->texture.viewDimension = _sg_wgpu_texture_view_dimension(img_desc->image_type); + wgpu_bgl_entry->texture.sampleType = _sg_wgpu_texture_sample_type(img_desc->sample_type); wgpu_bgl_entry->texture.multisampled = img_desc->multisampled; } for (int smp_index = 0; smp_index < num_samplers; smp_index++) { @@ -12988,7 +12905,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ // - 1 bindgroup for vertex shader resources // - 1 bindgroup for fragment shader resources WGPUBindGroupLayout wgpu_bgl[_SG_WGPU_NUM_BINDGROUPS]; - wgpu_bgl[_SG_WGPU_UNIFORMS_BINDGROUP_INDEX] = _sg.wgpu.ub.bindgroup_layout; + wgpu_bgl[_SG_WGPU_UNIFORMS_BINDGROUP_INDEX] = _sg.wgpu.uniform.bind.group_layout; wgpu_bgl[_SG_WGPU_VS_BINDGROUP_INDEX] = shd->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout; wgpu_bgl[_SG_WGPU_FS_BINDGROUP_INDEX] = shd->wgpu.stage[SG_SHADERSTAGE_FS].bind_group_layout; WGPUPipelineLayoutDescriptor wgpu_pl_desc; @@ -13277,11 +13194,7 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* SOKOL_ASSERT(_sg.wgpu.pass_enc); // initial uniform buffer binding (required even if no uniforms are set in the frame) - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, - 0, // groupIndex 0 is reserved for uniform buffers - _sg.wgpu.ub.bindgroup, - SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS, - &_sg.wgpu.ub.bind_offsets[0][0]); + _sg_wgpu_uniform_buffer_on_begin_pass(); } _SOKOL_PRIVATE void _sg_wgpu_end_pass(void) { @@ -13297,9 +13210,6 @@ _SOKOL_PRIVATE void _sg_wgpu_commit(void) { SOKOL_ASSERT(!_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); - // finish and submit this frame's work - _sg_wgpu_ubpool_flush(); - WGPUCommandBufferDescriptor cmd_buf_desc; _sg_clear(&cmd_buf_desc, sizeof(cmd_buf_desc)); WGPUCommandBuffer wgpu_cmd_buf = wgpuCommandEncoderFinish(_sg.wgpu.render_cmd_enc, &cmd_buf_desc); @@ -13315,8 +13225,8 @@ _SOKOL_PRIVATE void _sg_wgpu_commit(void) { _sg_clear(&cmd_enc_desc, sizeof(cmd_enc_desc)); _sg.wgpu.render_cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); - // grab new staging buffers for uniform- and vertex/image-updates - _sg_wgpu_ubpool_next_frame(false); + // reset uniform buffer offsets + _sg_wgpu_uniform_buffer_on_commit(); } _SOKOL_PRIVATE void _sg_wgpu_apply_viewport(int x, int y, int w, int h, bool origin_top_left) { From fbdae164c42613677d1471077288a5506450b351 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 13 Aug 2023 16:27:41 +0200 Subject: [PATCH 11/95] sokol_gfx.h wgpu: implement sg_apply_uniforms() --- sokol_gfx.h | 62 +++++++++++++---------------------------------------- 1 file changed, 15 insertions(+), 47 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index afd5cccf0..368aaacdd 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4013,7 +4013,6 @@ enum { _SG_DEFAULT_PASS_POOL_SIZE = 16, _SG_DEFAULT_CONTEXT_POOL_SIZE = 16, _SG_DEFAULT_UB_SIZE = 4 * 1024 * 1024, - _SG_DEFAULT_STAGING_SIZE = 8 * 1024 * 1024, _SG_DEFAULT_MAX_COMMIT_LISTENERS = 1024, }; @@ -4793,15 +4792,13 @@ typedef struct { #elif defined(SOKOL_WGPU) -#define _SG_WGPU_STAGING_ALIGN (256) #define _SG_WGPU_ROWPITCH_ALIGN (256) -#define _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE (1<<16) +#define _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE (1<<16) // also see WGPULimits.maxUniformBufferBindingSize #define _SG_WGPU_NUM_BINDGROUPS (3) // 0: uniforms, 1: vertex stage images & samplers, 2: fragment stage images & samplers #define _SG_WGPU_UNIFORMS_BINDGROUP_INDEX (0) #define _SG_WGPU_VS_BINDGROUP_INDEX (1) #define _SG_WGPU_FS_BINDGROUP_INDEX (2) - typedef struct { _sg_slot_t slot; _sg_buffer_common_t cmn; @@ -5336,6 +5333,10 @@ _SOKOL_PRIVATE int _sg_roundup(int val, int round_to) { return (val+(round_to-1)) & ~(round_to-1); } +_SOKOL_PRIVATE uint64_t _sg_roundup_u32(uint32_t val, uint32_t round_to) { + return (val+(round_to-1)) & ~(round_to-1); +} + _SOKOL_PRIVATE uint64_t _sg_roundup_u64(uint64_t val, uint64_t round_to) { return (val+(round_to-1)) & ~(round_to-1); } @@ -12417,7 +12418,6 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_discard(void) { } _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_begin_pass(void) { - // FIXME: is this still needed? wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, 0, // groupIndex 0 is reserved for uniform buffers _sg.wgpu.uniform.bind.group, @@ -12549,10 +12549,7 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg.wgpu.queue = wgpuDeviceGetQueue(_sg.wgpu.dev); SOKOL_ASSERT(_sg.wgpu.queue); - // setup WebGPU features and limits _sg_wgpu_init_caps(); - - // setup the uniform and staging buffer pools _sg_wgpu_uniform_buffer_init(desc); // create an empty bind group for shader stages without bound images @@ -12773,33 +12770,6 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_sampler(_sg_sampler_t* smp) { // FIXME } -/* - How BindGroups work in WebGPU: - - - up to 4 bind groups can be bound simultaneously - - up to 16 bindings per bind group - - 'binding' slots are local per bind group - - in the shader: - layout(set=0, binding=1) corresponds to bind group 0, binding 1 - - Now how to map this to sokol-gfx's bind model: - - Reduce SG_MAX_SHADERSTAGE_IMAGES to 8, then: - - 1 bind group for all 8 uniform buffers - 1 bind group for vertex shader textures + samplers - 1 bind group for fragment shader textures + samples - - Alternatively: - - 1 bind group for 8 uniform buffer slots - 1 bind group for 8 vs images + 8 vs samplers - 1 bind group for 12 fs images - 1 bind group for 12 fs samplers - - I guess this means that we need to create BindGroups on the - fly during sg_apply_bindings() :/ -*/ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) { SOKOL_ASSERT(shd && desc); SOKOL_ASSERT(desc->vs.source && desc->fs.source); @@ -13343,6 +13313,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_bindings( } // FIXME: create adhoc bind group objects for images and samplers per stage + // (either use a bindgroup-cache or introduce bindgroups as sokol-gfx objects) if ((num_vs_imgs + num_vs_smps) > 0) { WGPUBindGroupLayout vs_bgl = pip->shader->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout; SOKOL_ASSERT(vs_bgl); @@ -13364,29 +13335,26 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_bindings( } _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) { -/* + const uint32_t alignment = _sg.wgpu.limits.limits.minUniformBufferOffsetAlignment; SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); - SOKOL_ASSERT((_sg.wgpu.ub.offset + data->size) <= _sg.wgpu.ub.num_bytes); - SOKOL_ASSERT((_sg.wgpu.ub.offset & (_SG_WGPU_STAGING_ALIGN-1)) == 0); + SOKOL_ASSERT((_sg.wgpu.uniform.offset + data->size) <= _sg.wgpu.uniform.num_bytes); + SOKOL_ASSERT((_sg.wgpu.uniform.offset & (alignment - 1)) == 0); SOKOL_ASSERT(_sg.wgpu.cur_pipeline && _sg.wgpu.cur_pipeline->shader); SOKOL_ASSERT(_sg.wgpu.cur_pipeline->slot.id == _sg.wgpu.cur_pipeline_id.id); SOKOL_ASSERT(_sg.wgpu.cur_pipeline->shader->slot.id == _sg.wgpu.cur_pipeline->cmn.shader_id.id); SOKOL_ASSERT(ub_index < _sg.wgpu.cur_pipeline->shader->cmn.stage[stage_index].num_uniform_blocks); SOKOL_ASSERT(data->size <= _sg.wgpu.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size); SOKOL_ASSERT(data->size <= _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); - SOKOL_ASSERT(0 != _sg.wgpu.ub.stage.ptr[_sg.wgpu.ub.stage.cur]); - uint8_t* dst_ptr = _sg.wgpu.ub.stage.ptr[_sg.wgpu.ub.stage.cur] + _sg.wgpu.ub.offset; - memcpy(dst_ptr, data->ptr, data->size); - _sg.wgpu.ub.bind_offsets[stage_index][ub_index] = _sg.wgpu.ub.offset; + wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, _sg.wgpu.uniform.offset, data->ptr, data->size); + _sg.wgpu.uniform.bind.offsets[stage_index][ub_index] = _sg.wgpu.uniform.offset; wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, - 0, // groupIndex 0 is reserved for uniform buffers - _sg.wgpu.ub.bindgroup, + _SG_WGPU_UNIFORMS_BINDGROUP_INDEX, + _sg.wgpu.uniform.bind.group, SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS, - &_sg.wgpu.ub.bind_offsets[0][0]); - _sg.wgpu.ub.offset = _sg_roundup(_sg.wgpu.ub.offset + data->size, _SG_WGPU_STAGING_ALIGN); -*/ + &_sg.wgpu.uniform.bind.offsets[0][0]); + _sg.wgpu.uniform.offset = _sg_roundup_u32(_sg.wgpu.uniform.offset + data->size, alignment); } _SOKOL_PRIVATE void _sg_wgpu_draw(int base_element, int num_elements, int num_instances) { From 96c691193cc78287e3279baea9363a8aaf5e3997 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 14 Aug 2023 15:51:40 +0200 Subject: [PATCH 12/95] sokol_gfx.h wgpu: implement image create/destroy --- sokol_gfx.h | 272 +++++++++++++++------------------------------------- 1 file changed, 79 insertions(+), 193 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 368aaacdd..9b38a3f3d 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2905,7 +2905,9 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_OUTPUT, "") \ _SG_LOGITEM_XMACRO(WGPU_MAP_UNIFORM_BUFFER_FAILED, "failed to map uniform buffer (wgpu)") \ _SG_LOGITEM_XMACRO(WGPU_CREATE_BUFFER_FAILED, "wgpuDeviceCreateBuffer() failed") \ - _SG_LOGITEM_XMACRO(WGPU_CREATE_SHADER_MODULE_FAILED, "wgpuDeviceCreateShaderModule failed") \ + _SG_LOGITEM_XMACRO(WGPU_CREATE_TEXTURE_FAILED, "wgpuDeviceCreateTexture() failed") \ + _SG_LOGITEM_XMACRO(WGPU_CREATE_TEXTURE_VIEW_FAILED, "wgpuTextureCreateView() failed") \ + _SG_LOGITEM_XMACRO(WGPU_CREATE_SHADER_MODULE_FAILED, "wgpuDeviceCreateShaderModule() failed") \ _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_IMAGES, "shader uses too many sampled images on shader stage (wgpu)") \ _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_SAMPLERS, "shader uses too many samplers on shader stage (wgpu)") \ _SG_LOGITEM_XMACRO(WGPU_SHADER_CREATE_BINDGROUP_LAYOUT_FAILED, "wgpuDeviceCreateBindGroupLayout for shader stage failed") \ @@ -11991,7 +11993,7 @@ _SOKOL_PRIVATE WGPUTextureViewDimension _sg_wgpu_texture_view_dimension(sg_image } } -_SOKOL_PRIVATE WGPUTextureDimension _sg_wgpu_texture_dim(sg_image_type t) { +_SOKOL_PRIVATE WGPUTextureDimension _sg_wgpu_texture_dimension(sg_image_type t) { if (SG_IMAGETYPE_3D == t) { return WGPUTextureDimension_3D; } else { @@ -12431,104 +12433,6 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { _sg_clear(&_sg.wgpu.uniform.bind.offsets[0][0], sizeof(_sg.wgpu.uniform.bind.offsets)); } -/* -// helper function to compute number of bytes needed in staging buffer to copy image data -_SOKOL_PRIVATE uint32_t _sg_wgpu_image_data_buffer_size(const _sg_image_t* img) { - uint32_t num_bytes = 0; - const uint32_t num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6:1; - const uint32_t num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.num_slices : 1; - for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++) { - const uint32_t mip_width = _sg_miplevel_dim(img->cmn.width, mip_index); - const uint32_t mip_height = _sg_miplevel_dim(img->cmn.height, mip_index); - // row-pitch must be 256-aligend - const uint32_t bytes_per_slice = _sg_surface_pitch(img->cmn.pixel_format, mip_width, mip_height, _SG_WGPU_ROWPITCH_ALIGN); - num_bytes += bytes_per_slice * num_slices * num_faces; - } - return num_bytes; -} - -_SOKOL_PRIVATE uint32_t _sg_wgpu_copy_image_data(WGPUBuffer stg_buf, uint8_t* stg_base_ptr, uint32_t stg_base_offset, _sg_image_t* img, const sg_image_data* data) { - SOKOL_ASSERT(_sg.wgpu.staging_cmd_enc); - SOKOL_ASSERT(stg_buf && stg_base_ptr); - SOKOL_ASSERT(img); - SOKOL_ASSERT(data); - uint32_t stg_offset = stg_base_offset; - const uint32_t num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6:1; - const uint32_t num_slices = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? img->cmn.num_slices : 1; - const sg_pixel_format fmt = img->cmn.pixel_format; - WGPUBufferCopyView src_view; - _sg_clear(&src_view, sizeof(src_view)); - src_view.buffer = stg_buf; - WGPUTextureCopyView dst_view; - _sg_clear(&dst_view, sizeof(dst_view)); - dst_view.texture = img->wgpu.tex; - WGPUExtent3D extent; - _sg_clear(&extent, sizeof(extent)); - - for (uint32_t face_index = 0; face_index < num_faces; face_index++) { - for (uint32_t mip_index = 0; mip_index < (uint32_t)img->cmn.num_mipmaps; mip_index++) { - SOKOL_ASSERT(data->subimage[face_index][mip_index].ptr); - SOKOL_ASSERT(data->subimage[face_index][mip_index].size > 0); - const uint8_t* src_base_ptr = (const uint8_t*)data->subimage[face_index][mip_index].ptr; - SOKOL_ASSERT(src_base_ptr); - uint8_t* dst_base_ptr = stg_base_ptr + stg_offset; - - const uint32_t mip_width = _sg_miplevel_dim(img->cmn.width, mip_index); - const uint32_t mip_height = _sg_miplevel_dim(img->cmn.height, mip_index); - const uint32_t mip_depth = (img->cmn.type == SG_IMAGETYPE_3D) ? _sg_miplevel_dim(img->cmn.num_slices, mip_index) : 1; - const uint32_t num_rows = _sg_num_rows(fmt, mip_height); - const uint32_t src_bytes_per_row = _sg_row_pitch(fmt, mip_width, 1); - const uint32_t dst_bytes_per_row = _sg_row_pitch(fmt, mip_width, _SG_WGPU_ROWPITCH_ALIGN); - const uint32_t src_bytes_per_slice = _sg_surface_pitch(fmt, mip_width, mip_height, 1); - const uint32_t dst_bytes_per_slice = _sg_surface_pitch(fmt, mip_width, mip_height, _SG_WGPU_ROWPITCH_ALIGN); - SOKOL_ASSERT((uint32_t)data->subimage[face_index][mip_index].size == (src_bytes_per_slice * num_slices)); - SOKOL_ASSERT(src_bytes_per_row <= dst_bytes_per_row); - SOKOL_ASSERT(src_bytes_per_slice == (src_bytes_per_row * num_rows)); - SOKOL_ASSERT(dst_bytes_per_slice == (dst_bytes_per_row * num_rows)); - _SOKOL_UNUSED(src_bytes_per_slice); - - // copy data into mapped staging buffer - if (src_bytes_per_row == dst_bytes_per_row) { - // can do a single memcpy - uint32_t num_bytes = data->subimage[face_index][mip_index].size; - memcpy(dst_base_ptr, src_base_ptr, num_bytes); - } else { - // src/dst pitch doesn't match, need to copy row by row - uint8_t* dst_ptr = dst_base_ptr; - const uint8_t* src_ptr = src_base_ptr; - for (uint32_t slice_index = 0; slice_index < num_slices; slice_index++) { - SOKOL_ASSERT(dst_ptr == dst_base_ptr + slice_index * dst_bytes_per_slice); - for (uint32_t row_index = 0; row_index < num_rows; row_index++) { - memcpy(dst_ptr, src_ptr, src_bytes_per_row); - src_ptr += src_bytes_per_row; - dst_ptr += dst_bytes_per_row; - } - } - } - - // record the staging copy operation into command encoder - src_view.imageHeight = mip_height; - src_view.rowPitch = dst_bytes_per_row; - dst_view.mipLevel = mip_index; - extent.width = mip_width; - extent.height = mip_height; - extent.depth = mip_depth; - SOKOL_ASSERT((img->cmn.type != SG_IMAGETYPE_CUBE) || (num_slices == 1)); - for (uint32_t slice_index = 0; slice_index < num_slices; slice_index++) { - const uint32_t layer_index = (img->cmn.type == SG_IMAGETYPE_ARRAY) ? slice_index : face_index; - src_view.offset = stg_offset; - dst_view.arrayLayer = layer_index; - wgpuCommandEncoderCopyBufferToTexture(_sg.wgpu.staging_cmd_enc, &src_view, &dst_view, &extent); - stg_offset += dst_bytes_per_slice; - SOKOL_ASSERT(stg_offset <= _sg.wgpu.staging.num_bytes); - } - } - } - SOKOL_ASSERT(stg_offset >= stg_base_offset); - return (stg_offset - stg_base_offset); -} -*/ - _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { SOKOL_ASSERT(desc); SOKOL_ASSERT(desc->context.wgpu.device); @@ -12644,118 +12548,100 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_buffer(_sg_buffer_t* buf) { } } -/* -_SOKOL_PRIVATE void _sg_wgpu_init_texdesc_common(WGPUTextureDescriptor* wgpu_tex_desc, const sg_image_desc* desc) { - wgpu_tex_desc->usage = WGPUTextureUsage_Sampled|WGPUTextureUsage_CopyDst; - wgpu_tex_desc->dimension = _sg_wgpu_tex_dim(desc->type); - wgpu_tex_desc->size.width = desc->width; - wgpu_tex_desc->size.height = desc->height; - if (desc->type == SG_IMAGETYPE_3D) { - wgpu_tex_desc->size.depth = desc->num_slices; - wgpu_tex_desc->arrayLayerCount = 1; - } else if (desc->type == SG_IMAGETYPE_CUBE) { - wgpu_tex_desc->size.depth = 1; - wgpu_tex_desc->arrayLayerCount = 6; - } else { - wgpu_tex_desc->size.depth = 1; - wgpu_tex_desc->arrayLayerCount = desc->num_slices; +_SOKOL_PRIVATE void _sg_wgpu_copy_image_data(const _sg_image_t* img, WGPUTexture wgpu_tex, const sg_image_data* data) { + WGPUTextureDataLayout wgpu_layout; + _sg_clear(&wgpu_layout, sizeof(wgpu_layout)); + WGPUImageCopyTexture wgpu_copy_tex; + _sg_clear(&wgpu_copy_tex, sizeof(wgpu_copy_tex)); + wgpu_copy_tex.texture = wgpu_tex; + wgpu_copy_tex.aspect = WGPUTextureAspect_All; + WGPUExtent3D wgpu_extent; + _sg_clear(&wgpu_extent, sizeof(wgpu_extent)); + for (int mip_level = 0; mip_level < img->cmn.num_mipmaps; mip_level++) { + wgpu_copy_tex.mipLevel = (uint32_t)mip_level; + const int mip_width = _sg_miplevel_dim(img->cmn.width, mip_level); + const int mip_height = _sg_miplevel_dim(img->cmn.height, mip_level); + int mip_slices; + switch (img->cmn.type) { + case SG_IMAGETYPE_CUBE: + mip_slices = 6; + break; + case SG_IMAGETYPE_3D: + mip_slices = _sg_miplevel_dim(img->cmn.num_slices, mip_level); + break; + default: + mip_slices = img->cmn.num_slices; + break; + } + const int row_pitch = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1); + const int num_rows = _sg_num_rows(img->cmn.pixel_format, mip_height); + wgpu_layout.offset = 0; + wgpu_layout.bytesPerRow = (uint32_t)row_pitch; + wgpu_layout.rowsPerImage = (uint32_t)num_rows; + wgpu_extent.width = (uint32_t)mip_width; + wgpu_extent.height = (uint32_t)mip_height; + wgpu_extent.depthOrArrayLayers = (uint32_t)mip_slices; + const sg_range* mip_data = &data->subimage[0][mip_level]; + wgpuQueueWriteTexture(_sg.wgpu.queue, &wgpu_copy_tex, mip_data->ptr, mip_data->size, &wgpu_layout, &wgpu_extent); } - wgpu_tex_desc->format = _sg_wgpu_textureformat(desc->pixel_format); - wgpu_tex_desc->mipLevelCount = desc->num_mipmaps; - wgpu_tex_desc->sampleCount = 1; } -*/ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const sg_image_desc* desc) { SOKOL_ASSERT(img && desc); - SOKOL_ASSERT(_sg.wgpu.dev); -/* - SOKOL_ASSERT(_sg.wgpu.staging_cmd_enc); - const bool injected = (0 != desc->wgpu_texture); - const bool is_msaa = desc->sample_count > 1; - WGPUTextureDescriptor wgpu_tex_desc; - _sg_clear(&wgpu_tex_desc, sizeof(wgpu_tex_desc)); - _sg_wgpu_init_texdesc_common(&wgpu_tex_desc, desc); - if (_sg_is_valid_rendertarget_depth_format(img->cmn.pixel_format)) { - SOKOL_ASSERT(img->cmn.render_target); - SOKOL_ASSERT(img->cmn.type == SG_IMAGETYPE_2D); - SOKOL_ASSERT(img->cmn.num_mipmaps == 1); - SOKOL_ASSERT(!injected); - wgpu_tex_desc.usage = WGPUTextureUsage_OutputAttachment; - wgpu_tex_desc.sampleCount = desc->sample_count; - img->wgpu.tex = wgpuDeviceCreateTexture(_sg.wgpu.dev, &wgpu_tex_desc); - SOKOL_ASSERT(img->wgpu.tex); + if (injected) { + img->wgpu.tex = (WGPUTexture)desc->wgpu_texture; + wgpuTextureReference(img->wgpu.tex); } else { - if (injected) { - img->wgpu.tex = (WGPUTexture) desc->wgpu_texture; - wgpuTextureReference(img->wgpu.tex); - } else { - if (img->cmn.render_target) { - wgpu_tex_desc.usage = WGPUTextureUsage_Sampled|WGPUTextureUsage_OutputAttachment; - } - img->wgpu.tex = wgpuDeviceCreateTexture(_sg.wgpu.dev, &wgpu_tex_desc); - SOKOL_ASSERT(img->wgpu.tex); - - // copy content into texture via a throw-away staging buffer - if (desc->usage == SG_USAGE_IMMUTABLE && !desc->render_target) { - WGPUBufferDescriptor wgpu_buf_desc; - _sg_clear(&wgpu_buf_desc, sizeof(wgpu_buf_desc)); - wgpu_buf_desc.size = _sg_wgpu_image_data_buffer_size(img); - wgpu_buf_desc.usage = WGPUBufferUsage_CopySrc|WGPUBufferUsage_CopyDst; - WGPUCreateBufferMappedResult map = wgpuDeviceCreateBufferMapped(_sg.wgpu.dev, &wgpu_buf_desc); - SOKOL_ASSERT(map.buffer && map.data); - uint32_t num_bytes = _sg_wgpu_copy_image_data(map.buffer, (uint8_t*)map.data, 0, img, &desc->data); - _SOKOL_UNUSED(num_bytes); - SOKOL_ASSERT(num_bytes == wgpu_buf_desc.size); - wgpuBufferUnmap(map.buffer); - wgpuBufferRelease(map.buffer); - } - } - - // create texture view object - WGPUTextureViewDescriptor wgpu_view_desc; - _sg_clear(&wgpu_view_desc, sizeof(wgpu_view_desc)); - wgpu_view_desc.dimension = _sg_wgpu_tex_viewdim(desc->type); - img->wgpu.tex_view = wgpuTextureCreateView(img->wgpu.tex, &wgpu_view_desc); - - if (desc->render_target && is_msaa) { - wgpu_tex_desc.dimension = WGPUTextureDimension_2D; - wgpu_tex_desc.size.depth = 1; - wgpu_tex_desc.arrayLayerCount = 1; - wgpu_tex_desc.mipLevelCount = 1; - wgpu_tex_desc.usage = WGPUTextureUsage_OutputAttachment; - wgpu_tex_desc.sampleCount = desc->sample_count; - img->wgpu.msaa_tex = wgpuDeviceCreateTexture(_sg.wgpu.dev, &wgpu_tex_desc); - SOKOL_ASSERT(img->wgpu.msaa_tex); + WGPUTextureDescriptor wgpu_tex_desc; + _sg_clear(&wgpu_tex_desc, sizeof(wgpu_tex_desc)); + wgpu_tex_desc.label = desc->label; + wgpu_tex_desc.usage = WGPUTextureUsage_TextureBinding|WGPUTextureUsage_CopyDst; + if (desc->render_target) { + wgpu_tex_desc.usage |= WGPUTextureUsage_RenderAttachment; + } + wgpu_tex_desc.dimension = _sg_wgpu_texture_dimension(desc->type); + wgpu_tex_desc.size.width = (uint32_t) desc->width; + wgpu_tex_desc.size.height = (uint32_t) desc->height; + wgpu_tex_desc.size.depthOrArrayLayers = (uint32_t) desc->num_slices; + wgpu_tex_desc.format = _sg_wgpu_textureformat(desc->pixel_format); + wgpu_tex_desc.mipLevelCount = (uint32_t) desc->num_mipmaps; + wgpu_tex_desc.sampleCount = (uint32_t) desc->sample_count; + img->wgpu.tex = wgpuDeviceCreateTexture(_sg.wgpu.dev, &wgpu_tex_desc); + if (0 == img->wgpu.tex) { + _SG_ERROR(WGPU_CREATE_TEXTURE_FAILED); + return SG_RESOURCESTATE_FAILED; } - - // create sampler via shared-sampler-cache - img->wgpu.sampler = _sg_wgpu_create_sampler(desc); - SOKOL_ASSERT(img->wgpu.sampler); + if ((img->cmn.usage == SG_USAGE_IMMUTABLE) && !img->cmn.render_target) { + _sg_wgpu_copy_image_data(img, img->wgpu.tex, &desc->data); + } + } + WGPUTextureViewDescriptor wgpu_texview_desc; + _sg_clear(&wgpu_texview_desc, sizeof(wgpu_texview_desc)); + wgpu_texview_desc.label = desc->label; + wgpu_texview_desc.dimension = _sg_wgpu_texture_view_dimension(img->cmn.type); + wgpu_texview_desc.mipLevelCount = (uint32_t)img->cmn.num_mipmaps; + wgpu_texview_desc.arrayLayerCount = (uint32_t)img->cmn.num_slices; + // FIXME: should aspect be DepthOnly for all depth texture formats? + wgpu_texview_desc.aspect = WGPUTextureAspect_All; + img->wgpu.view = wgpuTextureCreateView(img->wgpu.tex, &wgpu_texview_desc); + if (0 == img->wgpu.view) { + _SG_ERROR(WGPU_CREATE_TEXTURE_VIEW_FAILED); + return SG_RESOURCESTATE_FAILED; } -*/ return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_image(_sg_image_t* img) { SOKOL_ASSERT(img); -/* if (img->wgpu.tex) { wgpuTextureRelease(img->wgpu.tex); img->wgpu.tex = 0; } - if (img->wgpu.tex_view) { - wgpuTextureViewRelease(img->wgpu.tex_view); - img->wgpu.tex_view = 0; + if (img->wgpu.view) { + wgpuTextureViewRelease(img->wgpu.view); + img->wgpu.view = 0; } - if (img->wgpu.msaa_tex) { - wgpuTextureRelease(img->wgpu.msaa_tex); - img->wgpu.msaa_tex = 0; - } - // NOTE: do *not* destroy the sampler from the shared-sampler-cache - img->wgpu.sampler = 0; -*/ } _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) { From dc250eb6b4316daea99f685893bf382a504600f8 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 14 Aug 2023 16:10:47 +0200 Subject: [PATCH 13/95] sokol_gfx.h wgpu: implement sampler create/destroy --- sokol_gfx.h | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 9b38a3f3d..8d5d9dd45 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2907,6 +2907,7 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(WGPU_CREATE_BUFFER_FAILED, "wgpuDeviceCreateBuffer() failed") \ _SG_LOGITEM_XMACRO(WGPU_CREATE_TEXTURE_FAILED, "wgpuDeviceCreateTexture() failed") \ _SG_LOGITEM_XMACRO(WGPU_CREATE_TEXTURE_VIEW_FAILED, "wgpuTextureCreateView() failed") \ + _SG_LOGITEM_XMACRO(WGPU_CREATE_SAMPLER_FAILED, "wgpuDeviceCreateSampler() failed") \ _SG_LOGITEM_XMACRO(WGPU_CREATE_SHADER_MODULE_FAILED, "wgpuDeviceCreateShaderModule() failed") \ _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_IMAGES, "shader uses too many sampled images on shader stage (wgpu)") \ _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_SAMPLERS, "shader uses too many samplers on shader stage (wgpu)") \ @@ -12021,7 +12022,7 @@ _SOKOL_PRIVATE WGPUSamplerBindingType _sg_wgpu_sampler_binding_type(sg_sampler_t } } -_SOKOL_PRIVATE WGPUAddressMode _sg_wgpu_sampler_addrmode(sg_wrap m) { +_SOKOL_PRIVATE WGPUAddressMode _sg_wgpu_sampler_address_mode(sg_wrap m) { switch (m) { case SG_WRAP_REPEAT: return WGPUAddressMode_Repeat; @@ -12048,16 +12049,16 @@ _SOKOL_PRIVATE WGPUFilterMode _sg_wgpu_sampler_minmag_filter(sg_filter f) { } } -_SOKOL_PRIVATE WGPUFilterMode _sg_wgpu_sampler_mipmap_filter(sg_filter f) { +_SOKOL_PRIVATE WGPUMipmapFilterMode _sg_wgpu_sampler_mipmap_filter(sg_filter f) { switch (f) { case SG_FILTER_NONE: case SG_FILTER_NEAREST: - return WGPUFilterMode_Nearest; + return WGPUMipmapFilterMode_Nearest; case SG_FILTER_LINEAR: - return WGPUFilterMode_Linear; + return WGPUMipmapFilterMode_Linear; default: SOKOL_UNREACHABLE; - return WGPUFilterMode_Force32; + return WGPUMipmapFilterMode_Force32; } } @@ -12468,7 +12469,7 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { SOKOL_ASSERT(_sg.wgpu.empty_bind_group); wgpuBindGroupLayoutRelease(empty_bgl); - // create initial per-frame command encoders + // create initial per-frame command encoder WGPUCommandEncoderDescriptor cmd_enc_desc; _sg_clear(&cmd_enc_desc, sizeof(cmd_enc_desc)); _sg.wgpu.render_cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); @@ -12647,13 +12648,36 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_image(_sg_image_t* img) { _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) { SOKOL_ASSERT(smp && desc); SOKOL_ASSERT(_sg.wgpu.dev); - // FIXME + WGPUSamplerDescriptor wgpu_desc; + _sg_clear(&wgpu_desc, sizeof(wgpu_desc)); + wgpu_desc.label = desc->label; + wgpu_desc.addressModeU = _sg_wgpu_sampler_address_mode(desc->wrap_u); + wgpu_desc.addressModeV = _sg_wgpu_sampler_address_mode(desc->wrap_v); + wgpu_desc.addressModeW = _sg_wgpu_sampler_address_mode(desc->wrap_w); + wgpu_desc.magFilter = _sg_wgpu_sampler_minmag_filter(desc->mag_filter); + wgpu_desc.minFilter = _sg_wgpu_sampler_minmag_filter(desc->min_filter); + wgpu_desc.mipmapFilter = _sg_wgpu_sampler_mipmap_filter(desc->mipmap_filter); + wgpu_desc.lodMinClamp = desc->min_lod; + wgpu_desc.lodMaxClamp = desc->max_lod; + wgpu_desc.compare = _sg_wgpu_comparefunc(desc->compare); + if (wgpu_desc.compare == WGPUCompareFunction_Never) { + wgpu_desc.compare = WGPUCompareFunction_Undefined; + } + wgpu_desc.maxAnisotropy = (uint16_t)desc->max_anisotropy; + smp->wgpu.smp = wgpuDeviceCreateSampler(_sg.wgpu.dev, &wgpu_desc); + if (0 == smp->wgpu.smp) { + _SG_ERROR(WGPU_CREATE_SAMPLER_FAILED); + return SG_RESOURCESTATE_FAILED; + } return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_sampler(_sg_sampler_t* smp) { SOKOL_ASSERT(smp); - // FIXME + if (smp->wgpu.smp) { + wgpuSamplerReference(smp->wgpu.smp); + smp->wgpu.smp = 0; + } } _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const sg_shader_desc* desc) { From 233f6888defb8cfc70028e53ae4047aa6fc5bac9 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 15 Aug 2023 19:55:16 +0200 Subject: [PATCH 14/95] sokol_gfx.h wgpu: implement pass create/destroy --- sokol_gfx.h | 178 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 103 insertions(+), 75 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 8d5d9dd45..f8d167205 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2911,7 +2911,10 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(WGPU_CREATE_SHADER_MODULE_FAILED, "wgpuDeviceCreateShaderModule() failed") \ _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_IMAGES, "shader uses too many sampled images on shader stage (wgpu)") \ _SG_LOGITEM_XMACRO(WGPU_SHADER_TOO_MANY_SAMPLERS, "shader uses too many samplers on shader stage (wgpu)") \ - _SG_LOGITEM_XMACRO(WGPU_SHADER_CREATE_BINDGROUP_LAYOUT_FAILED, "wgpuDeviceCreateBindGroupLayout for shader stage failed") \ + _SG_LOGITEM_XMACRO(WGPU_SHADER_CREATE_BINDGROUP_LAYOUT_FAILED, "wgpuDeviceCreateBindGroupLayout() for shader stage failed") \ + _SG_LOGITEM_XMACRO(WGPU_CREATE_PIPELINE_LAYOUT_FAILED, "wgpuDeviceCreatePipelineLayout() failed") \ + _SG_LOGITEM_XMACRO(WGPU_CREATE_RENDER_PIPELINE_FAILED, "wgpuDeviceCreateRenderPipeline() failed") \ + _SG_LOGITEM_XMACRO(WGPU_PASS_CREATE_TEXTURE_VIEW_FAILED, "wgpuTextureCreateView() failed in create pass") \ _SG_LOGITEM_XMACRO(UNINIT_BUFFER_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in buffer uninit (must be same as for creation)") \ _SG_LOGITEM_XMACRO(UNINIT_IMAGE_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in image uninit (must be same as for creation)") \ _SG_LOGITEM_XMACRO(UNINIT_SAMPLER_ACTIVE_CONTEXT_MISMATCH, "active context mismatch in sampler uninit (must be same as for creation)") \ @@ -11959,8 +11962,10 @@ _SOKOL_PRIVATE WGPUBufferUsageFlags _sg_wgpu_buffer_usage(sg_buffer_type t, sg_u return res; } -_SOKOL_PRIVATE WGPULoadOp _sg_wgpu_load_op(sg_load_action a) { - switch (a) { +_SOKOL_PRIVATE WGPULoadOp _sg_wgpu_load_op(WGPUTextureView view, sg_load_action a) { + if (0 == view) { + return WGPULoadOp_Undefined; + } else switch (a) { case SG_LOADACTION_CLEAR: case SG_LOADACTION_DONTCARE: return WGPULoadOp_Clear; @@ -11972,8 +11977,10 @@ _SOKOL_PRIVATE WGPULoadOp _sg_wgpu_load_op(sg_load_action a) { } } -_SOKOL_PRIVATE WGPUStoreOp _sg_wgpu_store_op(sg_store_action a) { - switch (a) { +_SOKOL_PRIVATE WGPUStoreOp _sg_wgpu_store_op(WGPUTextureView view, sg_store_action a) { + if (0 == view) { + return WGPUStoreOp_Undefined; + } else switch (a) { case SG_STOREACTION_STORE: return WGPUStoreOp_Store; case SG_STOREACTION_DONTCARE: @@ -12793,6 +12800,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ wgpu_pl_desc.bindGroupLayoutCount = _SG_WGPU_NUM_BINDGROUPS; wgpu_pl_desc.bindGroupLayouts = &wgpu_bgl[0]; const WGPUPipelineLayout wgpu_pip_layout = wgpuDeviceCreatePipelineLayout(_sg.wgpu.dev, &wgpu_pl_desc); + if (0 == wgpu_pip_layout) { + _SG_ERROR(WGPU_CREATE_PIPELINE_LAYOUT_FAILED); + return SG_RESOURCESTATE_FAILED; + } SOKOL_ASSERT(wgpu_pip_layout); WGPUVertexBufferLayout wgpu_vb_layouts[SG_MAX_VERTEX_BUFFERS]; @@ -12888,9 +12899,11 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ wgpu_pip_desc.fragment = &wgpu_frag_state; } pip->wgpu.pip = wgpuDeviceCreateRenderPipeline(_sg.wgpu.dev, &wgpu_pip_desc); - SOKOL_ASSERT(0 != pip->wgpu.pip); wgpuPipelineLayoutRelease(wgpu_pip_layout); - + if (0 == pip->wgpu.pip) { + _SG_ERROR(WGPU_CREATE_RENDER_PIPELINE_FAILED); + return SG_RESOURCESTATE_FAILED; + } return SG_RESOURCESTATE_VALID; } @@ -12909,80 +12922,90 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_pipeline(_sg_pipeline_t* pip) { _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pass(_sg_pass_t* pass, _sg_image_t** color_images, _sg_image_t** resolve_images, _sg_image_t* ds_img, const sg_pass_desc* desc) { SOKOL_ASSERT(pass && desc); SOKOL_ASSERT(color_images && resolve_images); -/* - // copy image pointers and create render-texture views - const sg_pass_attachment_desc* att_desc; - for (uint32_t i = 0; i < pass->cmn.num_color_atts; i++) { - att_desc = &desc->color_attachments[i]; - if (att_desc->image.id != SG_INVALID_ID) { - SOKOL_ASSERT(att_desc->image.id != SG_INVALID_ID); - SOKOL_ASSERT(0 == pass->wgpu.color_atts[i].image); - _sg_image_t* img = att_images[i]; - SOKOL_ASSERT(img && (img->slot.id == att_desc->image.id)); - SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(img->cmn.pixel_format)); - pass->wgpu.color_atts[i].image = img; - // create a render-texture-view to render into the right sub-surface - const bool is_msaa = img->cmn.sample_count > 1; - WGPUTextureViewDescriptor view_desc; - _sg_clear(&view_desc, sizeof(view_desc)); - view_desc.baseMipLevel = is_msaa ? 0 : att_desc->mip_level; - view_desc.mipLevelCount = 1; - view_desc.baseArrayLayer = is_msaa ? 0 : att_desc->slice; - view_desc.arrayLayerCount = 1; - WGPUTexture wgpu_tex = is_msaa ? img->wgpu.msaa_tex : img->wgpu.tex; - SOKOL_ASSERT(wgpu_tex); - pass->wgpu.color_atts[i].render_tex_view = wgpuTextureCreateView(wgpu_tex, &view_desc); - SOKOL_ASSERT(pass->wgpu.color_atts[i].render_tex_view); - // ... and if needed a separate resolve texture view - if (is_msaa) { - view_desc.baseMipLevel = att_desc->mip_level; - view_desc.baseArrayLayer = att_desc->slice; - WGPUTexture wgpu_tex = img->wgpu.tex; - pass->wgpu.color_atts[i].resolve_tex_view = wgpuTextureCreateView(wgpu_tex, &view_desc); - SOKOL_ASSERT(pass->wgpu.color_atts[i].resolve_tex_view); + + // copy image pointers and create renderable wgpu texture views + for (int i = 0; i < pass->cmn.num_color_atts; i++) { + const sg_pass_attachment_desc* color_desc = &desc->color_attachments[i]; + _SOKOL_UNUSED(color_desc); + SOKOL_ASSERT(color_desc->image.id != SG_INVALID_ID); + SOKOL_ASSERT(0 == pass->wgpu.color_atts[i].image); + SOKOL_ASSERT(color_images[i] && (color_images[i]->slot.id == color_desc->image.id)); + SOKOL_ASSERT(_sg_is_valid_rendertarget_color_format(color_images[i]->cmn.pixel_format)); + SOKOL_ASSERT(color_images[i]->wgpu.tex); + pass->wgpu.color_atts[i].image = color_images[i]; + + WGPUTextureViewDescriptor wgpu_color_view_desc; + _sg_clear(&wgpu_color_view_desc, sizeof(wgpu_color_view_desc)); + wgpu_color_view_desc.baseMipLevel = (uint32_t) color_desc->mip_level; + wgpu_color_view_desc.mipLevelCount = 1; + wgpu_color_view_desc.baseArrayLayer = (uint32_t) color_desc->slice; + wgpu_color_view_desc.arrayLayerCount = 1; + pass->wgpu.color_atts[i].view = wgpuTextureCreateView(color_images[i]->wgpu.tex, &wgpu_color_view_desc); + if (0 == pass->wgpu.color_atts[i].view) { + _SG_ERROR(WGPU_PASS_CREATE_TEXTURE_VIEW_FAILED); + return SG_RESOURCESTATE_FAILED; + } + + const sg_pass_attachment_desc* resolve_desc = &desc->resolve_attachments[i]; + if (resolve_desc->image.id != SG_INVALID_ID) { + SOKOL_ASSERT(0 == pass->wgpu.resolve_atts[i].image); + SOKOL_ASSERT(resolve_images[i] && (resolve_images[i]->slot.id == resolve_desc->image.id)); + SOKOL_ASSERT(color_images[i] && (color_images[i]->cmn.pixel_format == resolve_images[i]->cmn.pixel_format)); + SOKOL_ASSERT(resolve_images[i]->wgpu.tex); + pass->wgpu.resolve_atts[i].image = resolve_images[i]; + + WGPUTextureViewDescriptor wgpu_resolve_view_desc; + _sg_clear(&wgpu_resolve_view_desc, sizeof(wgpu_resolve_view_desc)); + wgpu_resolve_view_desc.baseMipLevel = (uint32_t) resolve_desc->mip_level; + wgpu_resolve_view_desc.mipLevelCount = 1; + wgpu_resolve_view_desc.baseArrayLayer = (uint32_t) resolve_desc->slice; + wgpu_resolve_view_desc.arrayLayerCount = 1; + pass->wgpu.resolve_atts[i].view = wgpuTextureCreateView(resolve_images[i]->wgpu.tex, &wgpu_resolve_view_desc); + if (0 == pass->wgpu.resolve_atts[i].view) { + _SG_ERROR(WGPU_PASS_CREATE_TEXTURE_VIEW_FAILED); + return SG_RESOURCESTATE_FAILED; } } } SOKOL_ASSERT(0 == pass->wgpu.ds_att.image); - att_desc = &desc->depth_stencil_attachment; - if (att_desc->image.id != SG_INVALID_ID) { - const int ds_img_index = SG_MAX_COLOR_ATTACHMENTS; - SOKOL_ASSERT(att_images[ds_img_index] && (att_images[ds_img_index]->slot.id == att_desc->image.id)); - SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(att_images[ds_img_index]->cmn.pixel_format)); - _sg_image_t* ds_img = att_images[ds_img_index]; + const sg_pass_attachment_desc* ds_desc = &desc->depth_stencil_attachment; + if (ds_desc->image.id != SG_INVALID_ID) { + SOKOL_ASSERT(ds_img && (ds_img->slot.id == ds_desc->image.id)); + SOKOL_ASSERT(_sg_is_valid_rendertarget_depth_format(ds_img->cmn.pixel_format)); + SOKOL_ASSERT(ds_img->wgpu.tex); pass->wgpu.ds_att.image = ds_img; - // create a render-texture view - SOKOL_ASSERT(0 == att_desc->mip_level); - SOKOL_ASSERT(0 == att_desc->slice); - WGPUTextureViewDescriptor view_desc; - _sg_clear(&view_desc, sizeof(view_desc)); - WGPUTexture wgpu_tex = ds_img->wgpu.tex; - SOKOL_ASSERT(wgpu_tex); - pass->wgpu.ds_att.render_tex_view = wgpuTextureCreateView(wgpu_tex, &view_desc); - SOKOL_ASSERT(pass->wgpu.ds_att.render_tex_view); + + WGPUTextureViewDescriptor wgpu_ds_view_desc; + _sg_clear(&wgpu_ds_view_desc, sizeof(wgpu_ds_view_desc)); + wgpu_ds_view_desc.baseMipLevel = (uint32_t) ds_desc->mip_level; + wgpu_ds_view_desc.mipLevelCount = 1; + wgpu_ds_view_desc.baseArrayLayer = (uint32_t) ds_desc->slice; + wgpu_ds_view_desc.arrayLayerCount = 1; + pass->wgpu.ds_att.view = wgpuTextureCreateView(ds_img->wgpu.tex, &wgpu_ds_view_desc); + if (0 == pass->wgpu.ds_att.view) { + _SG_ERROR(WGPU_PASS_CREATE_TEXTURE_VIEW_FAILED); + return SG_RESOURCESTATE_FAILED; + } } -*/ return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_pass(_sg_pass_t* pass) { SOKOL_ASSERT(pass); -/* - for (uint32_t i = 0; i < pass->cmn.num_color_atts; i++) { - if (pass->wgpu.color_atts[i].render_tex_view) { - wgpuTextureViewRelease(pass->wgpu.color_atts[i].render_tex_view); - pass->wgpu.color_atts[i].render_tex_view = 0; + for (int i = 0; i < pass->cmn.num_color_atts; i++) { + if (pass->wgpu.color_atts[i].view) { + wgpuTextureViewRelease(pass->wgpu.color_atts[i].view); + pass->wgpu.color_atts[i].view = 0; } - if (pass->wgpu.color_atts[i].resolve_tex_view) { - wgpuTextureViewRelease(pass->wgpu.color_atts[i].resolve_tex_view); - pass->wgpu.color_atts[i].resolve_tex_view = 0; + if (pass->wgpu.resolve_atts[i].view) { + wgpuTextureViewRelease(pass->wgpu.resolve_atts[i].view); + pass->wgpu.resolve_atts[i].view = 0; } } - if (pass->wgpu.ds_att.render_tex_view) { - wgpuTextureViewRelease(pass->wgpu.ds_att.render_tex_view); - pass->wgpu.ds_att.render_tex_view = 0; + if (pass->wgpu.ds_att.view) { + wgpuTextureViewRelease(pass->wgpu.ds_att.view); + pass->wgpu.ds_att.view = 0; } -*/ } _SOKOL_PRIVATE _sg_image_t* _sg_wgpu_pass_color_image(const _sg_pass_t* pass, int index) { @@ -13006,22 +13029,27 @@ _SOKOL_PRIVATE _sg_image_t* _sg_wgpu_pass_ds_image(const _sg_pass_t* pass) { _SOKOL_PRIVATE void _sg_wgpu_init_color_att(WGPURenderPassColorAttachment* wgpu_att, const sg_color_attachment_action* action, WGPUTextureView color_view, WGPUTextureView resolve_view) { wgpu_att->view = color_view; wgpu_att->resolveTarget = resolve_view; - wgpu_att->loadOp = _sg_wgpu_load_op(action->load_action); - wgpu_att->storeOp = _sg_wgpu_store_op(action->store_action); + wgpu_att->loadOp = _sg_wgpu_load_op(color_view, action->load_action); + wgpu_att->storeOp = _sg_wgpu_store_op(color_view, action->store_action); wgpu_att->clearValue.r = action->clear_value.r; wgpu_att->clearValue.g = action->clear_value.g; wgpu_att->clearValue.b = action->clear_value.b; wgpu_att->clearValue.a = action->clear_value.a; } -_SOKOL_PRIVATE void _sg_wgpu_init_ds_att(WGPURenderPassDepthStencilAttachment* wgpu_att, const sg_pass_action* action, WGPUTextureView view) { +_SOKOL_PRIVATE void _sg_wgpu_init_ds_att(WGPURenderPassDepthStencilAttachment* wgpu_att, const sg_pass_action* action, sg_pixel_format fmt, WGPUTextureView view) { wgpu_att->view = view; - wgpu_att->depthLoadOp = _sg_wgpu_load_op(action->depth.load_action); - wgpu_att->depthStoreOp = _sg_wgpu_store_op(action->depth.store_action); + wgpu_att->depthLoadOp = _sg_wgpu_load_op(view, action->depth.load_action); + wgpu_att->depthStoreOp = _sg_wgpu_store_op(view, action->depth.store_action); wgpu_att->depthClearValue = action->depth.clear_value; wgpu_att->depthReadOnly = false; - wgpu_att->stencilLoadOp = _sg_wgpu_load_op(action->stencil.load_action); - wgpu_att->stencilStoreOp = _sg_wgpu_store_op(action->stencil.store_action); + if (_sg_is_depth_stencil_format(fmt)) { + wgpu_att->stencilLoadOp = _sg_wgpu_load_op(view, action->stencil.load_action); + wgpu_att->stencilStoreOp = _sg_wgpu_store_op(view, action->stencil.store_action); + } else { + wgpu_att->stencilLoadOp = WGPULoadOp_Undefined; + wgpu_att->stencilStoreOp = WGPUStoreOp_Undefined; + } wgpu_att->stencilClearValue = action->stencil.clear_value; wgpu_att->stencilReadOnly = false; } @@ -13055,7 +13083,7 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* wgpu_pass_desc.colorAttachmentCount = (size_t)pass->cmn.num_color_atts; wgpu_pass_desc.colorAttachments = &wgpu_color_att[0]; if (pass->wgpu.ds_att.image) { - _sg_wgpu_init_ds_att(&wgpu_ds_att, action, pass->wgpu.ds_att.view); + _sg_wgpu_init_ds_att(&wgpu_ds_att, action, pass->wgpu.ds_att.image->cmn.pixel_format, pass->wgpu.ds_att.view); wgpu_pass_desc.depthStencilAttachment = &wgpu_ds_att; } } else { @@ -13066,7 +13094,7 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* wgpu_pass_desc.colorAttachmentCount = 1; wgpu_pass_desc.colorAttachments = &wgpu_color_att[0]; if (wgpu_depth_stencil_view) { - _sg_wgpu_init_ds_att(&wgpu_ds_att, action, wgpu_depth_stencil_view); + _sg_wgpu_init_ds_att(&wgpu_ds_att, action, _sg.desc.context.depth_format, wgpu_depth_stencil_view); } wgpu_pass_desc.depthStencilAttachment = &wgpu_ds_att; } From 7906e70c777c7fbe35f2e81f0dbd6ec49794e2cf Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 16 Aug 2023 00:30:33 +0200 Subject: [PATCH 15/95] sokol_gfx.h wgpu: fix pipeline desc linked struct lifetimes doh --- sokol_gfx.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index f8d167205..527f7ba6e 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12837,6 +12837,14 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ WGPURenderPipelineDescriptor wgpu_pip_desc; _sg_clear(&wgpu_pip_desc, sizeof(wgpu_pip_desc)); + WGPUDepthStencilState wgpu_ds_state; + _sg_clear(&wgpu_ds_state, sizeof(wgpu_ds_state)); + WGPUFragmentState wgpu_frag_state; + _sg_clear(&wgpu_frag_state, sizeof(wgpu_frag_state)); + WGPUColorTargetState wgpu_ctgt_state[SG_MAX_COLOR_ATTACHMENTS]; + _sg_clear(&wgpu_ctgt_state, sizeof(wgpu_ctgt_state)); + WGPUBlendState wgpu_blend_state[SG_MAX_COLOR_ATTACHMENTS]; + _sg_clear(&wgpu_blend_state, sizeof(wgpu_blend_state)); wgpu_pip_desc.label = desc->label; wgpu_pip_desc.layout = wgpu_pip_layout; wgpu_pip_desc.vertex.module = shd->wgpu.stage[SG_SHADERSTAGE_VS].module; @@ -12848,8 +12856,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ wgpu_pip_desc.primitive.frontFace = _sg_wgpu_frontface(desc->face_winding); wgpu_pip_desc.primitive.cullMode = _sg_wgpu_cullmode(desc->cull_mode); if (SG_PIXELFORMAT_NONE != desc->depth.pixel_format) { - WGPUDepthStencilState wgpu_ds_state; - _sg_clear(&wgpu_ds_state, sizeof(wgpu_ds_state)); wgpu_ds_state.format = _sg_wgpu_textureformat(desc->depth.pixel_format); wgpu_ds_state.depthWriteEnabled = desc->depth.write_enabled; wgpu_ds_state.depthCompare = _sg_wgpu_comparefunc(desc->depth.compare); @@ -12872,12 +12878,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ wgpu_pip_desc.multisample.mask = 0xFFFFFFFF; wgpu_pip_desc.multisample.alphaToCoverageEnabled = desc->alpha_to_coverage_enabled; if (desc->color_count > 0) { - WGPUFragmentState wgpu_frag_state; - _sg_clear(&wgpu_frag_state, sizeof(wgpu_frag_state)); - WGPUColorTargetState wgpu_ctgt_state[SG_MAX_COLOR_ATTACHMENTS]; - _sg_clear(&wgpu_ctgt_state, sizeof(wgpu_ctgt_state)); - WGPUBlendState wgpu_blend_state[SG_MAX_COLOR_ATTACHMENTS]; - _sg_clear(&wgpu_blend_state, sizeof(wgpu_blend_state)); wgpu_frag_state.module = shd->wgpu.stage[SG_SHADERSTAGE_FS].module; wgpu_frag_state.entryPoint = shd->wgpu.stage[SG_SHADERSTAGE_FS].entry.buf; wgpu_frag_state.targetCount = (size_t)desc->color_count; From 0341168249a65bb1c0aadd85c2c7085b28067cdb Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 17 Aug 2023 19:02:40 +0200 Subject: [PATCH 16/95] sokol_gfx.h wgpu: implement sg_update_buffer --- sokol_gfx.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 527f7ba6e..9e549c0d9 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12296,7 +12296,7 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { _sg.features.mrt_independent_write_mask = true; bool success = wgpuDeviceGetLimits(_sg.wgpu.dev, &_sg.wgpu.limits); - SOKOL_ASSERT(success); + SOKOL_ASSERT(success); _SOKOL_UNUSED(success); const WGPULimits* l = &_sg.wgpu.limits.limits; _sg.limits.max_image_size_2d = (int) l->maxTextureDimension2D; @@ -13307,14 +13307,13 @@ _SOKOL_PRIVATE void _sg_wgpu_draw(int base_element, int num_elements, int num_in } _SOKOL_PRIVATE void _sg_wgpu_update_buffer(_sg_buffer_t* buf, const sg_range* data) { -/* - SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); - uint32_t copied_num_bytes = _sg_wgpu_staging_copy_to_buffer(buf->wgpu.buf, 0, data->ptr, data->size); - SOKOL_ASSERT(copied_num_bytes > 0); _SOKOL_UNUSED(copied_num_bytes); -*/ + SOKOL_ASSERT(data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(buf); + wgpuQueueWriteBuffer(_sg.wgpu.queue, buf->wgpu.buf, 0, data->ptr, data->size); } _SOKOL_PRIVATE int _sg_wgpu_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { +SOKOL_ASSERT(false); return 0; /* SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); @@ -13326,6 +13325,7 @@ return 0; } _SOKOL_PRIVATE void _sg_wgpu_update_image(_sg_image_t* img, const sg_image_data* data) { +SOKOL_ASSERT(false); /* SOKOL_ASSERT(img && data); bool success = _sg_wgpu_staging_copy_to_texture(img, data); From 97fafacb5b38ceb481ae560595d4b9d700cb6396 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 19 Aug 2023 14:25:29 +0200 Subject: [PATCH 17/95] sokol_gfx.h wgpu: implement sg_update_image --- sokol_gfx.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 9e549c0d9..6632b07e5 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -13325,13 +13325,8 @@ return 0; } _SOKOL_PRIVATE void _sg_wgpu_update_image(_sg_image_t* img, const sg_image_data* data) { -SOKOL_ASSERT(false); - /* SOKOL_ASSERT(img && data); - bool success = _sg_wgpu_staging_copy_to_texture(img, data); - SOKOL_ASSERT(success); - _SOKOL_UNUSED(success); -*/ + _sg_wgpu_copy_image_data(img, img->wgpu.tex, data); } #endif From 61d36f21935f0f4e5b6f0c6b5ecf151eaeaac679 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 20 Aug 2023 18:54:31 +0200 Subject: [PATCH 18/95] sokol_gfx.h wgpu: implement sg_append_buffer --- sokol_gfx.h | 65 ++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 6632b07e5..1f88af68b 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -5347,6 +5347,10 @@ _SOKOL_PRIVATE uint64_t _sg_roundup_u64(uint64_t val, uint64_t round_to) { return (val+(round_to-1)) & ~(round_to-1); } +_SOKOL_PRIVATE bool _sg_multiple_u64(uint64_t val, uint64_t of) { + return (val & (of-1)) == 0; +} + /* return row pitch for an image see ComputePitch in https://github.com/microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexUtil.cpp @@ -5795,22 +5799,22 @@ _SOKOL_PRIVATE void _sg_dummy_draw(int base_element, int num_elements, int num_i _SOKOL_PRIVATE void _sg_dummy_update_buffer(_sg_buffer_t* buf, const sg_range* data) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); _SOKOL_UNUSED(data); if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; } } -_SOKOL_PRIVATE int _sg_dummy_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { +_SOKOL_PRIVATE void _sg_dummy_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); _SOKOL_UNUSED(data); if (new_frame) { if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; } } - // NOTE: this is a requirement from WebGPU, but we want identical behaviour across all backend - return _sg_roundup((int)data->size, 4); } _SOKOL_PRIVATE void _sg_dummy_update_image(_sg_image_t* img, const sg_image_data* data) { @@ -8273,6 +8277,7 @@ _SOKOL_PRIVATE void _sg_gl_commit(void) { _SOKOL_PRIVATE void _sg_gl_update_buffer(_sg_buffer_t* buf, const sg_range* data) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); // only one update per buffer per frame allowed if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; @@ -8289,8 +8294,9 @@ _SOKOL_PRIVATE void _sg_gl_update_buffer(_sg_buffer_t* buf, const sg_range* data _SG_GL_CHECK_ERROR(); } -_SOKOL_PRIVATE int _sg_gl_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { +_SOKOL_PRIVATE void _sg_gl_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); if (new_frame) { if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; @@ -8306,8 +8312,6 @@ _SOKOL_PRIVATE int _sg_gl_append_buffer(_sg_buffer_t* buf, const sg_range* data, glBufferSubData(gl_tgt, buf->cmn.append_pos, (GLsizeiptr)data->size, data->ptr); _sg_gl_cache_restore_buffer_binding(gl_tgt); _SG_GL_CHECK_ERROR(); - // NOTE: this is a requirement from WebGPU, but we want identical behaviour across all backend - return _sg_roundup((int)data->size, 4); } _SOKOL_PRIVATE void _sg_gl_update_image(_sg_image_t* img, const sg_image_data* data) { @@ -10149,6 +10153,7 @@ _SOKOL_PRIVATE void _sg_d3d11_commit(void) { _SOKOL_PRIVATE void _sg_d3d11_update_buffer(_sg_buffer_t* buf, const sg_range* data) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); SOKOL_ASSERT(_sg.d3d11.ctx); SOKOL_ASSERT(buf->d3d11.buf); D3D11_MAPPED_SUBRESOURCE d3d11_msr; @@ -10161,8 +10166,9 @@ _SOKOL_PRIVATE void _sg_d3d11_update_buffer(_sg_buffer_t* buf, const sg_range* d } } -_SOKOL_PRIVATE int _sg_d3d11_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { +_SOKOL_PRIVATE void _sg_d3d11_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); SOKOL_ASSERT(_sg.d3d11.ctx); SOKOL_ASSERT(buf->d3d11.buf); D3D11_MAP map_type = new_frame ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE; @@ -10175,8 +10181,6 @@ _SOKOL_PRIVATE int _sg_d3d11_append_buffer(_sg_buffer_t* buf, const sg_range* da } else { _SG_ERROR(D3D11_MAP_FOR_APPEND_BUFFER_FAILED); } - // NOTE: this alignment is a requirement from WebGPU, but we want identical behaviour across all backend - return _sg_roundup((int)data->size, 4); } _SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_data* data) { @@ -11897,6 +11901,7 @@ _SOKOL_PRIVATE void _sg_mtl_draw(int base_element, int num_elements, int num_ins _SOKOL_PRIVATE void _sg_mtl_update_buffer(_sg_buffer_t* buf, const sg_range* data) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; } @@ -11910,8 +11915,9 @@ _SOKOL_PRIVATE void _sg_mtl_update_buffer(_sg_buffer_t* buf, const sg_range* dat #endif } -_SOKOL_PRIVATE int _sg_mtl_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { +_SOKOL_PRIVATE void _sg_mtl_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); if (new_frame) { if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; @@ -11926,8 +11932,6 @@ _SOKOL_PRIVATE int _sg_mtl_append_buffer(_sg_buffer_t* buf, const sg_range* data [mtl_buf didModifyRange:NSMakeRange((NSUInteger)buf->cmn.append_pos, (NSUInteger)data->size)]; } #endif - // NOTE: this is a requirement from WebGPU, but we want identical behaviour across all backends - return _sg_roundup((int)data->size, 4); } _SOKOL_PRIVATE void _sg_mtl_update_image(_sg_image_t* img, const sg_image_data* data) { @@ -13308,20 +13312,17 @@ _SOKOL_PRIVATE void _sg_wgpu_draw(int base_element, int num_elements, int num_in _SOKOL_PRIVATE void _sg_wgpu_update_buffer(_sg_buffer_t* buf, const sg_range* data) { SOKOL_ASSERT(data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); SOKOL_ASSERT(buf); wgpuQueueWriteBuffer(_sg.wgpu.queue, buf->wgpu.buf, 0, data->ptr, data->size); } -_SOKOL_PRIVATE int _sg_wgpu_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { -SOKOL_ASSERT(false); -return 0; -/* - SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); +_SOKOL_PRIVATE void _sg_wgpu_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { + SOKOL_ASSERT(data && data->ptr && (data->size > 0)); + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); + SOKOL_ASSERT(_sg_multiple_u64((uint64_t)buf->cmn.append_pos, 4)); _SOKOL_UNUSED(new_frame); - uint32_t copied_num_bytes = _sg_wgpu_staging_copy_to_buffer(buf->wgpu.buf, buf->cmn.append_pos, data->ptr, data->size); - SOKOL_ASSERT(copied_num_bytes > 0); _SOKOL_UNUSED(copied_num_bytes); - return (int)copied_num_bytes; -*/ + wgpuQueueWriteBuffer(_sg.wgpu.queue, buf->wgpu.buf, (uint64_t)buf->cmn.append_pos, data->ptr, data->size); } _SOKOL_PRIVATE void _sg_wgpu_update_image(_sg_image_t* img, const sg_image_data* data) { @@ -13841,17 +13842,17 @@ static inline void _sg_update_buffer(_sg_buffer_t* buf, const sg_range* data) { #endif } -static inline int _sg_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { +static inline void _sg_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { #if defined(_SOKOL_ANY_GL) - return _sg_gl_append_buffer(buf, data, new_frame); + _sg_gl_append_buffer(buf, data, new_frame); #elif defined(SOKOL_METAL) - return _sg_mtl_append_buffer(buf, data, new_frame); + _sg_mtl_append_buffer(buf, data, new_frame); #elif defined(SOKOL_D3D11) - return _sg_d3d11_append_buffer(buf, data, new_frame); + _sg_d3d11_append_buffer(buf, data, new_frame); #elif defined(SOKOL_WGPU) - return _sg_wgpu_append_buffer(buf, data, new_frame); + _sg_wgpu_append_buffer(buf, data, new_frame); #elif defined(SOKOL_DUMMY_BACKEND) - return _sg_dummy_append_buffer(buf, data, new_frame); + _sg_dummy_append_buffer(buf, data, new_frame); #else #error("INVALID BACKEND"); #endif @@ -14597,7 +14598,7 @@ _SOKOL_PRIVATE bool _sg_validate_pipeline_desc(const sg_pipeline_desc* desc) { if (l_state->stride == 0) { continue; } - _SG_VALIDATE((l_state->stride & 3) == 0, VALIDATE_PIPELINEDESC_LAYOUT_STRIDE4); + _SG_VALIDATE(_sg_multiple_u64((uint64_t)l_state->stride, 4), VALIDATE_PIPELINEDESC_LAYOUT_STRIDE4); } _SG_VALIDATE(desc->layout.attrs[0].format != SG_VERTEXFORMAT_INVALID, VALIDATE_PIPELINEDESC_NO_ATTRS); const _sg_shader_t* shd = _sg_lookup_shader(&_sg.pools, desc->shader.id); @@ -15016,6 +15017,7 @@ _SOKOL_PRIVATE bool _sg_validate_update_buffer(const _sg_buffer_t* buf, const sg _SG_VALIDATE(buf->cmn.size >= (int)data->size, VALIDATE_UPDATEBUF_SIZE); _SG_VALIDATE(buf->cmn.update_frame_index != _sg.frame_index, VALIDATE_UPDATEBUF_ONCE); _SG_VALIDATE(buf->cmn.append_frame_index != _sg.frame_index, VALIDATE_UPDATEBUF_APPEND); + // FIXME: data->size must be a multiple of 4 return _sg_validate_end(); #endif } @@ -15034,6 +15036,7 @@ _SOKOL_PRIVATE bool _sg_validate_append_buffer(const _sg_buffer_t* buf, const sg _SG_VALIDATE(buf->cmn.usage != SG_USAGE_IMMUTABLE, VALIDATE_APPENDBUF_USAGE); _SG_VALIDATE(buf->cmn.size >= (buf->cmn.append_pos + (int)data->size), VALIDATE_APPENDBUF_SIZE); _SG_VALIDATE(buf->cmn.update_frame_index != _sg.frame_index, VALIDATE_APPENDBUF_UPDATE); + // FIXME: data->size must be a multiple of 4 return _sg_validate_end(); #endif } @@ -16652,11 +16655,13 @@ SOKOL_API_IMPL int sg_append_buffer(sg_buffer buf_id, const sg_range* data) { const int start_pos = buf->cmn.append_pos; if (buf->slot.state == SG_RESOURCESTATE_VALID) { if (_sg_validate_append_buffer(buf, data)) { + SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); if (!buf->cmn.append_overflow && (data->size > 0)) { // update and append on same buffer in same frame not allowed SOKOL_ASSERT(buf->cmn.update_frame_index != _sg.frame_index); - int copied_num_bytes = _sg_append_buffer(buf, data, buf->cmn.append_frame_index != _sg.frame_index); - buf->cmn.append_pos += copied_num_bytes; + SOKOL_ASSERT(_sg_multiple_u64((uint64_t)buf->cmn.append_pos, 4)); + _sg_append_buffer(buf, data, buf->cmn.append_frame_index != _sg.frame_index); + buf->cmn.append_pos += (int)data->size; buf->cmn.append_frame_index = _sg.frame_index; } } From 3f00bf34cf11c22b71cef51b2f74d252456e96a8 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 21 Aug 2023 14:38:36 +0200 Subject: [PATCH 19/95] sokol_gfx.h wgpu: fix buffer updates for sizes not multiple of 4 --- sokol_gfx.h | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 1f88af68b..8cce079d6 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -5799,7 +5799,6 @@ _SOKOL_PRIVATE void _sg_dummy_draw(int base_element, int num_elements, int num_i _SOKOL_PRIVATE void _sg_dummy_update_buffer(_sg_buffer_t* buf, const sg_range* data) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); _SOKOL_UNUSED(data); if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; @@ -5808,7 +5807,6 @@ _SOKOL_PRIVATE void _sg_dummy_update_buffer(_sg_buffer_t* buf, const sg_range* d _SOKOL_PRIVATE void _sg_dummy_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); _SOKOL_UNUSED(data); if (new_frame) { if (++buf->cmn.active_slot >= buf->cmn.num_slots) { @@ -8277,7 +8275,6 @@ _SOKOL_PRIVATE void _sg_gl_commit(void) { _SOKOL_PRIVATE void _sg_gl_update_buffer(_sg_buffer_t* buf, const sg_range* data) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); // only one update per buffer per frame allowed if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; @@ -8296,7 +8293,6 @@ _SOKOL_PRIVATE void _sg_gl_update_buffer(_sg_buffer_t* buf, const sg_range* data _SOKOL_PRIVATE void _sg_gl_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); if (new_frame) { if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; @@ -10153,7 +10149,6 @@ _SOKOL_PRIVATE void _sg_d3d11_commit(void) { _SOKOL_PRIVATE void _sg_d3d11_update_buffer(_sg_buffer_t* buf, const sg_range* data) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); SOKOL_ASSERT(_sg.d3d11.ctx); SOKOL_ASSERT(buf->d3d11.buf); D3D11_MAPPED_SUBRESOURCE d3d11_msr; @@ -10168,7 +10163,6 @@ _SOKOL_PRIVATE void _sg_d3d11_update_buffer(_sg_buffer_t* buf, const sg_range* d _SOKOL_PRIVATE void _sg_d3d11_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); SOKOL_ASSERT(_sg.d3d11.ctx); SOKOL_ASSERT(buf->d3d11.buf); D3D11_MAP map_type = new_frame ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE; @@ -11901,7 +11895,6 @@ _SOKOL_PRIVATE void _sg_mtl_draw(int base_element, int num_elements, int num_ins _SOKOL_PRIVATE void _sg_mtl_update_buffer(_sg_buffer_t* buf, const sg_range* data) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; } @@ -11917,7 +11910,6 @@ _SOKOL_PRIVATE void _sg_mtl_update_buffer(_sg_buffer_t* buf, const sg_range* dat _SOKOL_PRIVATE void _sg_mtl_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); if (new_frame) { if (++buf->cmn.active_slot >= buf->cmn.num_slots) { buf->cmn.active_slot = 0; @@ -12560,6 +12552,26 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_buffer(_sg_buffer_t* buf) { } } +_SOKOL_PRIVATE void _sg_wgpu_copy_buffer_data(const _sg_buffer_t* buf, uint64_t offset, const sg_range* data) { + SOKOL_ASSERT((offset + data->size) <= (size_t)buf->cmn.size); + // WebGPU's write-buffer requires the size to be a multiple of four, so we may need to split the copy + // operation into two writeBuffer calls + uint64_t clamped_size = data->size & ~3UL; + uint64_t extra_size = data->size & 3UL; + SOKOL_ASSERT(extra_size < 4); + wgpuQueueWriteBuffer(_sg.wgpu.queue, buf->wgpu.buf, offset, data->ptr, clamped_size); + if (extra_size > 0) { + const uint64_t extra_src_offset = clamped_size; + const uint64_t extra_dst_offset = offset + clamped_size; + uint8_t extra_data[4] = { 0 }; + uint8_t* extra_src_ptr = ((uint8_t*)data->ptr) + extra_src_offset; + for (size_t i = 0; i < extra_size; i++) { + extra_data[i] = extra_src_ptr[i]; + } + wgpuQueueWriteBuffer(_sg.wgpu.queue, buf->wgpu.buf, extra_dst_offset, extra_src_ptr, 4); + } +} + _SOKOL_PRIVATE void _sg_wgpu_copy_image_data(const _sg_image_t* img, WGPUTexture wgpu_tex, const sg_image_data* data) { WGPUTextureDataLayout wgpu_layout; _sg_clear(&wgpu_layout, sizeof(wgpu_layout)); @@ -13312,17 +13324,14 @@ _SOKOL_PRIVATE void _sg_wgpu_draw(int base_element, int num_elements, int num_in _SOKOL_PRIVATE void _sg_wgpu_update_buffer(_sg_buffer_t* buf, const sg_range* data) { SOKOL_ASSERT(data && data->ptr && (data->size > 0)); - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); SOKOL_ASSERT(buf); - wgpuQueueWriteBuffer(_sg.wgpu.queue, buf->wgpu.buf, 0, data->ptr, data->size); + _sg_wgpu_copy_buffer_data(buf, 0, data); } _SOKOL_PRIVATE void _sg_wgpu_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { SOKOL_ASSERT(data && data->ptr && (data->size > 0)); - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); - SOKOL_ASSERT(_sg_multiple_u64((uint64_t)buf->cmn.append_pos, 4)); _SOKOL_UNUSED(new_frame); - wgpuQueueWriteBuffer(_sg.wgpu.queue, buf->wgpu.buf, (uint64_t)buf->cmn.append_pos, data->ptr, data->size); + _sg_wgpu_copy_buffer_data(buf, (uint64_t)buf->cmn.append_pos, data); } _SOKOL_PRIVATE void _sg_wgpu_update_image(_sg_image_t* img, const sg_image_data* data) { @@ -15017,7 +15026,6 @@ _SOKOL_PRIVATE bool _sg_validate_update_buffer(const _sg_buffer_t* buf, const sg _SG_VALIDATE(buf->cmn.size >= (int)data->size, VALIDATE_UPDATEBUF_SIZE); _SG_VALIDATE(buf->cmn.update_frame_index != _sg.frame_index, VALIDATE_UPDATEBUF_ONCE); _SG_VALIDATE(buf->cmn.append_frame_index != _sg.frame_index, VALIDATE_UPDATEBUF_APPEND); - // FIXME: data->size must be a multiple of 4 return _sg_validate_end(); #endif } @@ -15036,7 +15044,6 @@ _SOKOL_PRIVATE bool _sg_validate_append_buffer(const _sg_buffer_t* buf, const sg _SG_VALIDATE(buf->cmn.usage != SG_USAGE_IMMUTABLE, VALIDATE_APPENDBUF_USAGE); _SG_VALIDATE(buf->cmn.size >= (buf->cmn.append_pos + (int)data->size), VALIDATE_APPENDBUF_SIZE); _SG_VALIDATE(buf->cmn.update_frame_index != _sg.frame_index, VALIDATE_APPENDBUF_UPDATE); - // FIXME: data->size must be a multiple of 4 return _sg_validate_end(); #endif } @@ -16649,19 +16656,20 @@ SOKOL_API_IMPL int sg_append_buffer(sg_buffer buf_id, const sg_range* data) { buf->cmn.append_pos = 0; buf->cmn.append_overflow = false; } - if ((buf->cmn.append_pos + _sg_roundup((int)data->size, 4)) > buf->cmn.size) { + if ((buf->cmn.append_pos + data->size) > (size_t)buf->cmn.size) { buf->cmn.append_overflow = true; } const int start_pos = buf->cmn.append_pos; + // NOTE: the multiple-of-4 requirement for the buffer offset is coming + // from WebGPU, but we want identical behaviour between backends + SOKOL_ASSERT(_sg_multiple_u64((uint64_t)start_pos, 4)); if (buf->slot.state == SG_RESOURCESTATE_VALID) { if (_sg_validate_append_buffer(buf, data)) { - SOKOL_ASSERT(_sg_multiple_u64(data->size, 4)); if (!buf->cmn.append_overflow && (data->size > 0)) { // update and append on same buffer in same frame not allowed SOKOL_ASSERT(buf->cmn.update_frame_index != _sg.frame_index); - SOKOL_ASSERT(_sg_multiple_u64((uint64_t)buf->cmn.append_pos, 4)); _sg_append_buffer(buf, data, buf->cmn.append_frame_index != _sg.frame_index); - buf->cmn.append_pos += (int)data->size; + buf->cmn.append_pos += (int) _sg_roundup_u64(data->size, 4); buf->cmn.append_frame_index = _sg.frame_index; } } From d2d6d4762f2984e98eb5b4aeea7d806f933e46ea Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 21 Aug 2023 16:06:22 +0200 Subject: [PATCH 20/95] sokol_gfx.h wgpu: fix injected samplers, expose some wgpu objects in public api --- sokol_gfx.h | 115 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 36 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 8cce079d6..3c77db269 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -3451,12 +3451,18 @@ SOKOL_GFX_API_DECL void sg_discard_context(sg_context ctx_id); // D3D11: return ID3D11Device SOKOL_GFX_API_DECL const void* sg_d3d11_device(void); - // Metal: return __bridge-casted MTLDevice SOKOL_GFX_API_DECL const void* sg_mtl_device(void); - // Metal: return __bridge-casted MTLRenderCommandEncoder in current pass (or zero if outside pass) SOKOL_GFX_API_DECL const void* sg_mtl_render_command_encoder(void); +// WebGPU: return WGPUDevice object +SOKOL_GFX_API_DECL const void* sg_wgpu_device(void); +// WebGPU: return WGPUQueue object +SOKOL_GFX_API_DECL const void* sg_wgpu_queue(void); +// WebGPU: return this frame's WGPUCommandEncoder +SOKOL_GFX_API_DECL const void* sg_wgpu_command_encoder(void); +// WebGPU: return WGPURenderPassEncoder of currrent pass +SOKOL_GFX_API_DECL const void* sg_wgpu_render_pass_encoder(void); #ifdef __cplusplus } // extern "C" @@ -4910,7 +4916,7 @@ typedef struct { int cur_height; WGPUSupportedLimits limits; WGPUQueue queue; - WGPUCommandEncoder render_cmd_enc; + WGPUCommandEncoder cmd_enc; WGPURenderPassEncoder pass_enc; WGPUBindGroup empty_bind_group; const _sg_pipeline_t* cur_pipeline; @@ -12475,17 +12481,17 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { // create initial per-frame command encoder WGPUCommandEncoderDescriptor cmd_enc_desc; _sg_clear(&cmd_enc_desc, sizeof(cmd_enc_desc)); - _sg.wgpu.render_cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); - SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); + _sg.wgpu.cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); + SOKOL_ASSERT(_sg.wgpu.cmd_enc); } _SOKOL_PRIVATE void _sg_wgpu_discard_backend(void) { SOKOL_ASSERT(_sg.wgpu.valid); - SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); + SOKOL_ASSERT(_sg.wgpu.cmd_enc); _sg.wgpu.valid = false; _sg_wgpu_uniform_buffer_discard(); wgpuBindGroupRelease(_sg.wgpu.empty_bind_group); _sg.wgpu.empty_bind_group = 0; - wgpuCommandEncoderRelease(_sg.wgpu.render_cmd_enc); _sg.wgpu.render_cmd_enc = 0; + wgpuCommandEncoderRelease(_sg.wgpu.cmd_enc); _sg.wgpu.cmd_enc = 0; wgpuQueueRelease(_sg.wgpu.queue); _sg.wgpu.queue = 0; } @@ -12671,26 +12677,32 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_image(_sg_image_t* img) { _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) { SOKOL_ASSERT(smp && desc); SOKOL_ASSERT(_sg.wgpu.dev); - WGPUSamplerDescriptor wgpu_desc; - _sg_clear(&wgpu_desc, sizeof(wgpu_desc)); - wgpu_desc.label = desc->label; - wgpu_desc.addressModeU = _sg_wgpu_sampler_address_mode(desc->wrap_u); - wgpu_desc.addressModeV = _sg_wgpu_sampler_address_mode(desc->wrap_v); - wgpu_desc.addressModeW = _sg_wgpu_sampler_address_mode(desc->wrap_w); - wgpu_desc.magFilter = _sg_wgpu_sampler_minmag_filter(desc->mag_filter); - wgpu_desc.minFilter = _sg_wgpu_sampler_minmag_filter(desc->min_filter); - wgpu_desc.mipmapFilter = _sg_wgpu_sampler_mipmap_filter(desc->mipmap_filter); - wgpu_desc.lodMinClamp = desc->min_lod; - wgpu_desc.lodMaxClamp = desc->max_lod; - wgpu_desc.compare = _sg_wgpu_comparefunc(desc->compare); - if (wgpu_desc.compare == WGPUCompareFunction_Never) { - wgpu_desc.compare = WGPUCompareFunction_Undefined; - } - wgpu_desc.maxAnisotropy = (uint16_t)desc->max_anisotropy; - smp->wgpu.smp = wgpuDeviceCreateSampler(_sg.wgpu.dev, &wgpu_desc); - if (0 == smp->wgpu.smp) { - _SG_ERROR(WGPU_CREATE_SAMPLER_FAILED); - return SG_RESOURCESTATE_FAILED; + const bool injected = (0 != desc->wgpu_sampler); + if (injected) { + smp->wgpu.smp = (WGPUSampler) desc->wgpu_sampler; + wgpuSamplerReference(smp->wgpu.smp); + } else { + WGPUSamplerDescriptor wgpu_desc; + _sg_clear(&wgpu_desc, sizeof(wgpu_desc)); + wgpu_desc.label = desc->label; + wgpu_desc.addressModeU = _sg_wgpu_sampler_address_mode(desc->wrap_u); + wgpu_desc.addressModeV = _sg_wgpu_sampler_address_mode(desc->wrap_v); + wgpu_desc.addressModeW = _sg_wgpu_sampler_address_mode(desc->wrap_w); + wgpu_desc.magFilter = _sg_wgpu_sampler_minmag_filter(desc->mag_filter); + wgpu_desc.minFilter = _sg_wgpu_sampler_minmag_filter(desc->min_filter); + wgpu_desc.mipmapFilter = _sg_wgpu_sampler_mipmap_filter(desc->mipmap_filter); + wgpu_desc.lodMinClamp = desc->min_lod; + wgpu_desc.lodMaxClamp = desc->max_lod; + wgpu_desc.compare = _sg_wgpu_comparefunc(desc->compare); + if (wgpu_desc.compare == WGPUCompareFunction_Never) { + wgpu_desc.compare = WGPUCompareFunction_Undefined; + } + wgpu_desc.maxAnisotropy = (uint16_t)desc->max_anisotropy; + smp->wgpu.smp = wgpuDeviceCreateSampler(_sg.wgpu.dev, &wgpu_desc); + if (0 == smp->wgpu.smp) { + _SG_ERROR(WGPU_CREATE_SAMPLER_FAILED); + return SG_RESOURCESTATE_FAILED; + } } return SG_RESOURCESTATE_VALID; } @@ -13073,7 +13085,7 @@ _SOKOL_PRIVATE void _sg_wgpu_init_ds_att(WGPURenderPassDepthStencilAttachment* w _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* action, int w, int h) { SOKOL_ASSERT(action); SOKOL_ASSERT(!_sg.wgpu.in_pass); - SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); + SOKOL_ASSERT(_sg.wgpu.cmd_enc); SOKOL_ASSERT(_sg.wgpu.dev); SOKOL_ASSERT(_sg.wgpu.render_view_cb || _sg.wgpu.render_view_userdata_cb); SOKOL_ASSERT(_sg.wgpu.resolve_view_cb || _sg.wgpu.resolve_view_userdata_cb); @@ -13084,7 +13096,6 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* _sg.wgpu.cur_pipeline = 0; _sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID; - SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); WGPURenderPassDescriptor wgpu_pass_desc; WGPURenderPassColorAttachment wgpu_color_att[SG_MAX_COLOR_ATTACHMENTS]; WGPURenderPassDepthStencilAttachment wgpu_ds_att; @@ -13114,7 +13125,7 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* } wgpu_pass_desc.depthStencilAttachment = &wgpu_ds_att; } - _sg.wgpu.pass_enc = wgpuCommandEncoderBeginRenderPass(_sg.wgpu.render_cmd_enc, &wgpu_pass_desc); + _sg.wgpu.pass_enc = wgpuCommandEncoderBeginRenderPass(_sg.wgpu.cmd_enc, &wgpu_pass_desc); SOKOL_ASSERT(_sg.wgpu.pass_enc); // initial uniform buffer binding (required even if no uniforms are set in the frame) @@ -13132,14 +13143,14 @@ _SOKOL_PRIVATE void _sg_wgpu_end_pass(void) { _SOKOL_PRIVATE void _sg_wgpu_commit(void) { SOKOL_ASSERT(!_sg.wgpu.in_pass); - SOKOL_ASSERT(_sg.wgpu.render_cmd_enc); + SOKOL_ASSERT(_sg.wgpu.cmd_enc); WGPUCommandBufferDescriptor cmd_buf_desc; _sg_clear(&cmd_buf_desc, sizeof(cmd_buf_desc)); - WGPUCommandBuffer wgpu_cmd_buf = wgpuCommandEncoderFinish(_sg.wgpu.render_cmd_enc, &cmd_buf_desc); + WGPUCommandBuffer wgpu_cmd_buf = wgpuCommandEncoderFinish(_sg.wgpu.cmd_enc, &cmd_buf_desc); SOKOL_ASSERT(wgpu_cmd_buf); - wgpuCommandEncoderRelease(_sg.wgpu.render_cmd_enc); - _sg.wgpu.render_cmd_enc = 0; + wgpuCommandEncoderRelease(_sg.wgpu.cmd_enc); + _sg.wgpu.cmd_enc = 0; wgpuQueueSubmit(_sg.wgpu.queue, 1, &wgpu_cmd_buf); wgpuCommandBufferRelease(wgpu_cmd_buf); @@ -13147,7 +13158,7 @@ _SOKOL_PRIVATE void _sg_wgpu_commit(void) { // create a new render-command-encoder for next frame WGPUCommandEncoderDescriptor cmd_enc_desc; _sg_clear(&cmd_enc_desc, sizeof(cmd_enc_desc)); - _sg.wgpu.render_cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); + _sg.wgpu.cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); // reset uniform buffer offsets _sg_wgpu_uniform_buffer_on_commit(); @@ -16656,7 +16667,7 @@ SOKOL_API_IMPL int sg_append_buffer(sg_buffer buf_id, const sg_range* data) { buf->cmn.append_pos = 0; buf->cmn.append_overflow = false; } - if ((buf->cmn.append_pos + data->size) > (size_t)buf->cmn.size) { + if (((size_t)buf->cmn.append_pos + data->size) > (size_t)buf->cmn.size) { buf->cmn.append_overflow = true; } const int start_pos = buf->cmn.append_pos; @@ -17038,6 +17049,38 @@ SOKOL_API_IMPL const void* sg_mtl_render_command_encoder(void) { #endif } +SOKOL_API_IMPL const void* sg_wgpu_device(void) { + #if defined(SOKOL_WGPU) + return _sg.wgpu.dev; + #else + return 0; + #endif +} + +SOKOL_API_IMPL const void* sg_wgpu_queue(void) { + #if defined(SOKOL_WGPU) + return _sg.wgpu.queue; + #else + return 0; + #endif +} + +SOKOL_API_IMPL const void* sg_wgpu_command_encoder(void) { + #if defined(SOKOL_WGPU) + return _sg.wgpu.cmd_enc; + #else + return 0; + #endif +} + +SOKOL_API_IMPL const void* sg_wgpu_render_pass_encoder(void) { + #if defined(SOKOL_WGPU) + return _sg.wgpu.pass_enc; + #else + return 0; + #endif +} + #ifdef _MSC_VER #pragma warning(pop) #endif From 6a7a6b3f03e8079fb4bfbb847d5d30839a860d9e Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Fri, 25 Aug 2023 19:20:46 +0200 Subject: [PATCH 21/95] sokol_gfx.h wgpu: rewrite image/sampler binding use single bindgroup per pipeline --- sokol_gfx.h | 183 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 74 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 3c77db269..09b52f90e 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4806,10 +4806,9 @@ typedef struct { #define _SG_WGPU_ROWPITCH_ALIGN (256) #define _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE (1<<16) // also see WGPULimits.maxUniformBufferBindingSize -#define _SG_WGPU_NUM_BINDGROUPS (3) // 0: uniforms, 1: vertex stage images & samplers, 2: fragment stage images & samplers -#define _SG_WGPU_UNIFORMS_BINDGROUP_INDEX (0) -#define _SG_WGPU_VS_BINDGROUP_INDEX (1) -#define _SG_WGPU_FS_BINDGROUP_INDEX (2) +#define _SG_WGPU_NUM_BINDGROUPS (2) // 0: uniforms, 1: images and sampler on both shader stages +#define _SG_WGPU_UNIFORM_BINDGROUP_INDEX (0) +#define _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX (1) typedef struct { _sg_slot_t slot; @@ -4841,7 +4840,6 @@ typedef _sg_wgpu_sampler_t _sg_sampler_t; typedef struct { WGPUShaderModule module; - WGPUBindGroupLayout bind_group_layout; _sg_str_t entry; } _sg_wgpu_shader_stage_t; @@ -4850,6 +4848,7 @@ typedef struct { _sg_shader_common_t cmn; struct { _sg_wgpu_shader_stage_t stage[SG_NUM_SHADER_STAGES]; + WGPUBindGroupLayout bind_group_layout; } wgpu; } _sg_wgpu_shader_t; typedef _sg_wgpu_shader_t _sg_shader_t; @@ -12290,6 +12289,40 @@ _SOKOL_PRIVATE WGPUColorWriteMaskFlags _sg_wgpu_colorwritemask(uint8_t m) { return res; } +// image/sampler binding on wgpu follows this convention: +// +// - all images and sampler are in @group(1) +// - vertex stage images start at @binding(0) +// - vertex stage samplers start at @binding(16) +// - fragment stage images start at @binding(32) +// - fragment stage samplers start at @binding(48) +// +_SOKOL_PRIVATE uint32_t _sg_wgpu_image_binding(sg_shader_stage stage, int img_slot) { + SOKOL_ASSERT((img_slot >= 0) && (img_slot < 16)); + if (SG_SHADERSTAGE_VS == stage) { + return 0 + (uint32_t)img_slot; + } else { + return 32 + (uint32_t)img_slot; + } +} + +_SOKOL_PRIVATE uint32_t _sg_wgpu_sampler_binding(sg_shader_stage stage, int smp_slot) { + SOKOL_ASSERT((smp_slot >= 0) && (smp_slot < 16)); + if (SG_SHADERSTAGE_VS == stage) { + return 16 + (uint32_t)smp_slot; + } else { + return 48 + (uint32_t)smp_slot; + } +} + +_SOKOL_PRIVATE WGPUShaderStage _sg_wgpu_shader_stage(sg_shader_stage stage) { + switch (stage) { + case SG_SHADERSTAGE_VS: return WGPUShaderStage_Vertex; + case SG_SHADERSTAGE_FS: return WGPUShaderStage_Fragment; + default: SOKOL_UNREACHABLE; return WGPUShaderStage_None; + } +} + _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { _sg.backend = SG_BACKEND_WGPU; _sg.features.origin_top_left = true; @@ -12719,6 +12752,9 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const SOKOL_ASSERT(shd && desc); SOKOL_ASSERT(desc->vs.source && desc->fs.source); + #define _sg_wgpu_create_shader_max_bgl_entries (SG_NUM_SHADER_STAGES * (SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS)) + WGPUBindGroupLayoutEntry wgpu_bgl_entries[_sg_wgpu_create_shader_max_bgl_entries]; + int bgl_index = 0; for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS) ? &desc->vs : &desc->fs; @@ -12742,10 +12778,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const return SG_RESOURCESTATE_FAILED; } - // create image/sampler bind group layout: - // - first all images - // - followed by all samplers - WGPUShaderStage wgpu_shader_stage = (stage_index == SG_SHADERSTAGE_VS) ? WGPUShaderStage_Vertex : WGPUShaderStage_Fragment; const int num_images = cmn_stage->num_images; if (num_images > (int)_sg.wgpu.limits.limits.maxSampledTexturesPerShaderStage) { _SG_ERROR(WGPU_SHADER_TOO_MANY_IMAGES); @@ -12756,59 +12788,60 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const _SG_ERROR(WGPU_SHADER_TOO_MANY_SAMPLERS); return SG_RESOURCESTATE_FAILED; } - WGPUBindGroupLayoutEntry wgpu_bgl_entries[SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS]; _sg_clear(wgpu_bgl_entries, sizeof(wgpu_bgl_entries)); for (int img_index = 0; img_index < num_images; img_index++) { - const int bind_index = img_index; - WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bind_index]; + SOKOL_ASSERT(bgl_index < _sg_wgpu_create_shader_max_bgl_entries); + WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bgl_index++]; const sg_shader_image_desc* img_desc = &stage_desc->images[img_index]; - wgpu_bgl_entry->binding = (uint32_t)bind_index; - wgpu_bgl_entry->visibility = wgpu_shader_stage; + wgpu_bgl_entry->binding = _sg_wgpu_image_binding((sg_shader_stage)stage_index, img_index); + wgpu_bgl_entry->visibility = _sg_wgpu_shader_stage((sg_shader_stage)stage_index); wgpu_bgl_entry->texture.viewDimension = _sg_wgpu_texture_view_dimension(img_desc->image_type); wgpu_bgl_entry->texture.sampleType = _sg_wgpu_texture_sample_type(img_desc->sample_type); wgpu_bgl_entry->texture.multisampled = img_desc->multisampled; } for (int smp_index = 0; smp_index < num_samplers; smp_index++) { - const int bind_index = num_images + smp_index; - WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bind_index]; + SOKOL_ASSERT(bgl_index < _sg_wgpu_create_shader_max_bgl_entries); + WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bgl_index++]; const sg_shader_sampler_desc* smp_desc = &stage_desc->samplers[smp_index]; - wgpu_bgl_entry->binding = (uint32_t)bind_index; - wgpu_bgl_entry->visibility = wgpu_shader_stage; + wgpu_bgl_entry->binding =_sg_wgpu_sampler_binding((sg_shader_stage)stage_index, smp_index); + wgpu_bgl_entry->visibility = _sg_wgpu_shader_stage((sg_shader_stage)stage_index); wgpu_bgl_entry->sampler.type = _sg_wgpu_sampler_binding_type(smp_desc->sampler_type); } - WGPUBindGroupLayoutDescriptor wgpu_bgl_desc; - _sg_clear(&wgpu_bgl_desc, sizeof(wgpu_bgl_desc)); - wgpu_bgl_desc.entryCount = (size_t)(num_images + num_samplers); - wgpu_bgl_desc.entries = &wgpu_bgl_entries[0]; - wgpu_stage->bind_group_layout = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &wgpu_bgl_desc); - if (wgpu_stage->bind_group_layout == 0) { - _SG_ERROR(WGPU_SHADER_CREATE_BINDGROUP_LAYOUT_FAILED); - return SG_RESOURCESTATE_FAILED; - } } + + WGPUBindGroupLayoutDescriptor wgpu_bgl_desc; + _sg_clear(&wgpu_bgl_desc, sizeof(wgpu_bgl_desc)); + wgpu_bgl_desc.entryCount = (size_t)bgl_index; + wgpu_bgl_desc.entries = &wgpu_bgl_entries[0]; + shd->wgpu.bind_group_layout = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &wgpu_bgl_desc); + if (shd->wgpu.bind_group_layout == 0) { + _SG_ERROR(WGPU_SHADER_CREATE_BINDGROUP_LAYOUT_FAILED); + return SG_RESOURCESTATE_FAILED; + } + + #undef _sg_wgpu_create_shader_max_bgl_entries return SG_RESOURCESTATE_VALID; } _SOKOL_PRIVATE void _sg_wgpu_discard_shader(_sg_shader_t* shd) { SOKOL_ASSERT(shd); + if (shd->wgpu.bind_group_layout) { + wgpuBindGroupLayoutRelease(shd->wgpu.bind_group_layout); + shd->wgpu.bind_group_layout = 0; + } for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { _sg_wgpu_shader_stage_t* wgpu_stage = &shd->wgpu.stage[stage_index]; if (wgpu_stage->module) { wgpuShaderModuleRelease(wgpu_stage->module); wgpu_stage->module = 0; } - if (wgpu_stage->bind_group_layout) { - wgpuBindGroupLayoutRelease(wgpu_stage->bind_group_layout); - wgpu_stage->bind_group_layout = 0; - } } } _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) { SOKOL_ASSERT(pip && shd && desc); SOKOL_ASSERT(desc->shader.id == shd->slot.id); - SOKOL_ASSERT(shd->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout); - SOKOL_ASSERT(shd->wgpu.stage[SG_SHADERSTAGE_FS].bind_group_layout); + SOKOL_ASSERT(shd->wgpu.bind_group_layout); pip->shader = shd; pip->wgpu.blend_color.r = (double) desc->blend_color.r; @@ -12816,13 +12849,11 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ pip->wgpu.blend_color.b = (double) desc->blend_color.b; pip->wgpu.blend_color.a = (double) desc->blend_color.a; - // - 1 bindgroup for uniform block, - // - 1 bindgroup for vertex shader resources - // - 1 bindgroup for fragment shader resources + // - @group(0) for uniform blocks + // - @group(1) for all image and sampler resources WGPUBindGroupLayout wgpu_bgl[_SG_WGPU_NUM_BINDGROUPS]; - wgpu_bgl[_SG_WGPU_UNIFORMS_BINDGROUP_INDEX] = _sg.wgpu.uniform.bind.group_layout; - wgpu_bgl[_SG_WGPU_VS_BINDGROUP_INDEX] = shd->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout; - wgpu_bgl[_SG_WGPU_FS_BINDGROUP_INDEX] = shd->wgpu.stage[SG_SHADERSTAGE_FS].bind_group_layout; + wgpu_bgl[_SG_WGPU_UNIFORM_BINDGROUP_INDEX] = _sg.wgpu.uniform.bind.group_layout; + wgpu_bgl[_SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX] = shd->wgpu.bind_group_layout; WGPUPipelineLayoutDescriptor wgpu_pl_desc; _sg_clear(&wgpu_pl_desc, sizeof(wgpu_pl_desc)); wgpu_pl_desc.bindGroupLayoutCount = _SG_WGPU_NUM_BINDGROUPS; @@ -13214,31 +13245,44 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_pipeline(_sg_pipeline_t* pip) { _SOKOL_PRIVATE WGPUBindGroup _sg_wgpu_create_bindgroup( WGPUBindGroupLayout bgl, - _sg_image_t** imgs, int num_imgs, - _sg_sampler_t** smps, int num_smps) + _sg_image_t** vs_imgs, int num_vs_imgs, + _sg_sampler_t** vs_smps, int num_vs_smps, + _sg_image_t** fs_imgs, int num_fs_imgs, + _sg_sampler_t** fs_smps, int num_fs_smps) { SOKOL_ASSERT(_sg.wgpu.dev); - SOKOL_ASSERT(imgs && (num_imgs <= SG_MAX_SHADERSTAGE_IMAGES)); - SOKOL_ASSERT(smps && (num_smps <= SG_MAX_SHADERSTAGE_SAMPLERS)); + SOKOL_ASSERT(vs_imgs && (num_vs_imgs <= SG_MAX_SHADERSTAGE_IMAGES)); + SOKOL_ASSERT(vs_smps && (num_vs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS)); + SOKOL_ASSERT(fs_imgs && (num_fs_imgs <= SG_MAX_SHADERSTAGE_IMAGES)); + SOKOL_ASSERT(fs_smps && (num_fs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS)); - WGPUBindGroupEntry wgpu_entries[SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS]; + WGPUBindGroupEntry wgpu_entries[2 * SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS]; _sg_clear(&wgpu_entries, sizeof(wgpu_entries)); - for (int img_index = 0; img_index < num_imgs; img_index++) { - uint32_t wgpu_bind_index = (uint32_t)img_index; - WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[wgpu_bind_index]; - wgpu_entry->binding = wgpu_bind_index; - wgpu_entry->textureView = imgs[img_index]->wgpu.view; - } - for (int smp_index = 0; smp_index < num_smps; smp_index++) { - uint32_t wgpu_bind_index = (uint32_t)(num_imgs + smp_index); - WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[wgpu_bind_index]; - wgpu_entry->binding = wgpu_bind_index; - wgpu_entry->sampler = smps[smp_index]->wgpu.smp; + int bge_index = 0; + for (int i = 0; i < num_vs_imgs; i++) { + WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; + wgpu_entry->binding = _sg_wgpu_image_binding(SG_SHADERSTAGE_VS, i); + wgpu_entry->textureView = vs_imgs[i]->wgpu.view; + } + for (int i = 0; i < num_vs_smps; i++) { + WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; + wgpu_entry->binding = _sg_wgpu_sampler_binding(SG_SHADERSTAGE_VS, i); + wgpu_entry->sampler = vs_smps[i]->wgpu.smp; + } + for (int i = 0; i < num_fs_imgs; i++) { + WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; + wgpu_entry->binding = _sg_wgpu_image_binding(SG_SHADERSTAGE_FS, i); + wgpu_entry->textureView = fs_imgs[i]->wgpu.view; + } + for (int i = 0; i < num_fs_smps; i++) { + WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; + wgpu_entry->binding = _sg_wgpu_sampler_binding(SG_SHADERSTAGE_FS, i); + wgpu_entry->sampler = fs_smps[i]->wgpu.smp; } WGPUBindGroupDescriptor bg_desc; _sg_clear(&bg_desc, sizeof(bg_desc)); bg_desc.layout = bgl; - bg_desc.entryCount = (size_t)(num_imgs + num_smps); + bg_desc.entryCount = (size_t)bge_index; bg_desc.entries = &wgpu_entries[0]; WGPUBindGroup bg = wgpuDeviceCreateBindGroup(_sg.wgpu.dev, &bg_desc); SOKOL_ASSERT(bg); @@ -13277,25 +13321,16 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_bindings( wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, slot, vbs[slot]->wgpu.buf, offset, max_bytes); } - // FIXME: create adhoc bind group objects for images and samplers per stage + // FIXME: create adhoc bind group object for images and samplers // (either use a bindgroup-cache or introduce bindgroups as sokol-gfx objects) - if ((num_vs_imgs + num_vs_smps) > 0) { - WGPUBindGroupLayout vs_bgl = pip->shader->wgpu.stage[SG_SHADERSTAGE_VS].bind_group_layout; - SOKOL_ASSERT(vs_bgl); - WGPUBindGroup vs_bg = _sg_wgpu_create_bindgroup(vs_bgl, vs_imgs, num_vs_imgs, vs_smps, num_vs_smps); - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_VS_BINDGROUP_INDEX, vs_bg, 0, 0); - wgpuBindGroupRelease(vs_bg); - } else { - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_VS_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); - } - if ((num_fs_imgs + num_fs_smps) > 0) { - WGPUBindGroupLayout fs_bgl = pip->shader->wgpu.stage[SG_SHADERSTAGE_FS].bind_group_layout; - SOKOL_ASSERT(fs_bgl); - WGPUBindGroup fs_bg = _sg_wgpu_create_bindgroup(fs_bgl, fs_imgs, num_fs_imgs, fs_smps, num_fs_smps); - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_FS_BINDGROUP_INDEX, fs_bg, 0, 0); - wgpuBindGroupRelease(fs_bg); + if ((num_vs_imgs + num_vs_smps + num_fs_imgs + num_fs_smps) > 0) { + WGPUBindGroupLayout bgl = pip->shader->wgpu.bind_group_layout; + SOKOL_ASSERT(bgl); + WGPUBindGroup bg = _sg_wgpu_create_bindgroup(bgl, vs_imgs, num_vs_imgs, vs_smps, num_vs_smps, fs_imgs, num_fs_imgs, fs_smps, num_fs_smps); + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg, 0, 0); + wgpuBindGroupRelease(bg); } else { - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_FS_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); } } @@ -13315,7 +13350,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, _sg.wgpu.uniform.offset, data->ptr, data->size); _sg.wgpu.uniform.bind.offsets[stage_index][ub_index] = _sg.wgpu.uniform.offset; wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, - _SG_WGPU_UNIFORMS_BINDGROUP_INDEX, + _SG_WGPU_UNIFORM_BINDGROUP_INDEX, _sg.wgpu.uniform.bind.group, SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS, &_sg.wgpu.uniform.bind.offsets[0][0]); From 4a2e1747c226d62fcd7453559eed7629c5515f61 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 26 Aug 2023 17:52:32 +0200 Subject: [PATCH 22/95] sokol_gfx.h wgpu: minor cleanup --- sokol_gfx.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sokol_gfx.h b/sokol_gfx.h index 09b52f90e..41a5d9bce 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12852,6 +12852,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ // - @group(0) for uniform blocks // - @group(1) for all image and sampler resources WGPUBindGroupLayout wgpu_bgl[_SG_WGPU_NUM_BINDGROUPS]; + _sg_clear(&wgpu_bgl, sizeof(wgpu_bgl)); wgpu_bgl[_SG_WGPU_UNIFORM_BINDGROUP_INDEX] = _sg.wgpu.uniform.bind.group_layout; wgpu_bgl[_SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX] = shd->wgpu.bind_group_layout; WGPUPipelineLayoutDescriptor wgpu_pl_desc; From 8d7460cc2ac133c63eb31df02de3973954f3ed43 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 27 Aug 2023 10:29:37 +0200 Subject: [PATCH 23/95] sokol_gfx.h metal: remove redundant frame_index in _sg_mtl_backend_t --- sokol_gfx.h | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 41a5d9bce..6c9ff8263 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4782,7 +4782,6 @@ typedef struct { const void*(*drawable_cb)(void); const void*(*drawable_userdata_cb)(void*); void* user_data; - uint32_t frame_index; uint32_t cur_frame_rotate_index; int ub_size; int cur_ub_offset; @@ -10886,7 +10885,6 @@ _SOKOL_PRIVATE void _sg_mtl_setup_backend(const sg_desc* desc) { _sg.mtl.drawable_cb = desc->context.metal.drawable_cb; _sg.mtl.drawable_userdata_cb = desc->context.metal.drawable_userdata_cb; _sg.mtl.user_data = desc->context.metal.user_data; - _sg.mtl.frame_index = 1; _sg.mtl.ub_size = desc->uniform_buffer_size; _sg.mtl.sem = dispatch_semaphore_create(SG_NUM_INFLIGHT_FRAMES); _sg.mtl.device = (__bridge id) desc->context.metal.device; @@ -10920,7 +10918,7 @@ _SOKOL_PRIVATE void _sg_mtl_discard_backend(void) { for (int i = 0; i < SG_NUM_INFLIGHT_FRAMES; i++) { dispatch_semaphore_signal(_sg.mtl.sem); } - _sg_mtl_garbage_collect(_sg.mtl.frame_index + SG_NUM_INFLIGHT_FRAMES + 2); + _sg_mtl_garbage_collect(_sg.frame_index + SG_NUM_INFLIGHT_FRAMES + 2); _sg_mtl_destroy_pool(); _sg.mtl.valid = false; @@ -11002,7 +11000,7 @@ _SOKOL_PRIVATE void _sg_mtl_discard_buffer(_sg_buffer_t* buf) { SOKOL_ASSERT(buf); for (int slot = 0; slot < buf->cmn.num_slots; slot++) { // it's valid to call release resource with '0' - _sg_mtl_release_resource(_sg.mtl.frame_index, buf->mtl.buf[slot]); + _sg_mtl_release_resource(_sg.frame_index, buf->mtl.buf[slot]); } } @@ -11146,7 +11144,7 @@ _SOKOL_PRIVATE void _sg_mtl_discard_image(_sg_image_t* img) { SOKOL_ASSERT(img); // it's valid to call release resource with a 'null resource' for (int slot = 0; slot < img->cmn.num_slots; slot++) { - _sg_mtl_release_resource(_sg.mtl.frame_index, img->mtl.tex[slot]); + _sg_mtl_release_resource(_sg.frame_index, img->mtl.tex[slot]); } } @@ -11187,7 +11185,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_sampler(_sg_sampler_t* smp, cons _SOKOL_PRIVATE void _sg_mtl_discard_sampler(_sg_sampler_t* smp) { SOKOL_ASSERT(smp); // it's valid to call release resource with a 'null resource' - _sg_mtl_release_resource(_sg.mtl.frame_index, smp->mtl.sampler_state); + _sg_mtl_release_resource(_sg.frame_index, smp->mtl.sampler_state); } _SOKOL_PRIVATE id _sg_mtl_compile_library(const char* src) { @@ -11284,10 +11282,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_shader(_sg_shader_t* shd, const _SOKOL_PRIVATE void _sg_mtl_discard_shader(_sg_shader_t* shd) { SOKOL_ASSERT(shd); // it is valid to call _sg_mtl_release_resource with a 'null resource' - _sg_mtl_release_resource(_sg.mtl.frame_index, shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func); - _sg_mtl_release_resource(_sg.mtl.frame_index, shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_lib); - _sg_mtl_release_resource(_sg.mtl.frame_index, shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func); - _sg_mtl_release_resource(_sg.mtl.frame_index, shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_lib); + _sg_mtl_release_resource(_sg.frame_index, shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_func); + _sg_mtl_release_resource(_sg.frame_index, shd->mtl.stage[SG_SHADERSTAGE_VS].mtl_lib); + _sg_mtl_release_resource(_sg.frame_index, shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_func); + _sg_mtl_release_resource(_sg.frame_index, shd->mtl.stage[SG_SHADERSTAGE_FS].mtl_lib); } _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_pipeline(_sg_pipeline_t* pip, _sg_shader_t* shd, const sg_pipeline_desc* desc) { @@ -11415,8 +11413,8 @@ _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_pipeline(_sg_pipeline_t* pip, _s _SOKOL_PRIVATE void _sg_mtl_discard_pipeline(_sg_pipeline_t* pip) { SOKOL_ASSERT(pip); // it's valid to call release resource with a 'null resource' - _sg_mtl_release_resource(_sg.mtl.frame_index, pip->mtl.rps); - _sg_mtl_release_resource(_sg.mtl.frame_index, pip->mtl.dss); + _sg_mtl_release_resource(_sg.frame_index, pip->mtl.rps); + _sg_mtl_release_resource(_sg.frame_index, pip->mtl.dss); } _SOKOL_PRIVATE sg_resource_state _sg_mtl_create_pass(_sg_pass_t* pass, _sg_image_t** color_images, _sg_image_t** resolve_images, _sg_image_t* ds_img, const sg_pass_desc* desc) { @@ -11675,13 +11673,12 @@ _SOKOL_PRIVATE void _sg_mtl_commit(void) { [_sg.mtl.present_cmd_buffer commit]; // garbage-collect resources pending for release - _sg_mtl_garbage_collect(_sg.mtl.frame_index); + _sg_mtl_garbage_collect(_sg.frame_index); // rotate uniform buffer slot if (++_sg.mtl.cur_frame_rotate_index >= SG_NUM_INFLIGHT_FRAMES) { _sg.mtl.cur_frame_rotate_index = 0; } - _sg.mtl.frame_index++; _sg.mtl.cur_ub_offset = 0; _sg.mtl.cur_ub_base_ptr = 0; // NOTE: MTLCommandBuffer is autoreleased From 692a38961d094dbbc953a32dcbe1eb578561a362 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 27 Aug 2023 22:07:16 +0200 Subject: [PATCH 24/95] sokol_gfx.h wgpu: workaround missing return value of Emscripten's wgpuDeviceGetLimits() shim --- sokol_gfx.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 6c9ff8263..c4cb3952c 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12327,8 +12327,9 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { _sg.features.mrt_independent_blend_state = true; _sg.features.mrt_independent_write_mask = true; - bool success = wgpuDeviceGetLimits(_sg.wgpu.dev, &_sg.wgpu.limits); - SOKOL_ASSERT(success); _SOKOL_UNUSED(success); + // FIXME: in webgpu.h, wgpuDeviceGetLimits() has a boolean return value, but + // the JS shim doesn't actually return anything + wgpuDeviceGetLimits(_sg.wgpu.dev, &_sg.wgpu.limits); const WGPULimits* l = &_sg.wgpu.limits.limits; _sg.limits.max_image_size_2d = (int) l->maxTextureDimension2D; From 7e4c532606960378e4fb9802e333a0a5747e3405 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 28 Aug 2023 16:03:09 +0200 Subject: [PATCH 25/95] sokol_gfx.h wgpu: change SG_PIXELFORMAT_DEPTH_STENCIL to WGPUTextureFormat_Depth32FloatStencil8 --- sokol_gfx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index c4cb3952c..b67a2c62b 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -3207,7 +3207,7 @@ typedef enum sg_log_item { .context.wgpu.depth_stencil_view_cb .context.wgpu.depth_stencil_view_userdata_cb callback to get current default-pass depth-stencil-surface WGPUTextureView - the pixel format of the default WGPUTextureView must be WGPUTextureFormat_Depth24Plus8 + the pixel format of the default WGPUTextureView must be WGPUTextureFormat_Depth32FloatStencil8 .context.wgpu.user_data optional user data pointer passed to the userdata versions of callback functions @@ -12173,7 +12173,7 @@ _SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) { case SG_PIXELFORMAT_RGBA32SI: return WGPUTextureFormat_RGBA32Sint; case SG_PIXELFORMAT_RGBA32F: return WGPUTextureFormat_RGBA32Float; case SG_PIXELFORMAT_DEPTH: return WGPUTextureFormat_Depth32Float; - case SG_PIXELFORMAT_DEPTH_STENCIL: return WGPUTextureFormat_Depth24PlusStencil8; + case SG_PIXELFORMAT_DEPTH_STENCIL: return WGPUTextureFormat_Depth32FloatStencil8; case SG_PIXELFORMAT_BC1_RGBA: return WGPUTextureFormat_BC1RGBAUnorm; case SG_PIXELFORMAT_BC2_RGBA: return WGPUTextureFormat_BC2RGBAUnorm; case SG_PIXELFORMAT_BC3_RGBA: return WGPUTextureFormat_BC3RGBAUnorm; From fb3b4ef10354534142e8d0721fffdeea885a037a Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 28 Aug 2023 16:04:33 +0200 Subject: [PATCH 26/95] sokol_gfx.h: fix wgpu initialization and frame loop --- sokol_app.h | 452 +++++++++++++++++++++++++++++----------------------- 1 file changed, 252 insertions(+), 200 deletions(-) diff --git a/sokol_app.h b/sokol_app.h index a1f45b6b1..d0975861b 100644 --- a/sokol_app.h +++ b/sokol_app.h @@ -1573,6 +1573,18 @@ typedef struct sapp_allocator { _SAPP_LOGITEM_XMACRO(ANDROID_NATIVE_ACTIVITY_ONCREATE, "NativeActivity onCreate") \ _SAPP_LOGITEM_XMACRO(ANDROID_CREATE_THREAD_PIPE_FAILED, "failed to create thread pipe") \ _SAPP_LOGITEM_XMACRO(ANDROID_NATIVE_ACTIVITY_CREATE_SUCCESS, "NativeActivity sucessfully created") \ + _SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_SURFACE_FAILED, "wgpu: failed to create surface for swapchain") \ + _SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_SWAPCHAIN_FAILED, "wgpu: failed to create swapchain object") \ + _SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_DEPTH_STENCIL_TEXTURE_FAILED, "wgpu: failed to create depth-stencil texture for swapchain") \ + _SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_DEPTH_STENCIL_VIEW_FAILED, "wgpu: failed to create view object for swapchain depth-stencil texture") \ + _SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_MSAA_TEXTURE_FAILED, "wgpu: failed to create msaa texture for swapchain") \ + _SAPP_LOGITEM_XMACRO(WGPU_SWAPCHAIN_CREATE_MSAA_VIEW_FAILED, "wgpu: failed to create view object for swapchain msaa texture") \ + _SAPP_LOGITEM_XMACRO(WGPU_REQUEST_DEVICE_STATUS_ERROR, "wgpu: requesting device failed with status 'error'") \ + _SAPP_LOGITEM_XMACRO(WGPU_REQUEST_DEVICE_STATUS_UNKNOWN, "wgpu: requesting device failed with status 'unknown'") \ + _SAPP_LOGITEM_XMACRO(WGPU_REQUEST_ADAPTER_STATUS_UNAVAILABLE, "wgpu: requesting adapter failed with 'unavailable'") \ + _SAPP_LOGITEM_XMACRO(WGPU_REQUEST_ADAPTER_STATUS_ERROR, "wgpu: requesting adapter failed with status 'error'") \ + _SAPP_LOGITEM_XMACRO(WGPU_REQUEST_ADAPTER_STATUS_UNKNOWN, "wgpu: requesting adapter failed with status 'unknown'") \ + _SAPP_LOGITEM_XMACRO(WGPU_CREATE_INSTANCE_FAILED, "wgpu: failed to create instance") \ _SAPP_LOGITEM_XMACRO(IMAGE_DATA_SIZE_MISMATCH, "image data size mismatch (must be width*height*4 bytes)") \ _SAPP_LOGITEM_XMACRO(DROPPED_FILE_PATH_TOO_LONG, "dropped file path too long (sapp_desc.max_dropped_filed_path_length)") \ _SAPP_LOGITEM_XMACRO(CLIPBOARD_STRING_TOO_BIG, "clipboard string didn't fit into clipboard buffer") \ @@ -1852,7 +1864,31 @@ inline void sapp_run(const sapp_desc& desc) { return sapp_run(&desc); } #include // size_t #include // roundf -/* check if the config defines are alright */ +// helper macros +#define _sapp_def(val, def) (((val) == 0) ? (def) : (val)) +#define _sapp_absf(a) (((a)<0.0f)?-(a):(a)) + +#define _SAPP_MAX_TITLE_LENGTH (128) +#define _SAPP_FALLBACK_DEFAULT_WINDOW_WIDTH (640) +#define _SAPP_FALLBACK_DEFAULT_WINDOW_HEIGHT (480) +// NOTE: the pixel format values *must* be compatible with sg_pixel_format +#define _SAPP_PIXELFORMAT_RGBA8 (23) +#define _SAPP_PIXELFORMAT_BGRA8 (28) +#define _SAPP_PIXELFORMAT_DEPTH (42) +#define _SAPP_PIXELFORMAT_DEPTH_STENCIL (43) + +#if defined(_SAPP_MACOS) || defined(_SAPP_IOS) + // this is ARC compatible + #if defined(__cplusplus) + #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = type(); } + #else + #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = (type) { 0 }; } + #endif +#else + #define _SAPP_CLEAR_ARC_STRUCT(type, item) { _sapp_clear(&item, sizeof(item)); } +#endif + +// check if the config defines are alright #if defined(__APPLE__) // see https://clang.llvm.org/docs/LanguageExtensions.html#automatic-reference-counting #if !defined(__cplusplus) @@ -2339,15 +2375,18 @@ typedef struct { #if defined(SOKOL_WGPU) typedef struct { - int state; + WGPUInstance instance; + WGPUAdapter adapter; WGPUDevice device; - WGPUSwapChain swapchain; WGPUTextureFormat render_format; + WGPUSurface surface; + WGPUSwapChain swapchain; WGPUTexture msaa_tex; - WGPUTexture depth_stencil_tex; - WGPUTextureView swapchain_view; WGPUTextureView msaa_view; + WGPUTexture depth_stencil_tex; WGPUTextureView depth_stencil_view; + WGPUTextureView swapchain_view; + bool async_init_done; } _sapp_wgpu_t; #endif @@ -2357,9 +2396,7 @@ typedef struct { bool wants_hide_keyboard; bool mouse_lock_requested; uint16_t mouse_buttons; - #if defined(SOKOL_WGPU) - _sapp_wgpu_t wgpu; - #endif + char canvas_selector[_SAPP_MAX_TITLE_LENGTH]; } _sapp_emsc_t; #endif // _SAPP_EMSCRIPTEN @@ -2396,7 +2433,7 @@ typedef enum MONITOR_DPI_TYPE { MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE; -#endif /*DPI_ENUMS_DECLARED*/ +#endif // DPI_ENUMS_DECLARED typedef struct { bool aware; @@ -2683,30 +2720,6 @@ typedef struct { #endif // _SAPP_LINUX -/* helper macros */ -#define _sapp_def(val, def) (((val) == 0) ? (def) : (val)) -#define _sapp_absf(a) (((a)<0.0f)?-(a):(a)) - -#define _SAPP_MAX_TITLE_LENGTH (128) -#define _SAPP_FALLBACK_DEFAULT_WINDOW_WIDTH (640) -#define _SAPP_FALLBACK_DEFAULT_WINDOW_HEIGHT (480) -/* NOTE: the pixel format values *must* be compatible with sg_pixel_format */ -#define _SAPP_PIXELFORMAT_RGBA8 (23) -#define _SAPP_PIXELFORMAT_BGRA8 (28) -#define _SAPP_PIXELFORMAT_DEPTH (42) -#define _SAPP_PIXELFORMAT_DEPTH_STENCIL (43) - -#if defined(_SAPP_MACOS) || defined(_SAPP_IOS) - // this is ARC compatible - #if defined(__cplusplus) - #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = type(); } - #else - #define _SAPP_CLEAR_ARC_STRUCT(type, item) { item = (type) { 0 }; } - #endif -#else - #define _SAPP_CLEAR_ARC_STRUCT(type, item) { _sapp_clear(&item, sizeof(item)); } -#endif - typedef struct { bool enabled; int buf_size; @@ -2764,6 +2777,9 @@ typedef struct { _sapp_ios_t ios; #elif defined(_SAPP_EMSCRIPTEN) _sapp_emsc_t emsc; + #if defined(SOKOL_WGPU) + _sapp_wgpu_t wgpu; + #endif #elif defined(_SAPP_WIN32) _sapp_win32_t win32; #if defined(SOKOL_D3D11) @@ -2781,7 +2797,6 @@ typedef struct { _sapp_egl_t egl; #endif #endif - char html5_canvas_selector[_SAPP_MAX_TITLE_LENGTH]; char window_title[_SAPP_MAX_TITLE_LENGTH]; /* UTF-8 */ wchar_t window_title_wide[_SAPP_MAX_TITLE_LENGTH]; /* UTF-32 or UCS-2 */ sapp_keycode keycodes[SAPP_MAX_KEYCODES]; @@ -3005,9 +3020,9 @@ _SOKOL_PRIVATE void _sapp_init_state(const sapp_desc* desc) { _sapp.framebuffer_height = _sapp.window_height; _sapp.sample_count = _sapp.desc.sample_count; _sapp.swap_interval = _sapp.desc.swap_interval; - _sapp.html5_canvas_selector[0] = '#'; - _sapp_strcpy(_sapp.desc.html5_canvas_name, &_sapp.html5_canvas_selector[1], sizeof(_sapp.html5_canvas_selector) - 1); - _sapp.desc.html5_canvas_name = &_sapp.html5_canvas_selector[1]; + _sapp.emsc.canvas_selector[0] = '#'; + _sapp_strcpy(_sapp.desc.html5_canvas_name, &_sapp.emsc.canvas_selector[1], sizeof(_sapp.emsc.canvas_selector) - 1); + _sapp.desc.html5_canvas_name = &_sapp.emsc.canvas_selector[1]; _sapp.html5_ask_leave_site = _sapp.desc.html5_ask_leave_site; _sapp.clipboard.enabled = _sapp.desc.enable_clipboard; if (_sapp.clipboard.enabled) { @@ -5031,11 +5046,6 @@ _SOKOL_PRIVATE void _sapp_emsc_set_icon(const sapp_icon_desc* icon_desc, int num sapp_js_set_favicon(img_desc->width, img_desc->height, (const uint8_t*) img_desc->pixels.ptr); } -#if defined(SOKOL_WGPU) -_SOKOL_PRIVATE void _sapp_emsc_wgpu_surfaces_create(void); -_SOKOL_PRIVATE void _sapp_emsc_wgpu_surfaces_discard(void); -#endif - _SOKOL_PRIVATE uint32_t _sapp_emsc_mouse_button_mods(uint16_t buttons) { uint32_t m = 0; if (0 != (buttons & (1<<0))) { m |= SAPP_MODIFIER_LMB; } @@ -5074,11 +5084,15 @@ _SOKOL_PRIVATE uint32_t _sapp_emsc_touch_event_mods(const EmscriptenTouchEvent* return m; } +#if defined(SOKOL_WGPU) +_SOKOL_PRIVATE void _sapp_emsc_wgpu_size_changed(void); +#endif + _SOKOL_PRIVATE EM_BOOL _sapp_emsc_size_changed(int event_type, const EmscriptenUiEvent* ui_event, void* user_data) { _SOKOL_UNUSED(event_type); _SOKOL_UNUSED(user_data); double w, h; - emscripten_get_element_css_size(_sapp.html5_canvas_selector, &w, &h); + emscripten_get_element_css_size(_sapp.emsc.canvas_selector, &w, &h); /* The above method might report zero when toggling HTML5 fullscreen, in that case use the window's inner width reported by the emscripten event. This works ok when toggling *into* fullscreen @@ -5117,11 +5131,10 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_size_changed(int event_type, const EmscriptenU _sapp.framebuffer_width = (int)roundf(w * _sapp.dpi_scale); _sapp.framebuffer_height = (int)roundf(h * _sapp.dpi_scale); SOKOL_ASSERT((_sapp.framebuffer_width > 0) && (_sapp.framebuffer_height > 0)); - emscripten_set_canvas_element_size(_sapp.html5_canvas_selector, _sapp.framebuffer_width, _sapp.framebuffer_height); + emscripten_set_canvas_element_size(_sapp.emsc.canvas_selector, _sapp.framebuffer_width, _sapp.framebuffer_height); #if defined(SOKOL_WGPU) - /* on WebGPU: recreate size-dependent rendering surfaces */ - _sapp_emsc_wgpu_surfaces_discard(); - _sapp_emsc_wgpu_surfaces_create(); + // on WebGPU: recreate size-dependent rendering surfaces + _sapp_emsc_wgpu_size_changed(); #endif if (_sapp_events_enabled()) { _sapp_init_event(SAPP_EVENTTYPE_RESIZED); @@ -5393,11 +5406,10 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_key_cb(int emsc_type, const EmscriptenKeyboard _sapp.event.key_code = _sapp_emsc_translate_key(emsc_event->key); } - /* Special hack for macOS: if the Super key is pressed, macOS doesn't - send keyUp events. As a workaround, to prevent keys from - "sticking", we'll send a keyup event following a keydown - when the SUPER key is pressed - */ + // Special hack for macOS: if the Super key is pressed, macOS doesn't + // send keyUp events. As a workaround, to prevent keys from + // "sticking", we'll send a keyup event following a keydown + // when the SUPER key is pressed if ((type == SAPP_EVENTTYPE_KEY_DOWN) && (_sapp.event.key_code != SAPP_KEYCODE_LEFT_SUPER) && (_sapp.event.key_code != SAPP_KEYCODE_RIGHT_SUPER) && @@ -5582,7 +5594,7 @@ _SOKOL_PRIVATE void _sapp_emsc_webgl_init(void) { attrs.preserveDrawingBuffer = _sapp.desc.html5_preserve_drawing_buffer; attrs.enableExtensionsByDefault = true; attrs.majorVersion = 2; - EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(_sapp.html5_canvas_selector, &attrs); + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(_sapp.emsc.canvas_selector, &attrs); // FIXME: error message? emscripten_webgl_make_context_current(ctx); @@ -5592,129 +5604,190 @@ _SOKOL_PRIVATE void _sapp_emsc_webgl_init(void) { #endif #if defined(SOKOL_WGPU) -#define _SAPP_EMSC_WGPU_STATE_INITIAL (0) -#define _SAPP_EMSC_WGPU_STATE_READY (1) -#define _SAPP_EMSC_WGPU_STATE_RUNNING (2) - -#if defined(__cplusplus) -extern "C" { -#endif -/* called when the asynchronous WebGPU device + swapchain init code in JS has finished */ -EMSCRIPTEN_KEEPALIVE void _sapp_emsc_wgpu_ready(int device_id, int swapchain_id, int swapchain_fmt) { - SOKOL_ASSERT(0 == _sapp.emsc.wgpu.device); - _sapp.emsc.wgpu.device = (WGPUDevice) device_id; - _sapp.emsc.wgpu.swapchain = (WGPUSwapChain) swapchain_id; - _sapp.emsc.wgpu.render_format = (WGPUTextureFormat) swapchain_fmt; - _sapp.emsc.wgpu.state = _SAPP_EMSC_WGPU_STATE_READY; -} -#if defined(__cplusplus) -} // extern "C" -#endif - -/* embedded JS function to handle all the asynchronous WebGPU setup */ -EM_JS(void, sapp_js_wgpu_init, (), { - WebGPU.initManagers(); - // FIXME: the extension activation must be more clever here - navigator.gpu.requestAdapter().then((adapter) => { - console.log("wgpu adapter extensions: " + adapter.extensions); - adapter.requestDevice({ extensions: ["textureCompressionBC"]}).then((device) => { - var gpuContext = document.getElementById("canvas").getContext("gpupresent"); - console.log("wgpu device extensions: " + adapter.extensions); - gpuContext.getSwapChainPreferredFormat(device).then((fmt) => { - const swapChainDescriptor = { device: device, format: fmt }; - const swapChain = gpuContext.configureSwapChain(swapChainDescriptor); - const deviceId = WebGPU.mgrDevice.create(device); - const swapChainId = WebGPU.mgrSwapChain.create(swapChain); - const fmtId = WebGPU.TextureFormat.findIndex(function(elm) { return elm==fmt; }); - console.log("wgpu device: " + device); - console.log("wgpu swap chain: " + swapChain); - console.log("wgpu preferred format: " + fmt + " (" + fmtId + ")"); - __sapp_emsc_wgpu_ready(deviceId, swapChainId, fmtId); - }); - }); - }); -}); -_SOKOL_PRIVATE void _sapp_emsc_wgpu_surfaces_create(void) { - SOKOL_ASSERT(_sapp.emsc.wgpu.device); - SOKOL_ASSERT(_sapp.emsc.wgpu.swapchain); - SOKOL_ASSERT(0 == _sapp.emsc.wgpu.depth_stencil_tex); - SOKOL_ASSERT(0 == _sapp.emsc.wgpu.depth_stencil_view); - SOKOL_ASSERT(0 == _sapp.emsc.wgpu.msaa_tex); - SOKOL_ASSERT(0 == _sapp.emsc.wgpu.msaa_view); +_SOKOL_PRIVATE void _sapp_emsc_wgpu_create_swapchain(void) { + SOKOL_ASSERT(_sapp.wgpu.instance); + SOKOL_ASSERT(_sapp.wgpu.device); + SOKOL_ASSERT(0 == _sapp.wgpu.surface); + SOKOL_ASSERT(0 == _sapp.wgpu.swapchain); + SOKOL_ASSERT(0 == _sapp.wgpu.msaa_tex); + SOKOL_ASSERT(0 == _sapp.wgpu.msaa_view); + SOKOL_ASSERT(0 == _sapp.wgpu.depth_stencil_tex); + SOKOL_ASSERT(0 == _sapp.wgpu.depth_stencil_view); + SOKOL_ASSERT(0 == _sapp.wgpu.swapchain_view); + + WGPUSurfaceDescriptorFromCanvasHTMLSelector canvas_desc; + _sapp_clear(&canvas_desc, sizeof(canvas_desc)); + canvas_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector; + canvas_desc.selector = _sapp.emsc.canvas_selector; + WGPUSurfaceDescriptor surf_desc; + _sapp_clear(&surf_desc, sizeof(surf_desc)); + surf_desc.nextInChain = &canvas_desc.chain; + _sapp.wgpu.surface = wgpuInstanceCreateSurface(_sapp.wgpu.instance, &surf_desc); + if (0 == _sapp.wgpu.surface) { + _SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_SURFACE_FAILED); + } + _sapp.wgpu.render_format = wgpuSurfaceGetPreferredFormat(_sapp.wgpu.surface, _sapp.wgpu.adapter); + + WGPUSwapChainDescriptor sc_desc; + _sapp_clear(&sc_desc, sizeof(sc_desc)); + sc_desc.usage = WGPUTextureUsage_RenderAttachment; + sc_desc.format = _sapp.wgpu.render_format; + sc_desc.width = (uint32_t)_sapp.framebuffer_width; + sc_desc.height = (uint32_t)_sapp.framebuffer_height; + sc_desc.presentMode = WGPUPresentMode_Fifo; + _sapp.wgpu.swapchain = wgpuDeviceCreateSwapChain(_sapp.wgpu.device, _sapp.wgpu.surface, &sc_desc); + if (0 == _sapp.wgpu.swapchain) { + _SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_SWAPCHAIN_FAILED); + } WGPUTextureDescriptor ds_desc; _sapp_clear(&ds_desc, sizeof(ds_desc)); - ds_desc.usage = WGPUTextureUsage_OutputAttachment; + ds_desc.usage = WGPUTextureUsage_RenderAttachment; ds_desc.dimension = WGPUTextureDimension_2D; - ds_desc.size.width = (uint32_t) _sapp.framebuffer_width; - ds_desc.size.height = (uint32_t) _sapp.framebuffer_height; - ds_desc.size.depth = 1; - ds_desc.arrayLayerCount = 1; - ds_desc.format = WGPUTextureFormat_Depth24PlusStencil8; + ds_desc.size.width = (uint32_t)_sapp.framebuffer_width; + ds_desc.size.height = (uint32_t)_sapp.framebuffer_height; + ds_desc.size.depthOrArrayLayers = 1; + ds_desc.format = WGPUTextureFormat_Depth32FloatStencil8; ds_desc.mipLevelCount = 1; - ds_desc.sampleCount = _sapp.sample_count; - _sapp.emsc.wgpu.depth_stencil_tex = wgpuDeviceCreateTexture(_sapp.emsc.wgpu.device, &ds_desc); - _sapp.emsc.wgpu.depth_stencil_view = wgpuTextureCreateView(_sapp.emsc.wgpu.depth_stencil_tex, 0); + ds_desc.sampleCount = (uint32_t)_sapp.sample_count; + _sapp.wgpu.depth_stencil_tex = wgpuDeviceCreateTexture(_sapp.wgpu.device, &ds_desc); + if (0 == _sapp.wgpu.depth_stencil_tex) { + _SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_DEPTH_STENCIL_TEXTURE_FAILED); + } + _sapp.wgpu.depth_stencil_view = wgpuTextureCreateView(_sapp.wgpu.depth_stencil_tex, 0); + if (0 == _sapp.wgpu.depth_stencil_view) { + _SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_DEPTH_STENCIL_VIEW_FAILED); + } if (_sapp.sample_count > 1) { WGPUTextureDescriptor msaa_desc; _sapp_clear(&msaa_desc, sizeof(msaa_desc)); - msaa_desc.usage = WGPUTextureUsage_OutputAttachment; + msaa_desc.usage = WGPUTextureUsage_RenderAttachment; msaa_desc.dimension = WGPUTextureDimension_2D; - msaa_desc.size.width = (uint32_t) _sapp.framebuffer_width; - msaa_desc.size.height = (uint32_t) _sapp.framebuffer_height; - msaa_desc.size.depth = 1; - msaa_desc.arrayLayerCount = 1; - msaa_desc.format = _sapp.emsc.wgpu.render_format; + msaa_desc.size.width = (uint32_t)_sapp.framebuffer_width; + msaa_desc.size.height = (uint32_t)_sapp.framebuffer_height; + msaa_desc.size.depthOrArrayLayers = 1; + msaa_desc.format = _sapp.wgpu.render_format; msaa_desc.mipLevelCount = 1; - msaa_desc.sampleCount = _sapp.sample_count; - _sapp.emsc.wgpu.msaa_tex = wgpuDeviceCreateTexture(_sapp.emsc.wgpu.device, &msaa_desc); - _sapp.emsc.wgpu.msaa_view = wgpuTextureCreateView(_sapp.emsc.wgpu.msaa_tex, 0); + msaa_desc.sampleCount = (uint32_t)_sapp.sample_count; + _sapp.wgpu.msaa_tex = wgpuDeviceCreateTexture(_sapp.wgpu.device, &msaa_desc); + if (0 == _sapp.wgpu.msaa_tex) { + _SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_MSAA_TEXTURE_FAILED); + } + _sapp.wgpu.msaa_view = wgpuTextureCreateView(_sapp.wgpu.msaa_tex, 0); + if (0 == _sapp.wgpu.msaa_view) { + _SAPP_PANIC(WGPU_SWAPCHAIN_CREATE_MSAA_VIEW_FAILED); + } } } -_SOKOL_PRIVATE void _sapp_emsc_wgpu_surfaces_discard(void) { - if (_sapp.emsc.wgpu.msaa_tex) { - wgpuTextureRelease(_sapp.emsc.wgpu.msaa_tex); - _sapp.emsc.wgpu.msaa_tex = 0; +_SOKOL_PRIVATE void _sapp_emsc_wgpu_discard_swapchain(void) { + if (_sapp.wgpu.msaa_view) { + wgpuTextureViewRelease(_sapp.wgpu.msaa_view); + _sapp.wgpu.msaa_view = 0; + } + if (_sapp.wgpu.msaa_tex) { + wgpuTextureRelease(_sapp.wgpu.msaa_tex); + _sapp.wgpu.msaa_tex = 0; } - if (_sapp.emsc.wgpu.msaa_view) { - wgpuTextureViewRelease(_sapp.emsc.wgpu.msaa_view); - _sapp.emsc.wgpu.msaa_view = 0; + if (_sapp.wgpu.depth_stencil_view) { + wgpuTextureViewRelease(_sapp.wgpu.depth_stencil_view); + _sapp.wgpu.depth_stencil_view = 0; } - if (_sapp.emsc.wgpu.depth_stencil_tex) { - wgpuTextureRelease(_sapp.emsc.wgpu.depth_stencil_tex); - _sapp.emsc.wgpu.depth_stencil_tex = 0; + if (_sapp.wgpu.depth_stencil_tex) { + wgpuTextureRelease(_sapp.wgpu.depth_stencil_tex); + _sapp.wgpu.depth_stencil_tex = 0; } - if (_sapp.emsc.wgpu.depth_stencil_view) { - wgpuTextureViewRelease(_sapp.emsc.wgpu.depth_stencil_view); - _sapp.emsc.wgpu.depth_stencil_view = 0; + if (_sapp.wgpu.swapchain) { + wgpuSwapChainRelease(_sapp.wgpu.swapchain); + _sapp.wgpu.swapchain = 0; } + if (_sapp.wgpu.surface) { + wgpuSurfaceRelease(_sapp.wgpu.surface); + _sapp.wgpu.surface = 0; + } +} + +_SOKOL_PRIVATE void _sapp_emsc_wgpu_size_changed(void) { + _sapp_emsc_wgpu_discard_swapchain(); + _sapp_emsc_wgpu_create_swapchain(); } -_SOKOL_PRIVATE void _sapp_emsc_wgpu_next_frame(void) { - if (_sapp.emsc.wgpu.swapchain_view) { - wgpuTextureViewRelease(_sapp.emsc.wgpu.swapchain_view); +_SOKOL_PRIVATE void _sapp_emsc_wgpu_request_device_cb(WGPURequestDeviceStatus status, WGPUDevice device, const char* msg, void* userdata) { + _SOKOL_UNUSED(msg); + _SOKOL_UNUSED(userdata); + SOKOL_ASSERT(!_sapp.wgpu.async_init_done); + if (status != WGPURequestDeviceStatus_Success) { + if (status == WGPURequestDeviceStatus_Error) { + _SAPP_PANIC(WGPU_REQUEST_DEVICE_STATUS_ERROR); + } else { + _SAPP_PANIC(WGPU_REQUEST_DEVICE_STATUS_UNKNOWN); + } } - _sapp.emsc.wgpu.swapchain_view = wgpuSwapChainGetCurrentTextureView(_sapp.emsc.wgpu.swapchain); + SOKOL_ASSERT(device); + _sapp.wgpu.device = device; + _sapp_emsc_wgpu_create_swapchain(); + _sapp.wgpu.async_init_done = true; } -#endif + +_SOKOL_PRIVATE void _sapp_emsc_wgpu_request_adapter_cb(WGPURequestAdapterStatus status, WGPUAdapter adapter, const char* msg, void* userdata) { + _SOKOL_UNUSED(msg); + _SOKOL_UNUSED(userdata); + if (status != WGPURequestAdapterStatus_Success) { + switch (status) { + case WGPURequestAdapterStatus_Unavailable: _SAPP_PANIC(WGPU_REQUEST_ADAPTER_STATUS_UNAVAILABLE); break; + case WGPURequestAdapterStatus_Error: _SAPP_PANIC(WGPU_REQUEST_ADAPTER_STATUS_ERROR); break; + default: _SAPP_PANIC(WGPU_REQUEST_ADAPTER_STATUS_UNKNOWN); break; + } + } + SOKOL_ASSERT(adapter); + _sapp.wgpu.adapter = adapter; + const WGPUFeatureName requiredFeatures[1] = { + WGPUFeatureName_Depth32FloatStencil8, + }; + WGPUDeviceDescriptor dev_desc; + _sapp_clear(&dev_desc, sizeof(dev_desc)); + dev_desc.requiredFeaturesCount = 1, + dev_desc.requiredFeatures = requiredFeatures, + wgpuAdapterRequestDevice(adapter, &dev_desc, _sapp_emsc_wgpu_request_device_cb, 0); +} + +_SOKOL_PRIVATE void _sapp_emsc_wgpu_init(void) { + SOKOL_ASSERT(0 == _sapp.wgpu.instance); + SOKOL_ASSERT(!_sapp.wgpu.async_init_done); + _sapp.wgpu.instance = wgpuCreateInstance(0); + if (0 == _sapp.wgpu.instance) { + _SAPP_PANIC(WGPU_CREATE_INSTANCE_FAILED); + } + // FIXME: power preference? + wgpuInstanceRequestAdapter(_sapp.wgpu.instance, 0, _sapp_emsc_wgpu_request_adapter_cb, 0); +} + +_SOKOL_PRIVATE void _sapp_emsc_wgpu_frame(void) { + if (_sapp.wgpu.async_init_done) { + _sapp.wgpu.swapchain_view = wgpuSwapChainGetCurrentTextureView(_sapp.wgpu.swapchain); + _sapp_frame(); + wgpuTextureViewRelease(_sapp.wgpu.swapchain_view); + _sapp.wgpu.swapchain_view = 0; + } +} +#endif // SOKOL_WGPU _SOKOL_PRIVATE void _sapp_emsc_register_eventhandlers(void) { - emscripten_set_mousedown_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb); - emscripten_set_mouseup_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb); - emscripten_set_mousemove_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb); - emscripten_set_mouseenter_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb); - emscripten_set_mouseleave_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb); - emscripten_set_wheel_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_wheel_cb); + emscripten_set_mousedown_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_mouse_cb); + emscripten_set_mouseup_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_mouse_cb); + emscripten_set_mousemove_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_mouse_cb); + emscripten_set_mouseenter_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_mouse_cb); + emscripten_set_mouseleave_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_mouse_cb); + emscripten_set_wheel_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_wheel_cb); emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, _sapp_emsc_key_cb); emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, _sapp_emsc_key_cb); emscripten_set_keypress_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, _sapp_emsc_key_cb); - emscripten_set_touchstart_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_touch_cb); - emscripten_set_touchmove_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_touch_cb); - emscripten_set_touchend_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_touch_cb); - emscripten_set_touchcancel_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_touch_cb); + emscripten_set_touchstart_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_touch_cb); + emscripten_set_touchmove_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_touch_cb); + emscripten_set_touchend_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_touch_cb); + emscripten_set_touchcancel_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_touch_cb); emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, 0, true, _sapp_emsc_pointerlockchange_cb); emscripten_set_pointerlockerror_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, 0, true, _sapp_emsc_pointerlockerror_cb); emscripten_set_focus_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, _sapp_emsc_focus_cb); @@ -5724,28 +5797,28 @@ _SOKOL_PRIVATE void _sapp_emsc_register_eventhandlers(void) { sapp_js_add_clipboard_listener(); } if (_sapp.drop.enabled) { - sapp_js_add_dragndrop_listeners(&_sapp.html5_canvas_selector[1]); + sapp_js_add_dragndrop_listeners(&_sapp.emsc.canvas_selector[1]); } #if defined(SOKOL_GLES3) - emscripten_set_webglcontextlost_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_webgl_context_cb); - emscripten_set_webglcontextrestored_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_webgl_context_cb); + emscripten_set_webglcontextlost_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_webgl_context_cb); + emscripten_set_webglcontextrestored_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_webgl_context_cb); #endif } _SOKOL_PRIVATE void _sapp_emsc_unregister_eventhandlers() { - emscripten_set_mousedown_callback(_sapp.html5_canvas_selector, 0, true, 0); - emscripten_set_mouseup_callback(_sapp.html5_canvas_selector, 0, true, 0); - emscripten_set_mousemove_callback(_sapp.html5_canvas_selector, 0, true, 0); - emscripten_set_mouseenter_callback(_sapp.html5_canvas_selector, 0, true, 0); - emscripten_set_mouseleave_callback(_sapp.html5_canvas_selector, 0, true, 0); - emscripten_set_wheel_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_mousedown_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_mouseup_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_mousemove_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_mouseenter_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_mouseleave_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_wheel_callback(_sapp.emsc.canvas_selector, 0, true, 0); emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); emscripten_set_keypress_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); - emscripten_set_touchstart_callback(_sapp.html5_canvas_selector, 0, true, 0); - emscripten_set_touchmove_callback(_sapp.html5_canvas_selector, 0, true, 0); - emscripten_set_touchend_callback(_sapp.html5_canvas_selector, 0, true, 0); - emscripten_set_touchcancel_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_touchstart_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_touchmove_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_touchend_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_touchcancel_callback(_sapp.emsc.canvas_selector, 0, true, 0); emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, 0, true, 0); emscripten_set_pointerlockerror_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, 0, true, 0); emscripten_set_focus_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); @@ -5755,11 +5828,11 @@ _SOKOL_PRIVATE void _sapp_emsc_unregister_eventhandlers() { sapp_js_remove_clipboard_listener(); } if (_sapp.drop.enabled) { - sapp_js_remove_dragndrop_listeners(&_sapp.html5_canvas_selector[1]); + sapp_js_remove_dragndrop_listeners(&_sapp.emsc.canvas_selector[1]); } #if defined(SOKOL_GLES3) - emscripten_set_webglcontextlost_callback(_sapp.html5_canvas_selector, 0, true, 0); - emscripten_set_webglcontextrestored_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_webglcontextlost_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_webglcontextrestored_callback(_sapp.emsc.canvas_selector, 0, true, 0); #endif } @@ -5768,32 +5841,12 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_frame(double time, void* userData) { _sapp_timing_external(&_sapp.timing, time / 1000.0); #if defined(SOKOL_WGPU) - /* - on WebGPU, the emscripten frame callback will already be called while - the asynchronous WebGPU device and swapchain initialization is still - in progress - */ - switch (_sapp.emsc.wgpu.state) { - case _SAPP_EMSC_WGPU_STATE_INITIAL: - /* async JS init hasn't finished yet */ - break; - case _SAPP_EMSC_WGPU_STATE_READY: - /* perform post-async init stuff */ - _sapp_emsc_wgpu_surfaces_create(); - _sapp.emsc.wgpu.state = _SAPP_EMSC_WGPU_STATE_RUNNING; - break; - case _SAPP_EMSC_WGPU_STATE_RUNNING: - /* a regular frame */ - _sapp_emsc_wgpu_next_frame(); - _sapp_frame(); - break; - } + _sapp_emsc_wgpu_frame(); #else - /* WebGL code path */ _sapp_frame(); #endif - /* quit-handling */ + // quit-handling if (_sapp.quit_requested) { _sapp_init_event(SAPP_EVENTTYPE_QUIT_REQUESTED); _sapp_call_event(&_sapp.event); @@ -5812,14 +5865,14 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_frame(double time, void* userData) { _SOKOL_PRIVATE void _sapp_emsc_run(const sapp_desc* desc) { _sapp_init_state(desc); - sapp_js_init(&_sapp.html5_canvas_selector[1]); + sapp_js_init(&_sapp.emsc.canvas_selector[1]); double w, h; if (_sapp.desc.html5_canvas_resize) { w = (double) _sapp_def(_sapp.desc.width, _SAPP_FALLBACK_DEFAULT_WINDOW_WIDTH); h = (double) _sapp_def(_sapp.desc.height, _SAPP_FALLBACK_DEFAULT_WINDOW_HEIGHT); } else { - emscripten_get_element_css_size(_sapp.html5_canvas_selector, &w, &h); + emscripten_get_element_css_size(_sapp.emsc.canvas_selector, &w, &h); emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, false, _sapp_emsc_size_changed); } if (_sapp.desc.high_dpi) { @@ -5829,22 +5882,21 @@ _SOKOL_PRIVATE void _sapp_emsc_run(const sapp_desc* desc) { _sapp.window_height = (int)roundf(h); _sapp.framebuffer_width = (int)roundf(w * _sapp.dpi_scale); _sapp.framebuffer_height = (int)roundf(h * _sapp.dpi_scale); - emscripten_set_canvas_element_size(_sapp.html5_canvas_selector, _sapp.framebuffer_width, _sapp.framebuffer_height); + emscripten_set_canvas_element_size(_sapp.emsc.canvas_selector, _sapp.framebuffer_width, _sapp.framebuffer_height); #if defined(SOKOL_GLES3) _sapp_emsc_webgl_init(); #elif defined(SOKOL_WGPU) - sapp_js_wgpu_init(); + _sapp_emsc_wgpu_init(); #endif _sapp.valid = true; _sapp_emsc_register_eventhandlers(); sapp_set_icon(&desc->icon); - /* start the frame loop */ + // start the frame loop emscripten_request_animation_frame_loop(_sapp_emsc_frame, 0); - /* NOT A BUG: do not call _sapp_discard_state() here, instead this is - called in _sapp_emsc_frame() when the application is ordered to quit - */ + // NOT A BUG: do not call _sapp_discard_state() here, instead this is + // called in _sapp_emsc_frame() when the application is ordered to quit } #if !defined(SOKOL_NO_ENTRY) @@ -11030,7 +11082,7 @@ SOKOL_API_IMPL float sapp_heightf(void) { SOKOL_API_IMPL int sapp_color_format(void) { #if defined(_SAPP_EMSCRIPTEN) && defined(SOKOL_WGPU) - switch (_sapp.emsc.wgpu.render_format) { + switch (_sapp.wgpu.render_format) { case WGPUTextureFormat_RGBA8Unorm: return _SAPP_PIXELFORMAT_RGBA8; case WGPUTextureFormat_BGRA8Unorm: @@ -11458,7 +11510,7 @@ SOKOL_API_IMPL const void* sapp_win32_get_hwnd(void) { SOKOL_API_IMPL const void* sapp_wgpu_get_device(void) { SOKOL_ASSERT(_sapp.valid); #if defined(_SAPP_EMSCRIPTEN) && defined(SOKOL_WGPU) - return (const void*) _sapp.emsc.wgpu.device; + return (const void*) _sapp.wgpu.device; #else return 0; #endif @@ -11468,10 +11520,10 @@ SOKOL_API_IMPL const void* sapp_wgpu_get_render_view(void) { SOKOL_ASSERT(_sapp.valid); #if defined(_SAPP_EMSCRIPTEN) && defined(SOKOL_WGPU) if (_sapp.sample_count > 1) { - return (const void*) _sapp.emsc.wgpu.msaa_view; + return (const void*) _sapp.wgpu.msaa_view; } else { - return (const void*) _sapp.emsc.wgpu.swapchain_view; + return (const void*) _sapp.wgpu.swapchain_view; } #else return 0; @@ -11482,7 +11534,7 @@ SOKOL_API_IMPL const void* sapp_wgpu_get_resolve_view(void) { SOKOL_ASSERT(_sapp.valid); #if defined(_SAPP_EMSCRIPTEN) && defined(SOKOL_WGPU) if (_sapp.sample_count > 1) { - return (const void*) _sapp.emsc.wgpu.swapchain_view; + return (const void*) _sapp.wgpu.swapchain_view; } else { return 0; @@ -11495,7 +11547,7 @@ SOKOL_API_IMPL const void* sapp_wgpu_get_resolve_view(void) { SOKOL_API_IMPL const void* sapp_wgpu_get_depth_stencil_view(void) { SOKOL_ASSERT(_sapp.valid); #if defined(_SAPP_EMSCRIPTEN) && defined(SOKOL_WGPU) - return (const void*) _sapp.emsc.wgpu.depth_stencil_view; + return (const void*) _sapp.wgpu.depth_stencil_view; #else return 0; #endif From e4bf816bc3c563afaf7cfcc71b47f0af558ebd0b Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 28 Aug 2023 16:13:22 +0200 Subject: [PATCH 27/95] sokol_gfx.h wgpu: fix wrong SG_VERTEXFORMAT_USHORT2N mapping --- sokol_gfx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index b67a2c62b..dfceb0942 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12098,7 +12098,7 @@ _SOKOL_PRIVATE WGPUVertexFormat _sg_wgpu_vertexformat(sg_vertex_format f) { case SG_VERTEXFORMAT_UBYTE4N: return WGPUVertexFormat_Unorm8x4; case SG_VERTEXFORMAT_SHORT2: return WGPUVertexFormat_Sint16x2; case SG_VERTEXFORMAT_SHORT2N: return WGPUVertexFormat_Snorm16x2; - case SG_VERTEXFORMAT_USHORT2N: return WGPUVertexFormat_Uint16x2; + case SG_VERTEXFORMAT_USHORT2N: return WGPUVertexFormat_Unorm16x2; case SG_VERTEXFORMAT_SHORT4: return WGPUVertexFormat_Sint16x4; case SG_VERTEXFORMAT_SHORT4N: return WGPUVertexFormat_Snorm16x4; case SG_VERTEXFORMAT_USHORT4N: return WGPUVertexFormat_Unorm16x4; From f750e22e3af09796141b9dd6951722cb4e146d26 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 28 Aug 2023 16:46:28 +0200 Subject: [PATCH 28/95] sokol_app.h emsc: revert _sapp.html5_canvas_selector => _sapp.emsc.canvas_selector change --- sokol_app.h | 78 ++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/sokol_app.h b/sokol_app.h index d0975861b..1a13ba7b8 100644 --- a/sokol_app.h +++ b/sokol_app.h @@ -2396,7 +2396,6 @@ typedef struct { bool wants_hide_keyboard; bool mouse_lock_requested; uint16_t mouse_buttons; - char canvas_selector[_SAPP_MAX_TITLE_LENGTH]; } _sapp_emsc_t; #endif // _SAPP_EMSCRIPTEN @@ -2797,8 +2796,9 @@ typedef struct { _sapp_egl_t egl; #endif #endif - char window_title[_SAPP_MAX_TITLE_LENGTH]; /* UTF-8 */ - wchar_t window_title_wide[_SAPP_MAX_TITLE_LENGTH]; /* UTF-32 or UCS-2 */ + char html5_canvas_selector[_SAPP_MAX_TITLE_LENGTH]; + char window_title[_SAPP_MAX_TITLE_LENGTH]; // UTF-8 + wchar_t window_title_wide[_SAPP_MAX_TITLE_LENGTH]; // UTF-32 or UCS-2 */ sapp_keycode keycodes[SAPP_MAX_KEYCODES]; } _sapp_t; static _sapp_t _sapp; @@ -3020,9 +3020,9 @@ _SOKOL_PRIVATE void _sapp_init_state(const sapp_desc* desc) { _sapp.framebuffer_height = _sapp.window_height; _sapp.sample_count = _sapp.desc.sample_count; _sapp.swap_interval = _sapp.desc.swap_interval; - _sapp.emsc.canvas_selector[0] = '#'; - _sapp_strcpy(_sapp.desc.html5_canvas_name, &_sapp.emsc.canvas_selector[1], sizeof(_sapp.emsc.canvas_selector) - 1); - _sapp.desc.html5_canvas_name = &_sapp.emsc.canvas_selector[1]; + _sapp.html5_canvas_selector[0] = '#'; + _sapp_strcpy(_sapp.desc.html5_canvas_name, &_sapp.html5_canvas_selector[1], sizeof(_sapp.html5_canvas_selector) - 1); + _sapp.desc.html5_canvas_name = &_sapp.html5_canvas_selector[1]; _sapp.html5_ask_leave_site = _sapp.desc.html5_ask_leave_site; _sapp.clipboard.enabled = _sapp.desc.enable_clipboard; if (_sapp.clipboard.enabled) { @@ -5092,7 +5092,7 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_size_changed(int event_type, const EmscriptenU _SOKOL_UNUSED(event_type); _SOKOL_UNUSED(user_data); double w, h; - emscripten_get_element_css_size(_sapp.emsc.canvas_selector, &w, &h); + emscripten_get_element_css_size(_sapp.html5_canvas_selector, &w, &h); /* The above method might report zero when toggling HTML5 fullscreen, in that case use the window's inner width reported by the emscripten event. This works ok when toggling *into* fullscreen @@ -5131,7 +5131,7 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_size_changed(int event_type, const EmscriptenU _sapp.framebuffer_width = (int)roundf(w * _sapp.dpi_scale); _sapp.framebuffer_height = (int)roundf(h * _sapp.dpi_scale); SOKOL_ASSERT((_sapp.framebuffer_width > 0) && (_sapp.framebuffer_height > 0)); - emscripten_set_canvas_element_size(_sapp.emsc.canvas_selector, _sapp.framebuffer_width, _sapp.framebuffer_height); + emscripten_set_canvas_element_size(_sapp.html5_canvas_selector, _sapp.framebuffer_width, _sapp.framebuffer_height); #if defined(SOKOL_WGPU) // on WebGPU: recreate size-dependent rendering surfaces _sapp_emsc_wgpu_size_changed(); @@ -5594,7 +5594,7 @@ _SOKOL_PRIVATE void _sapp_emsc_webgl_init(void) { attrs.preserveDrawingBuffer = _sapp.desc.html5_preserve_drawing_buffer; attrs.enableExtensionsByDefault = true; attrs.majorVersion = 2; - EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(_sapp.emsc.canvas_selector, &attrs); + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(_sapp.html5_canvas_selector, &attrs); // FIXME: error message? emscripten_webgl_make_context_current(ctx); @@ -5619,7 +5619,7 @@ _SOKOL_PRIVATE void _sapp_emsc_wgpu_create_swapchain(void) { WGPUSurfaceDescriptorFromCanvasHTMLSelector canvas_desc; _sapp_clear(&canvas_desc, sizeof(canvas_desc)); canvas_desc.chain.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector; - canvas_desc.selector = _sapp.emsc.canvas_selector; + canvas_desc.selector = _sapp.html5_canvas_selector; WGPUSurfaceDescriptor surf_desc; _sapp_clear(&surf_desc, sizeof(surf_desc)); surf_desc.nextInChain = &canvas_desc.chain; @@ -5775,19 +5775,19 @@ _SOKOL_PRIVATE void _sapp_emsc_wgpu_frame(void) { #endif // SOKOL_WGPU _SOKOL_PRIVATE void _sapp_emsc_register_eventhandlers(void) { - emscripten_set_mousedown_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_mouse_cb); - emscripten_set_mouseup_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_mouse_cb); - emscripten_set_mousemove_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_mouse_cb); - emscripten_set_mouseenter_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_mouse_cb); - emscripten_set_mouseleave_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_mouse_cb); - emscripten_set_wheel_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_wheel_cb); + emscripten_set_mousedown_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb); + emscripten_set_mouseup_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb); + emscripten_set_mousemove_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb); + emscripten_set_mouseenter_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb); + emscripten_set_mouseleave_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_mouse_cb); + emscripten_set_wheel_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_wheel_cb); emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, _sapp_emsc_key_cb); emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, _sapp_emsc_key_cb); emscripten_set_keypress_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, _sapp_emsc_key_cb); - emscripten_set_touchstart_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_touch_cb); - emscripten_set_touchmove_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_touch_cb); - emscripten_set_touchend_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_touch_cb); - emscripten_set_touchcancel_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_touch_cb); + emscripten_set_touchstart_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_touch_cb); + emscripten_set_touchmove_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_touch_cb); + emscripten_set_touchend_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_touch_cb); + emscripten_set_touchcancel_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_touch_cb); emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, 0, true, _sapp_emsc_pointerlockchange_cb); emscripten_set_pointerlockerror_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, 0, true, _sapp_emsc_pointerlockerror_cb); emscripten_set_focus_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, _sapp_emsc_focus_cb); @@ -5797,28 +5797,28 @@ _SOKOL_PRIVATE void _sapp_emsc_register_eventhandlers(void) { sapp_js_add_clipboard_listener(); } if (_sapp.drop.enabled) { - sapp_js_add_dragndrop_listeners(&_sapp.emsc.canvas_selector[1]); + sapp_js_add_dragndrop_listeners(&_sapp.html5_canvas_selector[1]); } #if defined(SOKOL_GLES3) - emscripten_set_webglcontextlost_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_webgl_context_cb); - emscripten_set_webglcontextrestored_callback(_sapp.emsc.canvas_selector, 0, true, _sapp_emsc_webgl_context_cb); + emscripten_set_webglcontextlost_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_webgl_context_cb); + emscripten_set_webglcontextrestored_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_webgl_context_cb); #endif } _SOKOL_PRIVATE void _sapp_emsc_unregister_eventhandlers() { - emscripten_set_mousedown_callback(_sapp.emsc.canvas_selector, 0, true, 0); - emscripten_set_mouseup_callback(_sapp.emsc.canvas_selector, 0, true, 0); - emscripten_set_mousemove_callback(_sapp.emsc.canvas_selector, 0, true, 0); - emscripten_set_mouseenter_callback(_sapp.emsc.canvas_selector, 0, true, 0); - emscripten_set_mouseleave_callback(_sapp.emsc.canvas_selector, 0, true, 0); - emscripten_set_wheel_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_mousedown_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_mouseup_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_mousemove_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_mouseenter_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_mouseleave_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_wheel_callback(_sapp.html5_canvas_selector, 0, true, 0); emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); emscripten_set_keypress_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); - emscripten_set_touchstart_callback(_sapp.emsc.canvas_selector, 0, true, 0); - emscripten_set_touchmove_callback(_sapp.emsc.canvas_selector, 0, true, 0); - emscripten_set_touchend_callback(_sapp.emsc.canvas_selector, 0, true, 0); - emscripten_set_touchcancel_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_touchstart_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_touchmove_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_touchend_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_touchcancel_callback(_sapp.html5_canvas_selector, 0, true, 0); emscripten_set_pointerlockchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, 0, true, 0); emscripten_set_pointerlockerror_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, 0, true, 0); emscripten_set_focus_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); @@ -5828,11 +5828,11 @@ _SOKOL_PRIVATE void _sapp_emsc_unregister_eventhandlers() { sapp_js_remove_clipboard_listener(); } if (_sapp.drop.enabled) { - sapp_js_remove_dragndrop_listeners(&_sapp.emsc.canvas_selector[1]); + sapp_js_remove_dragndrop_listeners(&_sapp.html5_canvas_selector[1]); } #if defined(SOKOL_GLES3) - emscripten_set_webglcontextlost_callback(_sapp.emsc.canvas_selector, 0, true, 0); - emscripten_set_webglcontextrestored_callback(_sapp.emsc.canvas_selector, 0, true, 0); + emscripten_set_webglcontextlost_callback(_sapp.html5_canvas_selector, 0, true, 0); + emscripten_set_webglcontextrestored_callback(_sapp.html5_canvas_selector, 0, true, 0); #endif } @@ -5865,14 +5865,14 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_frame(double time, void* userData) { _SOKOL_PRIVATE void _sapp_emsc_run(const sapp_desc* desc) { _sapp_init_state(desc); - sapp_js_init(&_sapp.emsc.canvas_selector[1]); + sapp_js_init(&_sapp.html5_canvas_selector[1]); double w, h; if (_sapp.desc.html5_canvas_resize) { w = (double) _sapp_def(_sapp.desc.width, _SAPP_FALLBACK_DEFAULT_WINDOW_WIDTH); h = (double) _sapp_def(_sapp.desc.height, _SAPP_FALLBACK_DEFAULT_WINDOW_HEIGHT); } else { - emscripten_get_element_css_size(_sapp.emsc.canvas_selector, &w, &h); + emscripten_get_element_css_size(_sapp.html5_canvas_selector, &w, &h); emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, false, _sapp_emsc_size_changed); } if (_sapp.desc.high_dpi) { @@ -5882,7 +5882,7 @@ _SOKOL_PRIVATE void _sapp_emsc_run(const sapp_desc* desc) { _sapp.window_height = (int)roundf(h); _sapp.framebuffer_width = (int)roundf(w * _sapp.dpi_scale); _sapp.framebuffer_height = (int)roundf(h * _sapp.dpi_scale); - emscripten_set_canvas_element_size(_sapp.emsc.canvas_selector, _sapp.framebuffer_width, _sapp.framebuffer_height); + emscripten_set_canvas_element_size(_sapp.html5_canvas_selector, _sapp.framebuffer_width, _sapp.framebuffer_height); #if defined(SOKOL_GLES3) _sapp_emsc_webgl_init(); #elif defined(SOKOL_WGPU) From e453b7726d7db2d79831d769485d3ea507bbe995 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 30 Aug 2023 20:22:58 +0200 Subject: [PATCH 29/95] sokol_gfx.h: harmonize sg_sampler_type names with webgpu --- sokol_gfx.h | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 697c2e9f5..31fe1bffb 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -1662,8 +1662,9 @@ typedef enum sg_image_sample_type { */ typedef enum sg_sampler_type { _SG_SAMPLERTYPE_DEFAULT, - SG_SAMPLERTYPE_SAMPLE, - SG_SAMPLERTYPE_COMPARE, + SG_SAMPLERTYPE_FILTERING, + SG_SAMPLERTYPE_NONFILTERING, + SG_SAMPLERTYPE_COMPARISON, _SG_SAMPLERTYPE_NUM, _SG_SAMPLERTYPE_FORCE_U32, } sg_sampler_type; @@ -3072,8 +3073,8 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_IMAGE_MSAA, "sg_apply_bindings: cannot bind image with sample_count>1 to vertex stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_IMAGE_BINDING, "sg_apply_bindings: unexpected image binding on vertex stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_SAMPLER_BINDING, "sg_apply_bindings: missing sampler binding on vertex stage") \ - _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_COMPARE on vertex stage but sampler has SG_COMPAREFUNC_NEVER") \ - _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_SAMPLE on vertex stage but sampler doesn't have SG_COMPAREFUNC_NEVER") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_COMPARISON on vertex stage but sampler has SG_COMPAREFUNC_NEVER") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_FILTERING on vertex stage but sampler doesn't have SG_COMPAREFUNC_NEVER") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_SAMPLER_BINDING, "sg_apply_bindings: unexpected sampler binding on vertex stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_SMP_EXISTS, "sg_apply_bindings: sampler bound to vertex stage no longer alive") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_IMG_SMP_MIPMAPS, "sg_apply_bindings: image bound to vertex stage has mipmap_count == 1, but associated sampler mipmap filer is not SG_MIPMAPFILTER_NONE") \ @@ -3083,8 +3084,8 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_IMAGE_MSAA, "sg_apply_bindings: cannot bind image with sample_count>1 to fragment stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_IMAGE_BINDING, "sg_apply_bindings: unexpected image binding on fragment stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_SAMPLER_BINDING, "sg_apply_bindings: missing sampler binding on fragment stage") \ - _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_COMPARE on fragment stage but sampler has SG_COMPAREFUNC_NEVER") \ - _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_SAMPLE on fragment stage but sampler doesn't have SG_COMPAREFUNC_NEVER") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_COMPARISON on fragment stage but sampler has SG_COMPAREFUNC_NEVER") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_FILTERING on fragment stage but sampler doesn't have SG_COMPAREFUNC_NEVER") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_SAMPLER_BINDING, "sg_apply_bindings: unexpected sampler binding on fragment stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_SMP_EXISTS, "sg_apply_bindings: sampler bound to fragment stage no longer alive") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_IMG_SMP_MIPMAPS, "sg_apply_bindings: image bound to fragment stage has mipmap_count == 1, but associated sampler mipmap filer is not SG_MIPMAPFILTER_NONE") \ @@ -12017,9 +12018,9 @@ _SOKOL_PRIVATE WGPUTextureSampleType _sg_wgpu_texture_sample_type(sg_image_sampl _SOKOL_PRIVATE WGPUSamplerBindingType _sg_wgpu_sampler_binding_type(sg_sampler_type t) { switch (t) { - // FIXME: NonFiltering - case SG_SAMPLERTYPE_SAMPLE: return WGPUSamplerBindingType_Filtering; - case SG_SAMPLERTYPE_COMPARE: return WGPUSamplerBindingType_Comparison; + case SG_SAMPLERTYPE_FILTERING: return WGPUSamplerBindingType_Filtering; + case SG_SAMPLERTYPE_COMPARISON: return WGPUSamplerBindingType_Comparison; + case SG_SAMPLERTYPE_NONFILTERING: return WGPUSamplerBindingType_NonFiltering; default: SOKOL_UNREACHABLE; return WGPUSamplerBindingType_Force32; } } @@ -14942,7 +14943,7 @@ _SOKOL_PRIVATE bool _sg_validate_apply_bindings(const sg_bindings* bindings) { const _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, bindings->vs.samplers[i].id); _SG_VALIDATE(smp != 0, VALIDATE_ABND_VS_SMP_EXISTS); if (smp) { - if (stage->samplers[i].sampler_type == SG_SAMPLERTYPE_COMPARE) { + if (stage->samplers[i].sampler_type == SG_SAMPLERTYPE_COMPARISON) { _SG_VALIDATE(smp->cmn.compare != SG_COMPAREFUNC_NEVER, VALIDATE_ABND_VS_UNEXPECTED_SAMPLER_COMPARE_NEVER); } else { _SG_VALIDATE(smp->cmn.compare == SG_COMPAREFUNC_NEVER, VALIDATE_ABND_VS_EXPECTED_SAMPLER_COMPARE_NEVER); @@ -14981,7 +14982,7 @@ _SOKOL_PRIVATE bool _sg_validate_apply_bindings(const sg_bindings* bindings) { const _sg_sampler_t* smp = _sg_lookup_sampler(&_sg.pools, bindings->fs.samplers[i].id); _SG_VALIDATE(smp != 0, VALIDATE_ABND_FS_SMP_EXISTS); if (smp) { - if (stage->samplers[i].sampler_type == SG_SAMPLERTYPE_COMPARE) { + if (stage->samplers[i].sampler_type == SG_SAMPLERTYPE_COMPARISON) { _SG_VALIDATE(smp->cmn.compare != SG_COMPAREFUNC_NEVER, VALIDATE_ABND_FS_UNEXPECTED_SAMPLER_COMPARE_NEVER); } else { _SG_VALIDATE(smp->cmn.compare == SG_COMPAREFUNC_NEVER, VALIDATE_ABND_FS_EXPECTED_SAMPLER_COMPARE_NEVER); @@ -15210,7 +15211,7 @@ _SOKOL_PRIVATE sg_shader_desc _sg_shader_desc_defaults(const sg_shader_desc* des if (!smp_desc->used) { break; } - smp_desc->sampler_type = _sg_def(smp_desc->sampler_type, SG_SAMPLERTYPE_SAMPLE); + smp_desc->sampler_type = _sg_def(smp_desc->sampler_type, SG_SAMPLERTYPE_FILTERING); } } return def; From eeb975cf9c1796819ec5578582ea435ac8e9c4fe Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 31 Aug 2023 16:54:02 +0200 Subject: [PATCH 30/95] sg_sampler_type renaming fixes --- tests/functional/sokol_gfx_test.c | 16 ++++++++-------- util/sokol_debugtext.h | 2 +- util/sokol_fontstash.h | 2 +- util/sokol_gfx_imgui.h | 8 +++++--- util/sokol_gl.h | 2 +- util/sokol_imgui.h | 2 +- util/sokol_nuklear.h | 2 +- util/sokol_spine.h | 2 +- 8 files changed, 19 insertions(+), 17 deletions(-) diff --git a/tests/functional/sokol_gfx_test.c b/tests/functional/sokol_gfx_test.c index 28084e0f3..90d460afe 100644 --- a/tests/functional/sokol_gfx_test.c +++ b/tests/functional/sokol_gfx_test.c @@ -1064,8 +1064,8 @@ UTEST(sokol_gfx, query_shader_desc) { }, .images[0] = { .used = true, .image_type = SG_IMAGETYPE_2D, .sample_type = SG_IMAGESAMPLETYPE_FLOAT, .multisampled = true }, .images[1] = { .used = true, .image_type = SG_IMAGETYPE_3D, .sample_type = SG_IMAGESAMPLETYPE_SINT }, - .samplers[0] = { .used = true, .sampler_type = SG_SAMPLERTYPE_SAMPLE }, - .samplers[1] = { .used = true, .sampler_type = SG_SAMPLERTYPE_COMPARE }, + .samplers[0] = { .used = true, .sampler_type = SG_SAMPLERTYPE_FILTERING }, + .samplers[1] = { .used = true, .sampler_type = SG_SAMPLERTYPE_COMPARISON }, .image_sampler_pairs[0] = { .used = true, .image_slot = 0, .sampler_slot = 1, .glsl_name = "img0" }, .image_sampler_pairs[1] = { .used = true, .image_slot = 1, .sampler_slot = 0, .glsl_name = "img1" }, }, @@ -1073,8 +1073,8 @@ UTEST(sokol_gfx, query_shader_desc) { .source = "fs_source", .images[0] = { .used = true, .image_type = SG_IMAGETYPE_ARRAY, .sample_type = SG_IMAGESAMPLETYPE_DEPTH }, .images[1] = { .used = true, .image_type = SG_IMAGETYPE_CUBE, .sample_type = SG_IMAGESAMPLETYPE_FLOAT }, - .samplers[0] = { .used = true, .sampler_type = SG_SAMPLERTYPE_COMPARE }, - .samplers[1] = { .used = true, .sampler_type = SG_SAMPLERTYPE_SAMPLE }, + .samplers[0] = { .used = true, .sampler_type = SG_SAMPLERTYPE_COMPARISON }, + .samplers[1] = { .used = true, .sampler_type = SG_SAMPLERTYPE_FILTERING }, .image_sampler_pairs[0] = { .used = true, .image_slot = 0, .sampler_slot = 0, .glsl_name = "img3" }, .image_sampler_pairs[1] = { .used = true, .image_slot = 1, .sampler_slot = 1, .glsl_name = "img4" }, }, @@ -1099,9 +1099,9 @@ UTEST(sokol_gfx, query_shader_desc) { T(s0_desc.vs.images[1].sample_type == SG_IMAGESAMPLETYPE_SINT); T(s0_desc.vs.images[1].multisampled == false); T(s0_desc.vs.samplers[0].used); - T(s0_desc.vs.samplers[0].sampler_type == SG_SAMPLERTYPE_SAMPLE); + T(s0_desc.vs.samplers[0].sampler_type == SG_SAMPLERTYPE_FILTERING); T(s0_desc.vs.samplers[1].used); - T(s0_desc.vs.samplers[1].sampler_type == SG_SAMPLERTYPE_COMPARE); + T(s0_desc.vs.samplers[1].sampler_type == SG_SAMPLERTYPE_COMPARISON); T(s0_desc.vs.image_sampler_pairs[0].used); T(s0_desc.vs.image_sampler_pairs[0].image_slot == 0); T(s0_desc.vs.image_sampler_pairs[0].sampler_slot == 1); @@ -1125,9 +1125,9 @@ UTEST(sokol_gfx, query_shader_desc) { T(s0_desc.fs.images[1].sample_type == SG_IMAGESAMPLETYPE_FLOAT); T(s0_desc.fs.images[1].multisampled == false); T(s0_desc.fs.samplers[0].used); - T(s0_desc.fs.samplers[0].sampler_type == SG_SAMPLERTYPE_COMPARE); + T(s0_desc.fs.samplers[0].sampler_type == SG_SAMPLERTYPE_COMPARISON); T(s0_desc.fs.samplers[1].used); - T(s0_desc.fs.samplers[1].sampler_type == SG_SAMPLERTYPE_SAMPLE); + T(s0_desc.fs.samplers[1].sampler_type == SG_SAMPLERTYPE_FILTERING); T(s0_desc.fs.image_sampler_pairs[0].used); T(s0_desc.fs.image_sampler_pairs[0].image_slot == 0); T(s0_desc.fs.image_sampler_pairs[0].sampler_slot == 0); diff --git a/util/sokol_debugtext.h b/util/sokol_debugtext.h index 4d4ee6e1f..b0af45dd3 100644 --- a/util/sokol_debugtext.h +++ b/util/sokol_debugtext.h @@ -4007,7 +4007,7 @@ static void _sdtx_setup_common(void) { shd_desc.fs.images[0].image_type = SG_IMAGETYPE_2D; shd_desc.fs.images[0].sample_type = SG_IMAGESAMPLETYPE_FLOAT; shd_desc.fs.samplers[0].used = true; - shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_SAMPLE; + shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_FILTERING; shd_desc.fs.image_sampler_pairs[0].used = true; shd_desc.fs.image_sampler_pairs[0].image_slot = 0; shd_desc.fs.image_sampler_pairs[0].sampler_slot = 0; diff --git a/util/sokol_fontstash.h b/util/sokol_fontstash.h index 9719e3802..46950e45c 100644 --- a/util/sokol_fontstash.h +++ b/util/sokol_fontstash.h @@ -1663,7 +1663,7 @@ static int _sfons_render_create(void* user_ptr, int width, int height) { shd_desc.fs.images[0].image_type = SG_IMAGETYPE_2D; shd_desc.fs.images[0].sample_type = SG_IMAGESAMPLETYPE_FLOAT; shd_desc.fs.samplers[0].used = true; - shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_SAMPLE; + shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_FILTERING; shd_desc.fs.image_sampler_pairs[0].used = true; shd_desc.fs.image_sampler_pairs[0].glsl_name = "tex_smp"; shd_desc.fs.image_sampler_pairs[0].image_slot = 0; diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h index f9106f1bb..9685331c9 100644 --- a/util/sokol_gfx_imgui.h +++ b/util/sokol_gfx_imgui.h @@ -1136,15 +1136,17 @@ _SOKOL_PRIVATE const char* _sg_imgui_imagesampletype_string(sg_image_sample_type case SG_IMAGESAMPLETYPE_DEPTH: return "SG_IMAGESAMPLETYPE_DEPTH"; case SG_IMAGESAMPLETYPE_SINT: return "SG_IMAGESAMPLETYPE_SINT"; case SG_IMAGESAMPLETYPE_UINT: return "SG_IMAGESAMPLETYPE_UINT"; + case SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT: return "SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT"; default: return "???"; } } _SOKOL_PRIVATE const char* _sg_imgui_samplertype_string(sg_sampler_type t) { switch (t) { - case SG_SAMPLERTYPE_SAMPLE: return "SG_SAMPLERTYPE_SAMPLE"; - case SG_SAMPLERTYPE_COMPARE: return "SG_SAMPLERTYPE_COMPARE"; - default: return "???"; + case SG_SAMPLERTYPE_FILTERING: return "SG_SAMPLERTYPE_FILTERING"; + case SG_SAMPLERTYPE_COMPARISON: return "SG_SAMPLERTYPE_COMPARISON"; + case SG_SAMPLERTYPE_NONFILTERING: return "SG_SAMPLERTYPE_NONFILTERING"; + default: return "???"; } } diff --git a/util/sokol_gl.h b/util/sokol_gl.h index f17da4788..7fe1d936f 100644 --- a/util/sokol_gl.h +++ b/util/sokol_gl.h @@ -3344,7 +3344,7 @@ static void _sgl_setup_common(void) { shd_desc.fs.images[0].image_type = SG_IMAGETYPE_2D; shd_desc.fs.images[0].sample_type = SG_IMAGESAMPLETYPE_FLOAT; shd_desc.fs.samplers[0].used = true; - shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_SAMPLE; + shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_FILTERING; shd_desc.fs.image_sampler_pairs[0].used = true; shd_desc.fs.image_sampler_pairs[0].image_slot = 0; shd_desc.fs.image_sampler_pairs[0].sampler_slot = 0; diff --git a/util/sokol_imgui.h b/util/sokol_imgui.h index 024b37618..e8abe7d81 100644 --- a/util/sokol_imgui.h +++ b/util/sokol_imgui.h @@ -2363,7 +2363,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) { shd_desc.fs.images[0].image_type = SG_IMAGETYPE_2D; shd_desc.fs.images[0].sample_type = SG_IMAGESAMPLETYPE_FLOAT; shd_desc.fs.samplers[0].used = true; - shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_SAMPLE; + shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_FILTERING; shd_desc.fs.image_sampler_pairs[0].used = true; shd_desc.fs.image_sampler_pairs[0].image_slot = 0; shd_desc.fs.image_sampler_pairs[0].sampler_slot = 0; diff --git a/util/sokol_nuklear.h b/util/sokol_nuklear.h index ae4e9ae09..8a5cfb8d3 100644 --- a/util/sokol_nuklear.h +++ b/util/sokol_nuklear.h @@ -2293,7 +2293,7 @@ SOKOL_API_IMPL void snk_setup(const snk_desc_t* desc) { .entry = fs_entry, .d3d11_target = "ps_4_0", .images[0] = { .used = true, .image_type = SG_IMAGETYPE_2D, .sample_type = SG_IMAGESAMPLETYPE_FLOAT }, - .samplers[0] = { .used = true, .sampler_type = SG_SAMPLERTYPE_SAMPLE }, + .samplers[0] = { .used = true, .sampler_type = SG_SAMPLERTYPE_FILTERING }, .image_sampler_pairs[0] = { .used = true, .glsl_name = "tex_smp", .image_slot = 0, .sampler_slot = 0 }, }, .label = "sokol-nuklear-shader" diff --git a/util/sokol_spine.h b/util/sokol_spine.h index 5a9125aea..0ca556c8c 100644 --- a/util/sokol_spine.h +++ b/util/sokol_spine.h @@ -4521,7 +4521,7 @@ static void _sspine_init_shared(void) { shd_desc.fs.images[0].image_type = SG_IMAGETYPE_2D; shd_desc.fs.images[0].sample_type = SG_IMAGESAMPLETYPE_FLOAT; shd_desc.fs.samplers[0].used = true; - shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_SAMPLE; + shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_FILTERING; shd_desc.fs.image_sampler_pairs[0].used = true; shd_desc.fs.image_sampler_pairs[0].image_slot = 0; shd_desc.fs.image_sampler_pairs[0].sampler_slot = 0; From f697ca389123e8bc34b685fd50092d84433a800a Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 2 Sep 2023 18:15:09 +0200 Subject: [PATCH 31/95] sokol_debugtext.h: fix embedded wgsl shader --- util/sokol_debugtext.h | 270 ++++++++++++++++------------------------- 1 file changed, 104 insertions(+), 166 deletions(-) diff --git a/util/sokol_debugtext.h b/util/sokol_debugtext.h index b0af45dd3..981cab465 100644 --- a/util/sokol_debugtext.h +++ b/util/sokol_debugtext.h @@ -3351,171 +3351,109 @@ static const uint8_t _sdtx_fs_bytecode_hlsl4[608] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #elif defined(SOKOL_WGPU) -static const uint8_t _sdtx_vs_bytecode_wgpu[1648] = { - 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x08,0x00,0x08,0x00,0x2e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00, - 0x02,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x24,0x00,0x00,0x00, - 0x25,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x2c,0x00,0x00,0x00, - 0x2d,0x00,0x00,0x00,0x07,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x37,0x00,0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65, - 0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x76,0x75,0x6c,0x6b, - 0x61,0x6e,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c, - 0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e, - 0x74,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f, - 0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64, - 0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d,0x65,0x6e,0x76,0x20,0x76,0x75,0x6c,0x6b, - 0x61,0x6e,0x31,0x2e,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c, - 0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65, - 0x74,0x2d,0x65,0x6e,0x76,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x0a,0x2f,0x2f,0x20, - 0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65, - 0x64,0x20,0x65,0x6e,0x74,0x72,0x79,0x2d,0x70,0x6f,0x69,0x6e,0x74,0x20,0x6d,0x61, - 0x69,0x6e,0x0a,0x23,0x6c,0x69,0x6e,0x65,0x20,0x31,0x0a,0x00,0x05,0x00,0x04,0x00, - 0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00, - 0x0c,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x65,0x72,0x56,0x65,0x72,0x74,0x65,0x78, - 0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x06,0x00,0x07,0x00, - 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74, - 0x53,0x69,0x7a,0x65,0x00,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x0c,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x67,0x6c,0x5f,0x43,0x6c,0x69,0x70,0x44,0x69,0x73,0x74,0x61, - 0x6e,0x63,0x65,0x00,0x06,0x00,0x07,0x00,0x0c,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x43,0x75,0x6c,0x6c,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,0x00, - 0x05,0x00,0x03,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00, - 0x13,0x00,0x00,0x00,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00, - 0x05,0x00,0x03,0x00,0x24,0x00,0x00,0x00,0x75,0x76,0x00,0x00,0x05,0x00,0x05,0x00, - 0x25,0x00,0x00,0x00,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x00,0x00,0x00, - 0x05,0x00,0x04,0x00,0x27,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00, - 0x05,0x00,0x04,0x00,0x29,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x00,0x00, - 0x05,0x00,0x05,0x00,0x2c,0x00,0x00,0x00,0x67,0x6c,0x5f,0x56,0x65,0x72,0x74,0x65, - 0x78,0x49,0x44,0x00,0x05,0x00,0x06,0x00,0x2d,0x00,0x00,0x00,0x67,0x6c,0x5f,0x49, - 0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x49,0x44,0x00,0x00,0x00,0x48,0x00,0x05,0x00, - 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x48,0x00,0x05,0x00,0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0c,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0c,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x47,0x00,0x03,0x00, - 0x0c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x13,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x24,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x25,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x27,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x29,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x2c,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x2d,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x13,0x00,0x02,0x00,0x03,0x00,0x00,0x00, - 0x21,0x00,0x03,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x00,0x03,0x00, - 0x07,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x08,0x00,0x00,0x00, - 0x07,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x09,0x00,0x00,0x00, - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x09,0x00,0x00,0x00, - 0x0a,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x04,0x00,0x0b,0x00,0x00,0x00, - 0x07,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x1e,0x00,0x06,0x00,0x0c,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x15,0x00,0x04,0x00,0x0f,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x0f,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x11,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x40, - 0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0xc0, - 0x2c,0x00,0x05,0x00,0x11,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x15,0x00,0x00,0x00, - 0x16,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x19,0x00,0x00,0x00, - 0x00,0x00,0x80,0xbf,0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x1a,0x00,0x00,0x00, - 0x00,0x00,0x80,0x3f,0x2c,0x00,0x05,0x00,0x11,0x00,0x00,0x00,0x1b,0x00,0x00,0x00, - 0x19,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00, - 0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x21,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x23,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x23,0x00,0x00,0x00, - 0x24,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x12,0x00,0x00,0x00, - 0x25,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x21,0x00,0x00,0x00, - 0x27,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x28,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x28,0x00,0x00,0x00, - 0x29,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x2b,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x2b,0x00,0x00,0x00, - 0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x2b,0x00,0x00,0x00, - 0x2d,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x36,0x00,0x05,0x00,0x03,0x00,0x00,0x00, - 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0x00,0x02,0x00, - 0x06,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x14,0x00,0x00,0x00, - 0x13,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x11,0x00,0x00,0x00,0x18,0x00,0x00,0x00, - 0x14,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x81,0x00,0x05,0x00,0x11,0x00,0x00,0x00, - 0x1c,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x51,0x00,0x05,0x00, - 0x07,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x51,0x00,0x05,0x00,0x07,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1c,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x50,0x00,0x07,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x1a,0x00,0x00,0x00, - 0x41,0x00,0x05,0x00,0x21,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x0e,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x22,0x00,0x00,0x00,0x20,0x00,0x00,0x00, - 0x08,0x00,0x04,0x00,0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x25,0x00,0x00,0x00, - 0x3e,0x00,0x03,0x00,0x24,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x08,0x00,0x04,0x00, - 0x01,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x08,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x3e,0x00,0x03,0x00, - 0x27,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00, +static const char _sdtx_vs_source_wgsl[922] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70, + 0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65, + 0x3e,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20,0x3a,0x20,0x76,0x65, + 0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74, + 0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66, + 0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a, + 0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x67,0x6c, + 0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63,0x34, + 0x66,0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20, + 0x7b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x31,0x39,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f, + 0x31,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x37,0x20,0x3a,0x20, + 0x76,0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x28,0x28,0x78,0x5f,0x31,0x39,0x20,0x2a, + 0x20,0x76,0x65,0x63,0x32,0x66,0x28,0x32,0x2e,0x30,0x66,0x2c,0x20,0x2d,0x32,0x2e, + 0x30,0x66,0x29,0x29,0x20,0x2b,0x20,0x76,0x65,0x63,0x32,0x66,0x28,0x2d,0x31,0x2e, + 0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x29,0x3b,0x0a,0x20,0x20,0x67,0x6c, + 0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,0x34, + 0x66,0x28,0x78,0x5f,0x32,0x37,0x2e,0x78,0x2c,0x20,0x78,0x5f,0x32,0x37,0x2e,0x79, + 0x2c,0x20,0x30,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x3b,0x0a,0x20, + 0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x37,0x20,0x3a,0x20,0x76,0x65,0x63,0x32, + 0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,0x20, + 0x20,0x75,0x76,0x20,0x3d,0x20,0x78,0x5f,0x33,0x37,0x3b,0x0a,0x20,0x20,0x6c,0x65, + 0x74,0x20,0x78,0x5f,0x34,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d, + 0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72, + 0x20,0x3d,0x20,0x78,0x5f,0x34,0x31,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72, + 0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69, + 0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x40,0x62,0x75,0x69,0x6c,0x74, + 0x69,0x6e,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x29,0x0a,0x20,0x20,0x67, + 0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x34,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28, + 0x30,0x29,0x0a,0x20,0x20,0x75,0x76,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x32, + 0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31, + 0x29,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65, + 0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x76,0x65,0x72,0x74,0x65,0x78,0x0a, + 0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f, + 0x6e,0x28,0x30,0x29,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x5f, + 0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20,0x40, + 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x74,0x65,0x78,0x63, + 0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65, + 0x63,0x32,0x66,0x2c,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x32, + 0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a, + 0x20,0x76,0x65,0x63,0x34,0x66,0x29,0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f, + 0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e, + 0x5f,0x31,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x5f, + 0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72, + 0x64,0x30,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70, + 0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3d, + 0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20, + 0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74, + 0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x28,0x67,0x6c,0x5f, + 0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x75,0x76,0x2c,0x20,0x63,0x6f, + 0x6c,0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; -static const uint8_t _sdtx_fs_bytecode_wgpu[940] = { - 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x08,0x00,0x08,0x00,0x1a,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00, - 0x02,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x08,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x17,0x00,0x00,0x00, - 0x10,0x00,0x03,0x00,0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x03,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x37,0x00,0x02,0x00,0x00,0x00, - 0xc2,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64, - 0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69, - 0x65,0x6e,0x74,0x20,0x76,0x75,0x6c,0x6b,0x61,0x6e,0x31,0x30,0x30,0x0a,0x2f,0x2f, - 0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73, - 0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c, - 0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50, - 0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d, - 0x65,0x6e,0x76,0x20,0x76,0x75,0x6c,0x6b,0x61,0x6e,0x31,0x2e,0x30,0x0a,0x2f,0x2f, - 0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73, - 0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d,0x65,0x6e,0x76,0x20,0x6f,0x70, - 0x65,0x6e,0x67,0x6c,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65, - 0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x65,0x6e,0x74,0x72,0x79,0x2d, - 0x70,0x6f,0x69,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x0a,0x23,0x6c,0x69,0x6e,0x65, - 0x20,0x31,0x0a,0x00,0x05,0x00,0x04,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x0a,0x00,0x00,0x00,0x66,0x72,0x61,0x67, - 0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x05,0x00,0x03,0x00,0x0e,0x00,0x00,0x00, - 0x74,0x65,0x78,0x00,0x05,0x00,0x03,0x00,0x12,0x00,0x00,0x00,0x75,0x76,0x00,0x00, - 0x05,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x13,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x21,0x00,0x03,0x00,0x04,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x07,0x00,0x00,0x00,0x20,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x19,0x00,0x09,0x00,0x0b,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x1b,0x00,0x03,0x00,0x0c,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x36,0x00,0x05,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x06,0x00,0x00,0x00,0x08,0x00,0x04,0x00, - 0x01,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x0c,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x10,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x05,0x00, - 0x08,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x13,0x00,0x00,0x00, - 0x4f,0x00,0x09,0x00,0x08,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x14,0x00,0x00,0x00, - 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00, - 0x17,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x08,0x00,0x00,0x00,0x19,0x00,0x00,0x00, - 0x15,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x0a,0x00,0x00,0x00, - 0x19,0x00,0x00,0x00,0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00, +static const char _sdtx_fs_source_wgsl[663] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75, + 0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x33,0x32, + 0x29,0x20,0x76,0x61,0x72,0x20,0x74,0x65,0x78,0x20,0x3a,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x5f,0x32,0x64,0x3c,0x66,0x33,0x32,0x3e,0x3b,0x0a,0x0a,0x40,0x67, + 0x72,0x6f,0x75,0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, + 0x28,0x34,0x38,0x29,0x20,0x76,0x61,0x72,0x20,0x73,0x6d,0x70,0x20,0x3a,0x20,0x73, + 0x61,0x6d,0x70,0x6c,0x65,0x72,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66, + 0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a, + 0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20, + 0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x33,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66, + 0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32, + 0x34,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x53,0x61,0x6d,0x70,0x6c,0x65,0x28,0x74,0x65,0x78,0x2c,0x20,0x73, + 0x6d,0x70,0x2c,0x20,0x78,0x5f,0x32,0x33,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74, + 0x20,0x78,0x5f,0x32,0x38,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f, + 0x6c,0x6f,0x72,0x20,0x3d,0x20,0x28,0x76,0x65,0x63,0x34,0x66,0x28,0x78,0x5f,0x32, + 0x34,0x2e,0x78,0x2c,0x20,0x78,0x5f,0x32,0x34,0x2e,0x78,0x2c,0x20,0x78,0x5f,0x32, + 0x34,0x2e,0x78,0x2c,0x20,0x78,0x5f,0x32,0x34,0x2e,0x78,0x29,0x20,0x2a,0x20,0x78, + 0x5f,0x32,0x38,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a, + 0x7d,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f, + 0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e, + 0x28,0x30,0x29,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72, + 0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40, + 0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e, + 0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x75,0x76, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20, + 0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x63,0x6f,0x6c, + 0x6f,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66, + 0x29,0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a, + 0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b, + 0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31, + 0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69, + 0x6e,0x5f,0x6f,0x75,0x74,0x28,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72, + 0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; #elif defined(SOKOL_DUMMY_BACKEND) static const char* _sdtx_vs_src_dummy = ""; @@ -4039,8 +3977,8 @@ static void _sdtx_setup_common(void) { shd_desc.vs.bytecode = SG_RANGE(_sdtx_vs_bytecode_hlsl4); shd_desc.fs.bytecode = SG_RANGE(_sdtx_fs_bytecode_hlsl4); #elif defined(SOKOL_WGPU) - shd_desc.vs.bytecode = SG_RANGE(_sdtx_vs_bytecode_wgpu); - shd_desc.fs.bytecode = SG_RANGE(_sdtx_fs_bytecode_wgpu); + shd_desc.vs.source = _sdtx_vs_source_wgsl; + shd_desc.fs.source = _sdtx_fs_source_wgsl; #else shd_desc.vs.source = _sdtx_vs_src_dummy; shd_desc.fs.source = _sdtx_fs_src_dummy; From 9d18ccc58ec2c5f389b946dc567fc96742cf6201 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 2 Sep 2023 18:27:39 +0200 Subject: [PATCH 32/95] sokol_gfx.h wgpu: fix 3d texture view arrayLayerCount --- sokol_gfx.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 31fe1bffb..2ee46b9d9 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12680,7 +12680,12 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s wgpu_texview_desc.label = desc->label; wgpu_texview_desc.dimension = _sg_wgpu_texture_view_dimension(img->cmn.type); wgpu_texview_desc.mipLevelCount = (uint32_t)img->cmn.num_mipmaps; - wgpu_texview_desc.arrayLayerCount = (uint32_t)img->cmn.num_slices; + // FIXME: cubemap?? + if (img->cmn.type == SG_IMAGETYPE_ARRAY) { + wgpu_texview_desc.arrayLayerCount = (uint32_t)img->cmn.num_slices; + } else { + wgpu_texview_desc.arrayLayerCount = 1; + } // FIXME: should aspect be DepthOnly for all depth texture formats? wgpu_texview_desc.aspect = WGPUTextureAspect_All; img->wgpu.view = wgpuTextureCreateView(img->wgpu.tex, &wgpu_texview_desc); From 08e258a9c00f0496802adbe30d830e8835745fa4 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 2 Sep 2023 18:56:31 +0200 Subject: [PATCH 33/95] sokol_app.h, sokol_gfx.h wgpu: support bc and etc2 compressed texture formats --- sokol_app.h | 13 +++++++++++-- sokol_gfx.h | 33 ++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/sokol_app.h b/sokol_app.h index 1a13ba7b8..7055653b0 100644 --- a/sokol_app.h +++ b/sokol_app.h @@ -5743,12 +5743,21 @@ _SOKOL_PRIVATE void _sapp_emsc_wgpu_request_adapter_cb(WGPURequestAdapterStatus } SOKOL_ASSERT(adapter); _sapp.wgpu.adapter = adapter; - const WGPUFeatureName requiredFeatures[1] = { + size_t cur_feature_index = 1; + WGPUFeatureName requiredFeatures[8] = { WGPUFeatureName_Depth32FloatStencil8, }; + // check for optional features we're interested in + // FIXME: ASTC texture compression + if (wgpuAdapterHasFeature(adapter, WGPUFeatureName_TextureCompressionBC)) { + requiredFeatures[cur_feature_index++] = WGPUFeatureName_TextureCompressionBC; + } else if (wgpuAdapterHasFeature(adapter, WGPUFeatureName_TextureCompressionETC2)) { + requiredFeatures[cur_feature_index++] = WGPUFeatureName_TextureCompressionETC2; + } + WGPUDeviceDescriptor dev_desc; _sapp_clear(&dev_desc, sizeof(dev_desc)); - dev_desc.requiredFeaturesCount = 1, + dev_desc.requiredFeaturesCount = cur_feature_index; dev_desc.requiredFeatures = requiredFeatures, wgpuAdapterRequestDevice(adapter, &dev_desc, _sapp_emsc_wgpu_request_device_cb, 0); } diff --git a/sokol_gfx.h b/sokol_gfx.h index 2ee46b9d9..dde49065c 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12341,6 +12341,7 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R8SN]); _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8UI]); _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8SI]); + // NOTE: no WGPUTextureFormat_R16Unorm _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16UI]); _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16SI]); _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16F]); @@ -12373,19 +12374,25 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH]); _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH_STENCIL]); - /* FIXME FIXME FIXME: need to check if BC texture compression is - actually supported, currently the WebGPU C-API doesn't allow this - */ - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC1_RGBA]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC2_RGBA]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC3_RGBA]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_R]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_RSN]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RG]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RGSN]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBF]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBUF]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_RGBA]); + if (wgpuDeviceHasFeature(_sg.wgpu.dev, WGPUFeatureName_TextureCompressionBC)) { + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC1_RGBA]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC2_RGBA]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC3_RGBA]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_R]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC4_RSN]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RG]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC5_RGSN]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBF]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC6H_RGBUF]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_BC7_RGBA]); + } + if (wgpuDeviceHasFeature(_sg.wgpu.dev, WGPUFeatureName_TextureCompressionETC2)) { + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGB8A1]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RGBA8]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RG11]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_ETC2_RG11SN]); + } } _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_init(const sg_desc* desc) { From 7008ca1f3110305de7f00157078927433bb44a0a Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 2 Sep 2023 19:02:33 +0200 Subject: [PATCH 34/95] sokol_gfx.h wgpu: in _sg_wgpu_copy_image_data() round up mip width/height to multiple of 4 for compressed formats --- sokol_gfx.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index dde49065c..98d713b3f 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12625,8 +12625,8 @@ _SOKOL_PRIVATE void _sg_wgpu_copy_image_data(const _sg_image_t* img, WGPUTexture _sg_clear(&wgpu_extent, sizeof(wgpu_extent)); for (int mip_level = 0; mip_level < img->cmn.num_mipmaps; mip_level++) { wgpu_copy_tex.mipLevel = (uint32_t)mip_level; - const int mip_width = _sg_miplevel_dim(img->cmn.width, mip_level); - const int mip_height = _sg_miplevel_dim(img->cmn.height, mip_level); + int mip_width = _sg_miplevel_dim(img->cmn.width, mip_level); + int mip_height = _sg_miplevel_dim(img->cmn.height, mip_level); int mip_slices; switch (img->cmn.type) { case SG_IMAGETYPE_CUBE: @@ -12641,6 +12641,10 @@ _SOKOL_PRIVATE void _sg_wgpu_copy_image_data(const _sg_image_t* img, WGPUTexture } const int row_pitch = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1); const int num_rows = _sg_num_rows(img->cmn.pixel_format, mip_height); + if (_sg_is_compressed_pixel_format(img->cmn.pixel_format)) { + mip_width = _sg_roundup(mip_width, 4); + mip_height = _sg_roundup(mip_height, 4); + } wgpu_layout.offset = 0; wgpu_layout.bytesPerRow = (uint32_t)row_pitch; wgpu_layout.rowsPerImage = (uint32_t)num_rows; From 465a795ee9be1c90d082038cd07c733304f27703 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 2 Sep 2023 19:21:08 +0200 Subject: [PATCH 35/95] sokol_gl.h: fix embedded wgsl shader --- util/sokol_gl.h | 306 +++++++++++++++++++----------------------------- 1 file changed, 120 insertions(+), 186 deletions(-) diff --git a/util/sokol_gl.h b/util/sokol_gl.h index 7fe1d936f..32cc07f58 100644 --- a/util/sokol_gl.h +++ b/util/sokol_gl.h @@ -991,7 +991,9 @@ inline sgl_pipeline sgl_context_make_pipeline(sgl_context ctx, const sg_pipeline out vec4 color; void main() { gl_Position = mvp * position; + #ifndef SOKOL_WGSL gl_PointSize = psize; + #endif uv = tm * vec4(texcoord0, 0.0, 1.0); color = color0; } @@ -2078,191 +2080,123 @@ static const uint8_t _sgl_fs_bytecode_hlsl4[608] = { }; #elif defined(SOKOL_WGPU) -static const uint8_t _sgl_vs_bytecode_wgpu[1968] = { - 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x08,0x00,0x08,0x00,0x35,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00, - 0x02,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x21,0x00,0x00,0x00, - 0x25,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x33,0x00,0x00,0x00, - 0x07,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x05,0x00, - 0x07,0x00,0x00,0x00,0x73,0x67,0x6c,0x2e,0x67,0x6c,0x73,0x6c,0x00,0x00,0x00,0x00, - 0x03,0x00,0x37,0x00,0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65, - 0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x76,0x75,0x6c,0x6b, - 0x61,0x6e,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c, - 0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e, - 0x74,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f, - 0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64, - 0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d,0x65,0x6e,0x76,0x20,0x76,0x75,0x6c,0x6b, - 0x61,0x6e,0x31,0x2e,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c, - 0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65, - 0x74,0x2d,0x65,0x6e,0x76,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x0a,0x2f,0x2f,0x20, - 0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65, - 0x64,0x20,0x65,0x6e,0x74,0x72,0x79,0x2d,0x70,0x6f,0x69,0x6e,0x74,0x20,0x6d,0x61, - 0x69,0x6e,0x0a,0x23,0x6c,0x69,0x6e,0x65,0x20,0x31,0x0a,0x00,0x05,0x00,0x04,0x00, - 0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00, - 0x0d,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x65,0x72,0x56,0x65,0x72,0x74,0x65,0x78, - 0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x06,0x00,0x07,0x00, - 0x0d,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74, - 0x53,0x69,0x7a,0x65,0x00,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x0d,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x67,0x6c,0x5f,0x43,0x6c,0x69,0x70,0x44,0x69,0x73,0x74,0x61, - 0x6e,0x63,0x65,0x00,0x06,0x00,0x07,0x00,0x0d,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x43,0x75,0x6c,0x6c,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,0x00, - 0x05,0x00,0x03,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00, - 0x13,0x00,0x00,0x00,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x00,0x00,0x00, - 0x06,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x76,0x70,0x00, - 0x06,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x74,0x6d,0x00,0x00, - 0x05,0x00,0x03,0x00,0x15,0x00,0x00,0x00,0x5f,0x32,0x31,0x00,0x05,0x00,0x05,0x00, - 0x1a,0x00,0x00,0x00,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00, - 0x05,0x00,0x04,0x00,0x21,0x00,0x00,0x00,0x70,0x73,0x69,0x7a,0x65,0x00,0x00,0x00, - 0x05,0x00,0x03,0x00,0x25,0x00,0x00,0x00,0x75,0x76,0x00,0x00,0x05,0x00,0x05,0x00, - 0x2a,0x00,0x00,0x00,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x00,0x00,0x00, - 0x05,0x00,0x04,0x00,0x32,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00, - 0x05,0x00,0x04,0x00,0x33,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x00,0x00, - 0x48,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0d,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x48,0x00,0x05,0x00, - 0x0d,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0x47,0x00,0x03,0x00,0x0d,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x48,0x00,0x04,0x00, - 0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x48,0x00,0x05,0x00, - 0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x48,0x00,0x05,0x00,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x48,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x05,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x13,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x23,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x13,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x47,0x00,0x03,0x00, - 0x13,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x15,0x00,0x00,0x00, - 0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x15,0x00,0x00,0x00, - 0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x1a,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x21,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x25,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x2a,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x32,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x33,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x13,0x00,0x02,0x00,0x03,0x00,0x00,0x00, - 0x21,0x00,0x03,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x00,0x03,0x00, - 0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x09,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x0a,0x00,0x00,0x00, - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x0a,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x04,0x00,0x0c,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x1e,0x00,0x06,0x00,0x0d,0x00,0x00,0x00, - 0x09,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0d,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x15,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x18,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0x1e,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x12,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x14,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x13,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x14,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x12,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x19,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x09,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x19,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x1d,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x09,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x23,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x1d,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x28,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x29,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x29,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x00,0x00,0x80,0x3f, - 0x3b,0x00,0x04,0x00,0x1d,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x19,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x36,0x00,0x05,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x06,0x00,0x00,0x00,0x08,0x00,0x04,0x00, - 0x07,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x05,0x00, - 0x16,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x11,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x17,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x1a,0x00,0x00,0x00, - 0x91,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x18,0x00,0x00,0x00, - 0x1b,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x1d,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0x0f,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x1e,0x00,0x00,0x00, - 0x1c,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x13,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x22,0x00,0x00,0x00, - 0x21,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x23,0x00,0x00,0x00,0x24,0x00,0x00,0x00, - 0x0f,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x24,0x00,0x00,0x00, - 0x22,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x14,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x16,0x00,0x00,0x00,0x26,0x00,0x00,0x00, - 0x15,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x12,0x00,0x00,0x00, - 0x27,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x28,0x00,0x00,0x00, - 0x2b,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x08,0x00,0x00,0x00, - 0x2e,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x05,0x00, - 0x08,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x50,0x00,0x07,0x00,0x09,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x2e,0x00,0x00,0x00, - 0x2f,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x91,0x00,0x05,0x00, - 0x09,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x30,0x00,0x00,0x00, - 0x3e,0x00,0x03,0x00,0x25,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x08,0x00,0x04,0x00, - 0x07,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x09,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x3e,0x00,0x03,0x00, - 0x32,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00, +static const char _sgl_vs_source_wgsl[1162] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20, + 0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x20,0x7b,0x0a,0x20,0x20,0x2f,0x2a, + 0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x30,0x29,0x20,0x2a,0x2f,0x0a,0x20, + 0x20,0x6d,0x76,0x70,0x20,0x3a,0x20,0x6d,0x61,0x74,0x34,0x78,0x34,0x66,0x2c,0x0a, + 0x20,0x20,0x2f,0x2a,0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x36,0x34,0x29, + 0x20,0x2a,0x2f,0x0a,0x20,0x20,0x74,0x6d,0x20,0x3a,0x20,0x6d,0x61,0x74,0x34,0x78, + 0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,0x70,0x28,0x30,0x29, + 0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x30,0x29,0x20,0x76,0x61,0x72, + 0x3c,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x3e,0x20,0x78,0x5f,0x31,0x39,0x20,0x3a, + 0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x3b,0x0a,0x0a,0x76,0x61,0x72, + 0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x70,0x6f,0x73,0x69,0x74,0x69, + 0x6f,0x6e,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76, + 0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a, + 0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20, + 0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72, + 0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61, + 0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65, + 0x3e,0x20,0x70,0x73,0x69,0x7a,0x65,0x20,0x3a,0x20,0x66,0x33,0x32,0x3b,0x0a,0x0a, + 0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x67,0x6c,0x5f, + 0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66, + 0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b, + 0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x32,0x20,0x3a,0x20,0x6d,0x61, + 0x74,0x34,0x78,0x34,0x66,0x20,0x3d,0x20,0x78,0x5f,0x31,0x39,0x2e,0x6d,0x76,0x70, + 0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x35,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f, + 0x31,0x3b,0x0a,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e, + 0x20,0x3d,0x20,0x28,0x78,0x5f,0x32,0x32,0x20,0x2a,0x20,0x78,0x5f,0x32,0x35,0x29, + 0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x32,0x20,0x3a,0x20,0x6d, + 0x61,0x74,0x34,0x78,0x34,0x66,0x20,0x3d,0x20,0x78,0x5f,0x31,0x39,0x2e,0x74,0x6d, + 0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x36,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30, + 0x3b,0x0a,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x28,0x78,0x5f,0x33,0x32,0x20,0x2a, + 0x20,0x76,0x65,0x63,0x34,0x66,0x28,0x78,0x5f,0x33,0x36,0x2e,0x78,0x2c,0x20,0x78, + 0x5f,0x33,0x36,0x2e,0x79,0x2c,0x20,0x30,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30, + 0x66,0x29,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x34,0x35,0x20, + 0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30, + 0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x78,0x5f,0x34,0x35, + 0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73, + 0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b, + 0x0a,0x20,0x20,0x40,0x62,0x75,0x69,0x6c,0x74,0x69,0x6e,0x28,0x70,0x6f,0x73,0x69, + 0x74,0x69,0x6f,0x6e,0x29,0x0a,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74, + 0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40, + 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x0a,0x20,0x20,0x75,0x76, + 0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c, + 0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x0a,0x20,0x20,0x63,0x6f,0x6c, + 0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a, + 0x0a,0x40,0x76,0x65,0x72,0x74,0x65,0x78,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e, + 0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x70,0x6f, + 0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a, + 0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f, + 0x6e,0x28,0x31,0x29,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70, + 0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20,0x40,0x6c, + 0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x32,0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72, + 0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c, + 0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x33,0x29,0x20,0x70,0x73, + 0x69,0x7a,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x66,0x33,0x32,0x29, + 0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20, + 0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x20,0x3d,0x20,0x70,0x6f, + 0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a, + 0x20,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20,0x3d,0x20,0x74,0x65, + 0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20, + 0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x70,0x73,0x69,0x7a,0x65,0x20, + 0x3d,0x20,0x70,0x73,0x69,0x7a,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20, + 0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74, + 0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x28,0x67,0x6c,0x5f, + 0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x75,0x76,0x2c,0x20,0x63,0x6f, + 0x6c,0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; -static const uint8_t _sgl_fs_bytecode_wgpu[936] = { - 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x08,0x00,0x08,0x00,0x1a,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00, - 0x02,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x08,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x17,0x00,0x00,0x00, - 0x10,0x00,0x03,0x00,0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x03,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x05,0x00,0x07,0x00,0x00,0x00, - 0x73,0x67,0x6c,0x2e,0x67,0x6c,0x73,0x6c,0x00,0x00,0x00,0x00,0x03,0x00,0x37,0x00, - 0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2f,0x2f,0x20,0x4f, - 0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64, - 0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x76,0x75,0x6c,0x6b,0x61,0x6e,0x31,0x30, - 0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f, - 0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x6f,0x70, - 0x65,0x6e,0x67,0x6c,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64, - 0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72, - 0x67,0x65,0x74,0x2d,0x65,0x6e,0x76,0x20,0x76,0x75,0x6c,0x6b,0x61,0x6e,0x31,0x2e, - 0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f, - 0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d,0x65,0x6e, - 0x76,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f, - 0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x65,0x6e, - 0x74,0x72,0x79,0x2d,0x70,0x6f,0x69,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x0a,0x23, - 0x6c,0x69,0x6e,0x65,0x20,0x31,0x0a,0x00,0x05,0x00,0x04,0x00,0x05,0x00,0x00,0x00, - 0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x0b,0x00,0x00,0x00, - 0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x05,0x00,0x03,0x00, - 0x0f,0x00,0x00,0x00,0x74,0x65,0x78,0x00,0x05,0x00,0x03,0x00,0x12,0x00,0x00,0x00, - 0x75,0x76,0x00,0x00,0x05,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f, - 0x72,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x0b,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x0f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x0f,0x00,0x00,0x00,0x22,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x0f,0x00,0x00,0x00,0x21,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x13,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x21,0x00,0x03,0x00, - 0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x08,0x00,0x00,0x00, - 0x20,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x09,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x19,0x00,0x09,0x00,0x0c,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x03,0x00,0x0d,0x00,0x00,0x00, - 0x0c,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0d,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x09,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x12,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x17,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x36,0x00,0x05,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x06,0x00,0x00,0x00, - 0x08,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x12,0x00,0x00,0x00, - 0x4f,0x00,0x07,0x00,0x13,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x14,0x00,0x00,0x00, - 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x05,0x00, - 0x09,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x15,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x17,0x00,0x00,0x00, - 0x85,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x16,0x00,0x00,0x00, - 0x18,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x0b,0x00,0x00,0x00,0x19,0x00,0x00,0x00, - 0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00, +static const char _sgl_fs_source_wgsl[647] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75, + 0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x33,0x32, + 0x29,0x20,0x76,0x61,0x72,0x20,0x74,0x65,0x78,0x20,0x3a,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x5f,0x32,0x64,0x3c,0x66,0x33,0x32,0x3e,0x3b,0x0a,0x0a,0x40,0x67, + 0x72,0x6f,0x75,0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, + 0x28,0x34,0x38,0x29,0x20,0x76,0x61,0x72,0x20,0x73,0x6d,0x70,0x20,0x3a,0x20,0x73, + 0x61,0x6d,0x70,0x6c,0x65,0x72,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66, + 0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a, + 0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20, + 0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x33,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66, + 0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32, + 0x35,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x53,0x61,0x6d,0x70,0x6c,0x65,0x28,0x74,0x65,0x78,0x2c,0x20,0x73, + 0x6d,0x70,0x2c,0x20,0x76,0x65,0x63,0x32,0x66,0x28,0x78,0x5f,0x32,0x33,0x2e,0x78, + 0x2c,0x20,0x78,0x5f,0x32,0x33,0x2e,0x79,0x29,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65, + 0x74,0x20,0x78,0x5f,0x32,0x37,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d, + 0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63, + 0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x28,0x78,0x5f,0x32,0x35,0x20,0x2a,0x20,0x78, + 0x5f,0x32,0x37,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a, + 0x7d,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f, + 0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e, + 0x28,0x30,0x29,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72, + 0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40, + 0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e, + 0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x75,0x76, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x20, + 0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x63,0x6f,0x6c, + 0x6f,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66, + 0x29,0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a, + 0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b, + 0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31, + 0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69, + 0x6e,0x5f,0x6f,0x75,0x74,0x28,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72, + 0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; #elif defined(SOKOL_DUMMY_BACKEND) static const char* _sgl_vs_source_dummy = ""; @@ -3377,8 +3311,8 @@ static void _sgl_setup_common(void) { shd_desc.vs.bytecode = SG_RANGE(_sgl_vs_bytecode_hlsl4); shd_desc.fs.bytecode = SG_RANGE(_sgl_fs_bytecode_hlsl4); #elif defined(SOKOL_WGPU) - shd_desc.vs.bytecode = SG_RANGE(_sgl_vs_bytecode_wgpu); - shd_desc.fs.bytecode = SG_RANGE(_sgl_fs_bytecode_wgpu); + shd_desc.vs.source = _sgl_vs_source_wgsl; + shd_desc.fs.source = _sgl_fs_source_wgsl; #else shd_desc.vs.source = _sgl_vs_source_dummy; shd_desc.fs.source = _sgl_fs_source_dummy; From c703eceac9d8e28e9bc41896dae6d872ecc16536 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 3 Sep 2023 12:48:38 +0200 Subject: [PATCH 36/95] sokol_fontstash.h wgpu: fix embedded shader --- util/sokol_fontstash.h | 314 ++++++++++++++++------------------------- 1 file changed, 122 insertions(+), 192 deletions(-) diff --git a/util/sokol_fontstash.h b/util/sokol_fontstash.h index 46950e45c..c6e9b5f6f 100644 --- a/util/sokol_fontstash.h +++ b/util/sokol_fontstash.h @@ -300,7 +300,9 @@ SOKOL_FONTSTASH_API_DECL uint32_t sfons_rgba(uint8_t r, uint8_t g, uint8_t b, ui out vec4 color; void main() { gl_Position = mvp * position; + #ifndef SOKOL_WGSL gl_PointSize = psize; + #endif uv = tm * vec4(texcoord0, 0.0, 1.0); color = color0; } @@ -1395,195 +1397,125 @@ static const uint8_t _sfons_fs_bytecode_hlsl4[628] = { 0x00,0x00,0x00,0x00, }; #elif defined(SOKOL_WGPU) -static const uint8_t _sfons_vs_bytecode_wgpu[1968] = { - 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x08,0x00,0x08,0x00,0x35,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00, - 0x02,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x21,0x00,0x00,0x00, - 0x25,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x33,0x00,0x00,0x00, - 0x07,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x05,0x00, - 0x07,0x00,0x00,0x00,0x73,0x66,0x6f,0x6e,0x73,0x2e,0x67,0x6c,0x73,0x6c,0x00,0x00, - 0x03,0x00,0x37,0x00,0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65, - 0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x76,0x75,0x6c,0x6b, - 0x61,0x6e,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c, - 0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e, - 0x74,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f, - 0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64, - 0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d,0x65,0x6e,0x76,0x20,0x76,0x75,0x6c,0x6b, - 0x61,0x6e,0x31,0x2e,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c, - 0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65, - 0x74,0x2d,0x65,0x6e,0x76,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x0a,0x2f,0x2f,0x20, - 0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65, - 0x64,0x20,0x65,0x6e,0x74,0x72,0x79,0x2d,0x70,0x6f,0x69,0x6e,0x74,0x20,0x6d,0x61, - 0x69,0x6e,0x0a,0x23,0x6c,0x69,0x6e,0x65,0x20,0x31,0x0a,0x00,0x05,0x00,0x04,0x00, - 0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00, - 0x0d,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x65,0x72,0x56,0x65,0x72,0x74,0x65,0x78, - 0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x06,0x00,0x07,0x00, - 0x0d,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74, - 0x53,0x69,0x7a,0x65,0x00,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x0d,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x67,0x6c,0x5f,0x43,0x6c,0x69,0x70,0x44,0x69,0x73,0x74,0x61, - 0x6e,0x63,0x65,0x00,0x06,0x00,0x07,0x00,0x0d,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x43,0x75,0x6c,0x6c,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,0x00, - 0x05,0x00,0x03,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00, - 0x13,0x00,0x00,0x00,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x00,0x00,0x00, - 0x06,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x76,0x70,0x00, - 0x06,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x74,0x6d,0x00,0x00, - 0x05,0x00,0x03,0x00,0x15,0x00,0x00,0x00,0x5f,0x32,0x31,0x00,0x05,0x00,0x05,0x00, - 0x1a,0x00,0x00,0x00,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00, - 0x05,0x00,0x04,0x00,0x21,0x00,0x00,0x00,0x70,0x73,0x69,0x7a,0x65,0x00,0x00,0x00, - 0x05,0x00,0x03,0x00,0x25,0x00,0x00,0x00,0x75,0x76,0x00,0x00,0x05,0x00,0x05,0x00, - 0x2a,0x00,0x00,0x00,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x00,0x00,0x00, - 0x05,0x00,0x04,0x00,0x32,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00, - 0x05,0x00,0x04,0x00,0x33,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x00,0x00, - 0x48,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0d,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x48,0x00,0x05,0x00, - 0x0d,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0x47,0x00,0x03,0x00,0x0d,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x48,0x00,0x04,0x00, - 0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x48,0x00,0x05,0x00, - 0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x48,0x00,0x05,0x00,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x48,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x05,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x13,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x23,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x13,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x47,0x00,0x03,0x00, - 0x13,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x15,0x00,0x00,0x00, - 0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x15,0x00,0x00,0x00, - 0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x1a,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x21,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x25,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x2a,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x32,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x33,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x13,0x00,0x02,0x00,0x03,0x00,0x00,0x00, - 0x21,0x00,0x03,0x00,0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x00,0x03,0x00, - 0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x09,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x0a,0x00,0x00,0x00, - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x0a,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x04,0x00,0x0c,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x1e,0x00,0x06,0x00,0x0d,0x00,0x00,0x00, - 0x09,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0d,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x15,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x18,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0x1e,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x12,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x14,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x13,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x14,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x12,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x19,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x09,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x19,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x1d,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x09,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x23,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x1d,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x28,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x29,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x28,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x29,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x00,0x00,0x80,0x3f, - 0x3b,0x00,0x04,0x00,0x1d,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x19,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x36,0x00,0x05,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x06,0x00,0x00,0x00,0x08,0x00,0x04,0x00, - 0x07,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x05,0x00, - 0x16,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x11,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x17,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x1a,0x00,0x00,0x00, - 0x91,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x18,0x00,0x00,0x00, - 0x1b,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x1d,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0x0f,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x1e,0x00,0x00,0x00, - 0x1c,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x13,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x22,0x00,0x00,0x00, - 0x21,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x23,0x00,0x00,0x00,0x24,0x00,0x00,0x00, - 0x0f,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x24,0x00,0x00,0x00, - 0x22,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x14,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x16,0x00,0x00,0x00,0x26,0x00,0x00,0x00, - 0x15,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x12,0x00,0x00,0x00, - 0x27,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x28,0x00,0x00,0x00, - 0x2b,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x08,0x00,0x00,0x00, - 0x2e,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x05,0x00, - 0x08,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x50,0x00,0x07,0x00,0x09,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x2e,0x00,0x00,0x00, - 0x2f,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x91,0x00,0x05,0x00, - 0x09,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x30,0x00,0x00,0x00, - 0x3e,0x00,0x03,0x00,0x25,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x08,0x00,0x04,0x00, - 0x07,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x09,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x3e,0x00,0x03,0x00, - 0x32,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00, +static const char _sfons_vs_source_wgsl[1162] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20, + 0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x20,0x7b,0x0a,0x20,0x20,0x2f,0x2a, + 0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x30,0x29,0x20,0x2a,0x2f,0x0a,0x20, + 0x20,0x6d,0x76,0x70,0x20,0x3a,0x20,0x6d,0x61,0x74,0x34,0x78,0x34,0x66,0x2c,0x0a, + 0x20,0x20,0x2f,0x2a,0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x36,0x34,0x29, + 0x20,0x2a,0x2f,0x0a,0x20,0x20,0x74,0x6d,0x20,0x3a,0x20,0x6d,0x61,0x74,0x34,0x78, + 0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,0x70,0x28,0x30,0x29, + 0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x30,0x29,0x20,0x76,0x61,0x72, + 0x3c,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x3e,0x20,0x78,0x5f,0x31,0x39,0x20,0x3a, + 0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x3b,0x0a,0x0a,0x76,0x61,0x72, + 0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x70,0x6f,0x73,0x69,0x74,0x69, + 0x6f,0x6e,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76, + 0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a, + 0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20, + 0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72, + 0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61, + 0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65, + 0x3e,0x20,0x70,0x73,0x69,0x7a,0x65,0x20,0x3a,0x20,0x66,0x33,0x32,0x3b,0x0a,0x0a, + 0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x67,0x6c,0x5f, + 0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66, + 0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b, + 0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x32,0x20,0x3a,0x20,0x6d,0x61, + 0x74,0x34,0x78,0x34,0x66,0x20,0x3d,0x20,0x78,0x5f,0x31,0x39,0x2e,0x6d,0x76,0x70, + 0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x35,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f, + 0x31,0x3b,0x0a,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e, + 0x20,0x3d,0x20,0x28,0x78,0x5f,0x32,0x32,0x20,0x2a,0x20,0x78,0x5f,0x32,0x35,0x29, + 0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x32,0x20,0x3a,0x20,0x6d, + 0x61,0x74,0x34,0x78,0x34,0x66,0x20,0x3d,0x20,0x78,0x5f,0x31,0x39,0x2e,0x74,0x6d, + 0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x36,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30, + 0x3b,0x0a,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x28,0x78,0x5f,0x33,0x32,0x20,0x2a, + 0x20,0x76,0x65,0x63,0x34,0x66,0x28,0x78,0x5f,0x33,0x36,0x2e,0x78,0x2c,0x20,0x78, + 0x5f,0x33,0x36,0x2e,0x79,0x2c,0x20,0x30,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30, + 0x66,0x29,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x34,0x35,0x20, + 0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30, + 0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x78,0x5f,0x34,0x35, + 0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73, + 0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b, + 0x0a,0x20,0x20,0x40,0x62,0x75,0x69,0x6c,0x74,0x69,0x6e,0x28,0x70,0x6f,0x73,0x69, + 0x74,0x69,0x6f,0x6e,0x29,0x0a,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74, + 0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40, + 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x0a,0x20,0x20,0x75,0x76, + 0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c, + 0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x0a,0x20,0x20,0x63,0x6f,0x6c, + 0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a, + 0x0a,0x40,0x76,0x65,0x72,0x74,0x65,0x78,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e, + 0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x70,0x6f, + 0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a, + 0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f, + 0x6e,0x28,0x31,0x29,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70, + 0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20,0x40,0x6c, + 0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x32,0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72, + 0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c, + 0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x33,0x29,0x20,0x70,0x73, + 0x69,0x7a,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x66,0x33,0x32,0x29, + 0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20, + 0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x20,0x3d,0x20,0x70,0x6f, + 0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a, + 0x20,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20,0x3d,0x20,0x74,0x65, + 0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20, + 0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x70,0x73,0x69,0x7a,0x65,0x20, + 0x3d,0x20,0x70,0x73,0x69,0x7a,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20, + 0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74, + 0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x28,0x67,0x6c,0x5f, + 0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x75,0x76,0x2c,0x20,0x63,0x6f, + 0x6c,0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; -static const uint8_t fs_bytecode_wgpu[1000] = { - 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x08,0x00,0x08,0x00,0x1f,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00, - 0x02,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x08,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x1c,0x00,0x00,0x00, - 0x10,0x00,0x03,0x00,0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x03,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x05,0x00,0x07,0x00,0x00,0x00, - 0x73,0x66,0x6f,0x6e,0x73,0x2e,0x67,0x6c,0x73,0x6c,0x00,0x00,0x03,0x00,0x37,0x00, - 0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2f,0x2f,0x20,0x4f, - 0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64, - 0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x76,0x75,0x6c,0x6b,0x61,0x6e,0x31,0x30, - 0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f, - 0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x6f,0x70, - 0x65,0x6e,0x67,0x6c,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64, - 0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72, - 0x67,0x65,0x74,0x2d,0x65,0x6e,0x76,0x20,0x76,0x75,0x6c,0x6b,0x61,0x6e,0x31,0x2e, - 0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f, - 0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d,0x65,0x6e, - 0x76,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f, - 0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x65,0x6e, - 0x74,0x72,0x79,0x2d,0x70,0x6f,0x69,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x0a,0x23, - 0x6c,0x69,0x6e,0x65,0x20,0x31,0x0a,0x00,0x05,0x00,0x04,0x00,0x05,0x00,0x00,0x00, - 0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x0b,0x00,0x00,0x00, - 0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x05,0x00,0x03,0x00, - 0x10,0x00,0x00,0x00,0x74,0x65,0x78,0x00,0x05,0x00,0x03,0x00,0x13,0x00,0x00,0x00, - 0x75,0x76,0x00,0x00,0x05,0x00,0x04,0x00,0x1c,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f, - 0x72,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x0b,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x22,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x21,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x47,0x00,0x04,0x00,0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x13,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x21,0x00,0x03,0x00, - 0x04,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x08,0x00,0x00,0x00, - 0x20,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x09,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x00,0x00,0x80,0x3f,0x19,0x00,0x09,0x00,0x0d,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x03,0x00,0x0e,0x00,0x00,0x00, - 0x0d,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0e,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0f,0x00,0x00,0x00,0x10,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x09,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x13,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x14,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x1c,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x36,0x00,0x05,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x06,0x00,0x00,0x00, - 0x08,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x10,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0x13,0x00,0x00,0x00, - 0x4f,0x00,0x07,0x00,0x14,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x15,0x00,0x00,0x00, - 0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x57,0x00,0x05,0x00, - 0x09,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x16,0x00,0x00,0x00, - 0x51,0x00,0x05,0x00,0x08,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x17,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x50,0x00,0x07,0x00,0x09,0x00,0x00,0x00,0x1b,0x00,0x00,0x00, - 0x0c,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x1a,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x1d,0x00,0x00,0x00,0x1c,0x00,0x00,0x00, - 0x85,0x00,0x05,0x00,0x09,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1b,0x00,0x00,0x00, - 0x1d,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x0b,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, - 0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00, +static const char _sfons_fs_source_wgsl[674] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75, + 0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x33,0x32, + 0x29,0x20,0x76,0x61,0x72,0x20,0x74,0x65,0x78,0x20,0x3a,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x5f,0x32,0x64,0x3c,0x66,0x33,0x32,0x3e,0x3b,0x0a,0x0a,0x40,0x67, + 0x72,0x6f,0x75,0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, + 0x28,0x34,0x38,0x29,0x20,0x76,0x61,0x72,0x20,0x73,0x6d,0x70,0x20,0x3a,0x20,0x73, + 0x61,0x6d,0x70,0x6c,0x65,0x72,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66, + 0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a, + 0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20, + 0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x34,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66, + 0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32, + 0x36,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x53,0x61,0x6d,0x70,0x6c,0x65,0x28,0x74,0x65,0x78,0x2c,0x20,0x73, + 0x6d,0x70,0x2c,0x20,0x76,0x65,0x63,0x32,0x66,0x28,0x78,0x5f,0x32,0x34,0x2e,0x78, + 0x2c,0x20,0x78,0x5f,0x32,0x34,0x2e,0x79,0x29,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65, + 0x74,0x20,0x78,0x5f,0x33,0x32,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d, + 0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63, + 0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x28,0x76,0x65,0x63,0x34,0x66,0x28,0x31,0x2e, + 0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x2c,0x20, + 0x78,0x5f,0x32,0x36,0x2e,0x78,0x29,0x20,0x2a,0x20,0x78,0x5f,0x33,0x32,0x29,0x3b, + 0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74, + 0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a, + 0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x0a,0x20, + 0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20, + 0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x66,0x72,0x61,0x67,0x6d, + 0x65,0x6e,0x74,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28,0x40,0x6c,0x6f,0x63, + 0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61, + 0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x20,0x40,0x6c,0x6f,0x63,0x61, + 0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x70,0x61, + 0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x29,0x20,0x2d,0x3e,0x20, + 0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x75,0x76,0x20, + 0x3d,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x63,0x6f, + 0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x70,0x61,0x72,0x61, + 0x6d,0x3b,0x0a,0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20, + 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74, + 0x28,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a, + 0x0a,0x00, }; #elif defined(SOKOL_DUMMY_BACKEND) static const char* _sfons_vs_source_dummy = ""; @@ -1696,10 +1628,8 @@ static int _sfons_render_create(void* user_ptr, int width, int height) { shd_desc.vs.bytecode = SG_RANGE(_sfons_vs_bytecode_hlsl4); shd_desc.fs.bytecode = SG_RANGE(_sfons_fs_bytecode_hlsl4); #elif defined(SOKOL_WGPU) - shd_desc.vs.byte_code = _sfons_vs_bytecode_wgpu; - shd_desc.vs.byte_code_size = sizeof(_sfons_vs_bytecode_wgpu); - shd_desc.fs.byte_code = _sfons_fs_bytecode_wgpu; - shd_desc.fs.byte_code_size = sizeof(_sfons_fs_bytecode_wgpu); + shd_desc.vs.source = _sfons_vs_source_wgsl; + shd_desc.fs.source = _sfons_fs_source_wgsl; #else shd_desc.vs.source = _sfons_vs_source_dummy; shd_desc.fs.source = _sfons_fs_source_dummy; From 561eec0271e9e11ba64f4dd4e692bf4a2a6e9eb7 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 3 Sep 2023 13:09:29 +0200 Subject: [PATCH 37/95] sokol_imgui.h wgpu: fix embedded shader --- util/sokol_imgui.h | 290 +++++++++++++++++---------------------------- 1 file changed, 112 insertions(+), 178 deletions(-) diff --git a/util/sokol_imgui.h b/util/sokol_imgui.h index e8abe7d81..51ad4eb52 100644 --- a/util/sokol_imgui.h +++ b/util/sokol_imgui.h @@ -1704,183 +1704,117 @@ static const uint8_t _simgui_fs_bytecode_hlsl4[608] = { }; #elif defined(SOKOL_WGPU) -static const uint8_t _simgui_vs_bytecode_wgpu[1868] = { - 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x08,0x00,0x08,0x00,0x34,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00, - 0x02,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x2a,0x00,0x00,0x00, - 0x2b,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x32,0x00,0x00,0x00, - 0x33,0x00,0x00,0x00,0x07,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x37,0x00,0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65, - 0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x76,0x75,0x6c,0x6b, - 0x61,0x6e,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c, - 0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e, - 0x74,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f, - 0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64, - 0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d,0x65,0x6e,0x76,0x20,0x76,0x75,0x6c,0x6b, - 0x61,0x6e,0x31,0x2e,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c, - 0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65, - 0x74,0x2d,0x65,0x6e,0x76,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x0a,0x2f,0x2f,0x20, - 0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65, - 0x64,0x20,0x65,0x6e,0x74,0x72,0x79,0x2d,0x70,0x6f,0x69,0x6e,0x74,0x20,0x6d,0x61, - 0x69,0x6e,0x0a,0x23,0x6c,0x69,0x6e,0x65,0x20,0x31,0x0a,0x00,0x05,0x00,0x04,0x00, - 0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00, - 0x0c,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x65,0x72,0x56,0x65,0x72,0x74,0x65,0x78, - 0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x06,0x00,0x07,0x00, - 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74, - 0x53,0x69,0x7a,0x65,0x00,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x0c,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x67,0x6c,0x5f,0x43,0x6c,0x69,0x70,0x44,0x69,0x73,0x74,0x61, - 0x6e,0x63,0x65,0x00,0x06,0x00,0x07,0x00,0x0c,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x43,0x75,0x6c,0x6c,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,0x00, - 0x05,0x00,0x03,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00, - 0x13,0x00,0x00,0x00,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00, - 0x05,0x00,0x05,0x00,0x15,0x00,0x00,0x00,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d, - 0x73,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x64,0x69,0x73,0x70,0x5f,0x73,0x69,0x7a,0x65,0x00,0x00,0x00,0x05,0x00,0x03,0x00, - 0x17,0x00,0x00,0x00,0x5f,0x32,0x33,0x00,0x05,0x00,0x03,0x00,0x2a,0x00,0x00,0x00, - 0x75,0x76,0x00,0x00,0x05,0x00,0x05,0x00,0x2b,0x00,0x00,0x00,0x74,0x65,0x78,0x63, - 0x6f,0x6f,0x72,0x64,0x30,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x2d,0x00,0x00,0x00, - 0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x2f,0x00,0x00,0x00, - 0x63,0x6f,0x6c,0x6f,0x72,0x30,0x00,0x00,0x05,0x00,0x05,0x00,0x32,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x56,0x65,0x72,0x74,0x65,0x78,0x49,0x44,0x00,0x05,0x00,0x06,0x00, - 0x33,0x00,0x00,0x00,0x67,0x6c,0x5f,0x49,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x49, - 0x44,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0c,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,0x00,0x05,0x00, - 0x0c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x48,0x00,0x05,0x00,0x0c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0x47,0x00,0x03,0x00,0x0c,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x48,0x00,0x05,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x47,0x00,0x03,0x00,0x15,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x2a,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x2b,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x2d,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x2f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x32,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x05,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x33,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x06,0x00,0x00,0x00, - 0x13,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x21,0x00,0x03,0x00,0x04,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x07,0x00,0x00,0x00,0x20,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0x15,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x1c,0x00,0x04,0x00,0x0b,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, - 0x1e,0x00,0x06,0x00,0x0c,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0d,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00, - 0x0e,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x0f,0x00,0x00,0x00, - 0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x0f,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x11,0x00,0x00,0x00, - 0x07,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x12,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x12,0x00,0x00,0x00, - 0x13,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1e,0x00,0x03,0x00,0x15,0x00,0x00,0x00, - 0x11,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x15,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x17,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x11,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x1c,0x00,0x00,0x00, - 0x00,0x00,0x00,0x3f,0x2c,0x00,0x05,0x00,0x11,0x00,0x00,0x00,0x1d,0x00,0x00,0x00, - 0x1c,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00, - 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00, - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x2c,0x00,0x05,0x00,0x11,0x00,0x00,0x00, - 0x21,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x2b,0x00,0x04,0x00, - 0x07,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x20,0x00,0x04,0x00, - 0x27,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x04,0x00, - 0x29,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x29,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x12,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x27,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x20,0x00,0x04,0x00, - 0x2e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x2e,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x20,0x00,0x04,0x00, - 0x31,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x31,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x31,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x36,0x00,0x05,0x00, - 0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0xf8,0x00,0x02,0x00,0x06,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x01,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x11,0x00,0x00,0x00, - 0x14,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x18,0x00,0x00,0x00, - 0x19,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x11,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x88,0x00,0x05,0x00, - 0x11,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x1a,0x00,0x00,0x00, - 0x83,0x00,0x05,0x00,0x11,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1b,0x00,0x00,0x00, - 0x1d,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x11,0x00,0x00,0x00,0x22,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x07,0x00,0x00,0x00, - 0x24,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x05,0x00, - 0x07,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x50,0x00,0x07,0x00,0x08,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x24,0x00,0x00,0x00, - 0x25,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x41,0x00,0x05,0x00, - 0x27,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x10,0x00,0x00,0x00, - 0x3e,0x00,0x03,0x00,0x28,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x08,0x00,0x04,0x00, - 0x01,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x11,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x3e,0x00,0x03,0x00, - 0x2a,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x01,0x00,0x00,0x00, - 0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x00,0x00,0x00, - 0x30,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x2d,0x00,0x00,0x00, - 0x30,0x00,0x00,0x00,0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00, +static const char _simgui_vs_source_wgsl[1083] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20, + 0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x20,0x7b,0x0a,0x20,0x20,0x2f,0x2a, + 0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x30,0x29,0x20,0x2a,0x2f,0x0a,0x20, + 0x20,0x64,0x69,0x73,0x70,0x5f,0x73,0x69,0x7a,0x65,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x32,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61, + 0x74,0x65,0x3e,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x20,0x3a, + 0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,0x70,0x28, + 0x30,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x30,0x29,0x20,0x76, + 0x61,0x72,0x3c,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x3e,0x20,0x78,0x5f,0x32,0x32, + 0x20,0x3a,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x3b,0x0a,0x0a,0x76, + 0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a, + 0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20, + 0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72, + 0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61, + 0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65, + 0x3e,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20, + 0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f, + 0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x31,0x39, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74, + 0x69,0x6f,0x6e,0x5f,0x31,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32, + 0x35,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x78,0x5f,0x32,0x32, + 0x2e,0x64,0x69,0x73,0x70,0x5f,0x73,0x69,0x7a,0x65,0x3b,0x0a,0x20,0x20,0x6c,0x65, + 0x74,0x20,0x78,0x5f,0x33,0x33,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x20,0x3d, + 0x20,0x28,0x28,0x28,0x78,0x5f,0x31,0x39,0x20,0x2f,0x20,0x78,0x5f,0x32,0x35,0x29, + 0x20,0x2d,0x20,0x76,0x65,0x63,0x32,0x66,0x28,0x30,0x2e,0x35,0x66,0x2c,0x20,0x30, + 0x2e,0x35,0x66,0x29,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x32,0x66,0x28,0x32,0x2e, + 0x30,0x66,0x2c,0x20,0x2d,0x32,0x2e,0x30,0x66,0x29,0x29,0x3b,0x0a,0x20,0x20,0x67, + 0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63, + 0x34,0x66,0x28,0x78,0x5f,0x33,0x33,0x2e,0x78,0x2c,0x20,0x78,0x5f,0x33,0x33,0x2e, + 0x79,0x2c,0x20,0x30,0x2e,0x35,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x3b,0x0a, + 0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x34,0x33,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x32,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a, + 0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x78,0x5f,0x34,0x33,0x3b,0x0a,0x20,0x20,0x6c, + 0x65,0x74,0x20,0x78,0x5f,0x34,0x37,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20, + 0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f, + 0x72,0x20,0x3d,0x20,0x78,0x5f,0x34,0x37,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75, + 0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61, + 0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x40,0x62,0x75,0x69,0x6c, + 0x74,0x69,0x6e,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x29,0x0a,0x20,0x20, + 0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65, + 0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e, + 0x28,0x30,0x29,0x0a,0x20,0x20,0x75,0x76,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x32,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28, + 0x31,0x29,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x76,0x65,0x72,0x74,0x65,0x78, + 0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69, + 0x6f,0x6e,0x28,0x30,0x29,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20, + 0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x74,0x65,0x78, + 0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x32,0x66,0x2c,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28, + 0x32,0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20, + 0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x29,0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e, + 0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f, + 0x6e,0x5f,0x31,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f, + 0x72,0x64,0x30,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f, + 0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20, + 0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a, + 0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65, + 0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x28,0x67,0x6c, + 0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x75,0x76,0x2c,0x20,0x63, + 0x6f,0x6c,0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; -static const uint8_t _simgui_fs_bytecode_wgpu[904] = { - 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x08,0x00,0x08,0x00,0x19,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00, - 0x02,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x08,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x16,0x00,0x00,0x00, - 0x10,0x00,0x03,0x00,0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x03,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x37,0x00,0x02,0x00,0x00,0x00, - 0xc2,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64, - 0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69, - 0x65,0x6e,0x74,0x20,0x76,0x75,0x6c,0x6b,0x61,0x6e,0x31,0x30,0x30,0x0a,0x2f,0x2f, - 0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73, - 0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c, - 0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50, - 0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d, - 0x65,0x6e,0x76,0x20,0x76,0x75,0x6c,0x6b,0x61,0x6e,0x31,0x2e,0x30,0x0a,0x2f,0x2f, - 0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73, - 0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d,0x65,0x6e,0x76,0x20,0x6f,0x70, - 0x65,0x6e,0x67,0x6c,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65, - 0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x65,0x6e,0x74,0x72,0x79,0x2d, - 0x70,0x6f,0x69,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x0a,0x23,0x6c,0x69,0x6e,0x65, - 0x20,0x31,0x0a,0x00,0x05,0x00,0x04,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x0a,0x00,0x00,0x00,0x66,0x72,0x61,0x67, - 0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x05,0x00,0x03,0x00,0x0e,0x00,0x00,0x00, - 0x74,0x65,0x78,0x00,0x05,0x00,0x03,0x00,0x12,0x00,0x00,0x00,0x75,0x76,0x00,0x00, - 0x05,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x13,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x21,0x00,0x03,0x00,0x04,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x07,0x00,0x00,0x00,0x20,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x19,0x00,0x09,0x00,0x0b,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x1b,0x00,0x03,0x00,0x0c,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x15,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x15,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x36,0x00,0x05,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x06,0x00,0x00,0x00,0x08,0x00,0x04,0x00, - 0x01,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x0c,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x10,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x05,0x00, - 0x08,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x13,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x16,0x00,0x00,0x00, - 0x85,0x00,0x05,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x14,0x00,0x00,0x00, - 0x17,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x0a,0x00,0x00,0x00,0x18,0x00,0x00,0x00, - 0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00, +static const char _simgui_fs_source_wgsl[630] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75, + 0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x33,0x32, + 0x29,0x20,0x76,0x61,0x72,0x20,0x74,0x65,0x78,0x20,0x3a,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x5f,0x32,0x64,0x3c,0x66,0x33,0x32,0x3e,0x3b,0x0a,0x0a,0x40,0x67, + 0x72,0x6f,0x75,0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, + 0x28,0x34,0x38,0x29,0x20,0x76,0x61,0x72,0x20,0x73,0x6d,0x70,0x20,0x3a,0x20,0x73, + 0x61,0x6d,0x70,0x6c,0x65,0x72,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66, + 0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a, + 0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20, + 0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x33,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66, + 0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32, + 0x34,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x53,0x61,0x6d,0x70,0x6c,0x65,0x28,0x74,0x65,0x78,0x2c,0x20,0x73, + 0x6d,0x70,0x2c,0x20,0x78,0x5f,0x32,0x33,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74, + 0x20,0x78,0x5f,0x32,0x37,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f, + 0x6c,0x6f,0x72,0x20,0x3d,0x20,0x28,0x78,0x5f,0x32,0x34,0x20,0x2a,0x20,0x78,0x5f, + 0x32,0x37,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d, + 0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75, + 0x74,0x20,0x7b,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28, + 0x30,0x29,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x5f, + 0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x66, + 0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28, + 0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x75,0x76,0x5f, + 0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20,0x40, + 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x63,0x6f,0x6c,0x6f, + 0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x29, + 0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20, + 0x20,0x75,0x76,0x20,0x3d,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a, + 0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f, + 0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28, + 0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e, + 0x5f,0x6f,0x75,0x74,0x28,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x29, + 0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; #elif defined(SOKOL_DUMMY_BACKEND) static const char* _simgui_vs_source_dummy = ""; @@ -2396,8 +2330,8 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) { shd_desc.vs.bytecode = SG_RANGE(_simgui_vs_bytecode_hlsl4); shd_desc.fs.bytecode = SG_RANGE(_simgui_fs_bytecode_hlsl4); #elif defined(SOKOL_WGPU) - shd_desc.vs.bytecode = SG_RANGE(_simgui_vs_bytecode_wgpu); - shd_desc.fs.bytecode = SG_RANGE(_simgui_fs_bytecode_wgpu); + shd_desc.vs.source = _simgui_vs_source_wgsl; + shd_desc.fs.source = _simgui_fs_source_wgsl; #else shd_desc.vs.source = _simgui_vs_source_dummy; shd_desc.fs.source = _simgui_fs_source_dummy; From 21b4cb1dacd81f3e12b034e7df5ded6929e86e2b Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 3 Sep 2023 13:10:09 +0200 Subject: [PATCH 38/95] sokol_gfx_imgui.h: fix missing sokol-gfx wgpu backend string --- util/sokol_gfx_imgui.h | 1 + 1 file changed, 1 insertion(+) diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h index 9685331c9..7614f61a7 100644 --- a/util/sokol_gfx_imgui.h +++ b/util/sokol_gfx_imgui.h @@ -1098,6 +1098,7 @@ _SOKOL_PRIVATE const char* _sg_imgui_backend_string(sg_backend b) { case SG_BACKEND_METAL_IOS: return "SG_BACKEND_METAL_IOS"; case SG_BACKEND_METAL_MACOS: return "SG_BACKEND_METAL_MACOS"; case SG_BACKEND_METAL_SIMULATOR: return "SG_BACKEND_METAL_SIMULATOR"; + case SG_BACKEND_WGPU: return "SG_BACKEND_WGPU"; case SG_BACKEND_DUMMY: return "SG_BACKEND_DUMMY"; default: return "???"; } From 915214d277799867450632d0e8455db51e20e0c8 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 3 Sep 2023 13:36:35 +0200 Subject: [PATCH 39/95] sokol_gfx.h wgpu: fix memory clearing bug in bind group layout setup --- sokol_gfx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 98d713b3f..70b2937c9 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12766,6 +12766,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const #define _sg_wgpu_create_shader_max_bgl_entries (SG_NUM_SHADER_STAGES * (SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS)) WGPUBindGroupLayoutEntry wgpu_bgl_entries[_sg_wgpu_create_shader_max_bgl_entries]; + _sg_clear(wgpu_bgl_entries, sizeof(wgpu_bgl_entries)); int bgl_index = 0; for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { const sg_shader_stage_desc* stage_desc = (stage_index == SG_SHADERSTAGE_VS) ? &desc->vs : &desc->fs; @@ -12800,7 +12801,6 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_shader(_sg_shader_t* shd, const _SG_ERROR(WGPU_SHADER_TOO_MANY_SAMPLERS); return SG_RESOURCESTATE_FAILED; } - _sg_clear(wgpu_bgl_entries, sizeof(wgpu_bgl_entries)); for (int img_index = 0; img_index < num_images; img_index++) { SOKOL_ASSERT(bgl_index < _sg_wgpu_create_shader_max_bgl_entries); WGPUBindGroupLayoutEntry* wgpu_bgl_entry = &wgpu_bgl_entries[bgl_index++]; From bd96188aa66348729d2bbe1a682678708e434d3f Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 3 Sep 2023 13:48:09 +0200 Subject: [PATCH 40/95] sokol_nuklear.h: fix embedded wgsl shaders --- util/sokol_nuklear.h | 290 +++++++++++++++++-------------------------- 1 file changed, 112 insertions(+), 178 deletions(-) diff --git a/util/sokol_nuklear.h b/util/sokol_nuklear.h index 8a5cfb8d3..74f6fee28 100644 --- a/util/sokol_nuklear.h +++ b/util/sokol_nuklear.h @@ -1612,183 +1612,117 @@ static const uint8_t _snk_fs_bytecode_hlsl4[608] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #elif defined(SOKOL_WGPU) -static const uint8_t _snk_vs_bytecode_wgpu[1520] = { - 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x08,0x00,0x08,0x00,0x27,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00, - 0x02,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x2a,0x00,0x00,0x00, - 0x2b,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x32,0x00,0x00,0x00, - 0x33,0x00,0x00,0x00,0x07,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x37,0x00,0x02,0x00,0x00,0x00,0xc2,0x01,0x00,0x00,0x01,0x00,0x00,0x00, - 0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65, - 0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x76,0x75,0x6c,0x6b, - 0x61,0x6e,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c, - 0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e, - 0x74,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f, - 0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64, - 0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d,0x65,0x6e,0x76,0x20,0x76,0x75,0x6c,0x6b, - 0x61,0x6e,0x31,0x2e,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c, - 0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65, - 0x74,0x2d,0x65,0x6e,0x76,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c,0x0a,0x2f,0x2f,0x20, - 0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65, - 0x64,0x20,0x65,0x6e,0x74,0x72,0x79,0x2d,0x70,0x6f,0x69,0x6e,0x74,0x20,0x6d,0x61, - 0x69,0x6e,0x0a,0x23,0x6c,0x69,0x6e,0x65,0x20,0x31,0x0a,0x00,0x05,0x00,0x04,0x00, - 0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e,0x00,0x00,0x00,0x00,0x05,0x00,0x06,0x00, - 0x0c,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x65,0x72,0x56,0x65,0x72,0x74,0x65,0x78, - 0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x06,0x00,0x07,0x00, - 0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74, - 0x53,0x69,0x7a,0x65,0x00,0x00,0x00,0x00,0x06,0x00,0x07,0x00,0x0c,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x67,0x6c,0x5f,0x43,0x6c,0x69,0x70,0x44,0x69,0x73,0x74,0x61, - 0x6e,0x63,0x65,0x00,0x06,0x00,0x07,0x00,0x0c,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x43,0x75,0x6c,0x6c,0x44,0x69,0x73,0x74,0x61,0x6e,0x63,0x65,0x00, - 0x05,0x00,0x03,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00, - 0x13,0x00,0x00,0x00,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00, - 0x05,0x00,0x05,0x00,0x15,0x00,0x00,0x00,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d, - 0x73,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x64,0x69,0x73,0x70,0x5f,0x73,0x69,0x7a,0x65,0x00,0x00,0x00,0x05,0x00,0x03,0x00, - 0x17,0x00,0x00,0x00,0x5f,0x32,0x33,0x00,0x05,0x00,0x03,0x00,0x2a,0x00,0x00,0x00, - 0x75,0x76,0x00,0x00,0x05,0x00,0x05,0x00,0x2b,0x00,0x00,0x00,0x74,0x65,0x78,0x63, - 0x6f,0x6f,0x72,0x64,0x30,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x2d,0x00,0x00,0x00, - 0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00,0x05,0x00,0x04,0x00,0x2f,0x00,0x00,0x00, - 0x63,0x6f,0x6c,0x6f,0x72,0x30,0x00,0x00,0x05,0x00,0x05,0x00,0x32,0x00,0x00,0x00, - 0x67,0x6c,0x5f,0x56,0x65,0x72,0x74,0x65,0x78,0x49,0x44,0x00,0x05,0x00,0x06,0x00, - 0x33,0x00,0x00,0x00,0x67,0x6c,0x5f,0x49,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x49, - 0x44,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x05,0x00,0x0c,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,0x00,0x05,0x00, - 0x0c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x48,0x00,0x05,0x00,0x0c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0x47,0x00,0x03,0x00,0x0c,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x13,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x48,0x00,0x05,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x47,0x00,0x03,0x00,0x15,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x17,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x2a,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x2b,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x2d,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x2f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x32,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x05,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x33,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x06,0x00,0x00,0x00, - 0x13,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x21,0x00,0x03,0x00,0x04,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x07,0x00,0x00,0x00,0x20,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0x15,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x2b,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x1c,0x00,0x04,0x00,0x0b,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x0a,0x00,0x00,0x00, - 0x1e,0x00,0x06,0x00,0x0c,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x00, - 0x0b,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x0d,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00, - 0x0e,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x15,0x00,0x04,0x00,0x0f,0x00,0x00,0x00, - 0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x0f,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,0x04,0x00,0x11,0x00,0x00,0x00, - 0x07,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x12,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x12,0x00,0x00,0x00, - 0x13,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1e,0x00,0x03,0x00,0x15,0x00,0x00,0x00, - 0x11,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x15,0x00,0x00,0x00,0x3b,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x17,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x20,0x00,0x04,0x00,0x18,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x11,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x1c,0x00,0x00,0x00, - 0x00,0x00,0x00,0x3f,0x2c,0x00,0x05,0x00,0x11,0x00,0x00,0x00,0x1d,0x00,0x00,0x00, - 0x1c,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00, - 0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x2b,0x00,0x04,0x00,0x07,0x00,0x00,0x00, - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x2c,0x00,0x05,0x00,0x11,0x00,0x00,0x00, - 0x21,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x2b,0x00,0x04,0x00, - 0x07,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x80,0x3f,0x20,0x00,0x04,0x00, - 0x27,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x04,0x00, - 0x29,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x29,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x12,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x27,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x20,0x00,0x04,0x00, - 0x2e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x2e,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x20,0x00,0x04,0x00, - 0x31,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x31,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x3b,0x00,0x04,0x00, - 0x31,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x36,0x00,0x05,0x00, - 0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0xf8,0x00,0x02,0x00,0x06,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x01,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x11,0x00,0x00,0x00, - 0x14,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x41,0x00,0x05,0x00,0x18,0x00,0x00,0x00, - 0x19,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x11,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x88,0x00,0x05,0x00, - 0x11,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x1a,0x00,0x00,0x00, - 0x83,0x00,0x05,0x00,0x11,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1b,0x00,0x00,0x00, - 0x1d,0x00,0x00,0x00,0x85,0x00,0x05,0x00,0x11,0x00,0x00,0x00,0x22,0x00,0x00,0x00, - 0x1e,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x51,0x00,0x05,0x00,0x07,0x00,0x00,0x00, - 0x24,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x05,0x00, - 0x07,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x50,0x00,0x07,0x00,0x08,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x24,0x00,0x00,0x00, - 0x25,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x41,0x00,0x05,0x00, - 0x27,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x10,0x00,0x00,0x00, - 0x3e,0x00,0x03,0x00,0x28,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x08,0x00,0x04,0x00, - 0x01,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x11,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x3e,0x00,0x03,0x00, - 0x2a,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x01,0x00,0x00,0x00, - 0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00,0x08,0x00,0x00,0x00, - 0x30,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x2d,0x00,0x00,0x00, - 0x30,0x00,0x00,0x00,0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00, +static const char _snk_vs_source_wgsl[1083] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20, + 0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x20,0x7b,0x0a,0x20,0x20,0x2f,0x2a, + 0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x30,0x29,0x20,0x2a,0x2f,0x0a,0x20, + 0x20,0x64,0x69,0x73,0x70,0x5f,0x73,0x69,0x7a,0x65,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x32,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61, + 0x74,0x65,0x3e,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x20,0x3a, + 0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,0x70,0x28, + 0x30,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x30,0x29,0x20,0x76, + 0x61,0x72,0x3c,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x3e,0x20,0x78,0x5f,0x32,0x32, + 0x20,0x3a,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x3b,0x0a,0x0a,0x76, + 0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a, + 0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20, + 0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72, + 0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61, + 0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65, + 0x3e,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20, + 0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f, + 0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x31,0x39, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74, + 0x69,0x6f,0x6e,0x5f,0x31,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32, + 0x35,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x78,0x5f,0x32,0x32, + 0x2e,0x64,0x69,0x73,0x70,0x5f,0x73,0x69,0x7a,0x65,0x3b,0x0a,0x20,0x20,0x6c,0x65, + 0x74,0x20,0x78,0x5f,0x33,0x33,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x20,0x3d, + 0x20,0x28,0x28,0x28,0x78,0x5f,0x31,0x39,0x20,0x2f,0x20,0x78,0x5f,0x32,0x35,0x29, + 0x20,0x2d,0x20,0x76,0x65,0x63,0x32,0x66,0x28,0x30,0x2e,0x35,0x66,0x2c,0x20,0x30, + 0x2e,0x35,0x66,0x29,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x32,0x66,0x28,0x32,0x2e, + 0x30,0x66,0x2c,0x20,0x2d,0x32,0x2e,0x30,0x66,0x29,0x29,0x3b,0x0a,0x20,0x20,0x67, + 0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63, + 0x34,0x66,0x28,0x78,0x5f,0x33,0x33,0x2e,0x78,0x2c,0x20,0x78,0x5f,0x33,0x33,0x2e, + 0x79,0x2c,0x20,0x30,0x2e,0x35,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x3b,0x0a, + 0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x34,0x33,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x32,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a, + 0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x78,0x5f,0x34,0x33,0x3b,0x0a,0x20,0x20,0x6c, + 0x65,0x74,0x20,0x78,0x5f,0x34,0x37,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20, + 0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f, + 0x72,0x20,0x3d,0x20,0x78,0x5f,0x34,0x37,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75, + 0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61, + 0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x40,0x62,0x75,0x69,0x6c, + 0x74,0x69,0x6e,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x29,0x0a,0x20,0x20, + 0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65, + 0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e, + 0x28,0x30,0x29,0x0a,0x20,0x20,0x75,0x76,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x32,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28, + 0x31,0x29,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x76,0x65,0x72,0x74,0x65,0x78, + 0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69, + 0x6f,0x6e,0x28,0x30,0x29,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20, + 0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x74,0x65,0x78, + 0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x32,0x66,0x2c,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28, + 0x32,0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20, + 0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x29,0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e, + 0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f, + 0x6e,0x5f,0x31,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f, + 0x72,0x64,0x30,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f, + 0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20, + 0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a, + 0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65, + 0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x28,0x67,0x6c, + 0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x75,0x76,0x2c,0x20,0x63, + 0x6f,0x6c,0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; -static const uint8_t _snk_fs_bytecode_wgpu[904] = { - 0x03,0x02,0x23,0x07,0x00,0x00,0x01,0x00,0x08,0x00,0x08,0x00,0x19,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x11,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x06,0x00, - 0x02,0x00,0x00,0x00,0x47,0x4c,0x53,0x4c,0x2e,0x73,0x74,0x64,0x2e,0x34,0x35,0x30, - 0x00,0x00,0x00,0x00,0x0e,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x08,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x16,0x00,0x00,0x00, - 0x10,0x00,0x03,0x00,0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x07,0x00,0x03,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x37,0x00,0x02,0x00,0x00,0x00, - 0xc2,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64, - 0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x63,0x6c,0x69, - 0x65,0x6e,0x74,0x20,0x76,0x75,0x6c,0x6b,0x61,0x6e,0x31,0x30,0x30,0x0a,0x2f,0x2f, - 0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73, - 0x65,0x64,0x20,0x63,0x6c,0x69,0x65,0x6e,0x74,0x20,0x6f,0x70,0x65,0x6e,0x67,0x6c, - 0x31,0x30,0x30,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50, - 0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d, - 0x65,0x6e,0x76,0x20,0x76,0x75,0x6c,0x6b,0x61,0x6e,0x31,0x2e,0x30,0x0a,0x2f,0x2f, - 0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65,0x50,0x72,0x6f,0x63,0x65,0x73,0x73, - 0x65,0x64,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2d,0x65,0x6e,0x76,0x20,0x6f,0x70, - 0x65,0x6e,0x67,0x6c,0x0a,0x2f,0x2f,0x20,0x4f,0x70,0x4d,0x6f,0x64,0x75,0x6c,0x65, - 0x50,0x72,0x6f,0x63,0x65,0x73,0x73,0x65,0x64,0x20,0x65,0x6e,0x74,0x72,0x79,0x2d, - 0x70,0x6f,0x69,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x0a,0x23,0x6c,0x69,0x6e,0x65, - 0x20,0x31,0x0a,0x00,0x05,0x00,0x04,0x00,0x05,0x00,0x00,0x00,0x6d,0x61,0x69,0x6e, - 0x00,0x00,0x00,0x00,0x05,0x00,0x05,0x00,0x0a,0x00,0x00,0x00,0x66,0x72,0x61,0x67, - 0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x05,0x00,0x03,0x00,0x0e,0x00,0x00,0x00, - 0x74,0x65,0x78,0x00,0x05,0x00,0x03,0x00,0x12,0x00,0x00,0x00,0x75,0x76,0x00,0x00, - 0x05,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x63,0x6f,0x6c,0x6f,0x72,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0a,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x0e,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x12,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x47,0x00,0x04,0x00,0x16,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x13,0x00,0x02,0x00,0x03,0x00,0x00,0x00,0x21,0x00,0x03,0x00,0x04,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x16,0x00,0x03,0x00,0x07,0x00,0x00,0x00,0x20,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x09,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x19,0x00,0x09,0x00,0x0b,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x1b,0x00,0x03,0x00,0x0c,0x00,0x00,0x00,0x0b,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x0d,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x17,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x11,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x20,0x00,0x04,0x00,0x15,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x3b,0x00,0x04,0x00,0x15,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x36,0x00,0x05,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0xf8,0x00,0x02,0x00,0x06,0x00,0x00,0x00,0x08,0x00,0x04,0x00, - 0x01,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x0c,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x3d,0x00,0x04,0x00, - 0x10,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x57,0x00,0x05,0x00, - 0x08,0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x13,0x00,0x00,0x00, - 0x3d,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x16,0x00,0x00,0x00, - 0x85,0x00,0x05,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x14,0x00,0x00,0x00, - 0x17,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0x0a,0x00,0x00,0x00,0x18,0x00,0x00,0x00, - 0xfd,0x00,0x01,0x00,0x38,0x00,0x01,0x00, +static const char _snk_fs_source_wgsl[630] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75, + 0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x33,0x32, + 0x29,0x20,0x76,0x61,0x72,0x20,0x74,0x65,0x78,0x20,0x3a,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x5f,0x32,0x64,0x3c,0x66,0x33,0x32,0x3e,0x3b,0x0a,0x0a,0x40,0x67, + 0x72,0x6f,0x75,0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, + 0x28,0x34,0x38,0x29,0x20,0x76,0x61,0x72,0x20,0x73,0x6d,0x70,0x20,0x3a,0x20,0x73, + 0x61,0x6d,0x70,0x6c,0x65,0x72,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66, + 0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a, + 0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20, + 0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x33,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66, + 0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32, + 0x34,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x53,0x61,0x6d,0x70,0x6c,0x65,0x28,0x74,0x65,0x78,0x2c,0x20,0x73, + 0x6d,0x70,0x2c,0x20,0x78,0x5f,0x32,0x33,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74, + 0x20,0x78,0x5f,0x32,0x37,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f, + 0x6c,0x6f,0x72,0x20,0x3d,0x20,0x28,0x78,0x5f,0x32,0x34,0x20,0x2a,0x20,0x78,0x5f, + 0x32,0x37,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d, + 0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75, + 0x74,0x20,0x7b,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28, + 0x30,0x29,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x5f, + 0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x66, + 0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28, + 0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x75,0x76,0x5f, + 0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20,0x40, + 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x63,0x6f,0x6c,0x6f, + 0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x29, + 0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20, + 0x20,0x75,0x76,0x20,0x3d,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a, + 0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f, + 0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28, + 0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e, + 0x5f,0x6f,0x75,0x74,0x28,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x29, + 0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; #elif defined(SOKOL_DUMMY_BACKEND) static const char* _snk_vs_source_dummy = ""; @@ -2261,8 +2195,8 @@ SOKOL_API_IMPL void snk_setup(const snk_desc_t* desc) { vs_bytecode = SG_RANGE(_snk_vs_bytecode_hlsl4); fs_bytecode = SG_RANGE(_snk_fs_bytecode_hlsl4); #elif defined(SOKOL_WGPU) - vs_bytecode = SG_RANGE(_snk_vs_bytecode_wgpu); - fs_bytecode = SG_RANGE(_snk_fs_bytecode_wgpu); + vs_source = _snk_vs_source_wgsl; + fs_source = _snk_fs_source_wgsl; #else vs_source = _snk_vs_source_dummy; fs_source = _snk_fs_source_dummy; From 7fdfefe0a3e5b2b1860fa34b71c7ad5e96631691 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 3 Sep 2023 15:09:26 +0200 Subject: [PATCH 41/95] sokol_spine.h: fix embedded wgsl shader --- util/sokol_spine.h | 143 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 3 deletions(-) diff --git a/util/sokol_spine.h b/util/sokol_spine.h index 0ca556c8c..8bdbc87bf 100644 --- a/util/sokol_spine.h +++ b/util/sokol_spine.h @@ -2571,7 +2571,144 @@ static const char _sspine_fs_source_metal_sim[619] = { 0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, }; #elif defined(SOKOL_WGPU) -#error "FIXME: wgpu shaders" +static const char _sspine_vs_source_wgsl[1003] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20, + 0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x20,0x7b,0x0a,0x20,0x20,0x2f,0x2a, + 0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x30,0x29,0x20,0x2a,0x2f,0x0a,0x20, + 0x20,0x6d,0x76,0x70,0x20,0x3a,0x20,0x6d,0x61,0x74,0x34,0x78,0x34,0x66,0x2c,0x0a, + 0x7d,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,0x70,0x28,0x30,0x29,0x20,0x40,0x62,0x69, + 0x6e,0x64,0x69,0x6e,0x67,0x28,0x30,0x29,0x20,0x76,0x61,0x72,0x3c,0x75,0x6e,0x69, + 0x66,0x6f,0x72,0x6d,0x3e,0x20,0x78,0x5f,0x31,0x39,0x20,0x3a,0x20,0x76,0x73,0x5f, + 0x70,0x61,0x72,0x61,0x6d,0x73,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69, + 0x76,0x61,0x74,0x65,0x3e,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70, + 0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65, + 0x3e,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20,0x3a,0x20,0x76,0x65, + 0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74, + 0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66, + 0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a, + 0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x67,0x6c, + 0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63,0x34, + 0x66,0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20, + 0x7b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x32,0x20,0x3a,0x20,0x6d, + 0x61,0x74,0x34,0x78,0x34,0x66,0x20,0x3d,0x20,0x78,0x5f,0x31,0x39,0x2e,0x6d,0x76, + 0x70,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x36,0x20,0x3a,0x20, + 0x76,0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e, + 0x5f,0x31,0x3b,0x0a,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f, + 0x6e,0x20,0x3d,0x20,0x28,0x78,0x5f,0x32,0x32,0x20,0x2a,0x20,0x76,0x65,0x63,0x34, + 0x66,0x28,0x78,0x5f,0x32,0x36,0x2e,0x78,0x2c,0x20,0x78,0x5f,0x32,0x36,0x2e,0x79, + 0x2c,0x20,0x30,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x29,0x3b,0x0a, + 0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x38,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x32,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a, + 0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x78,0x5f,0x33,0x38,0x3b,0x0a,0x20,0x20,0x6c, + 0x65,0x74,0x20,0x78,0x5f,0x34,0x32,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20, + 0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f, + 0x72,0x20,0x3d,0x20,0x78,0x5f,0x34,0x32,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75, + 0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61, + 0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x40,0x62,0x75,0x69,0x6c, + 0x74,0x69,0x6e,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x29,0x0a,0x20,0x20, + 0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65, + 0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e, + 0x28,0x30,0x29,0x0a,0x20,0x20,0x75,0x76,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63, + 0x32,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28, + 0x31,0x29,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x76,0x65,0x72,0x74,0x65,0x78, + 0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69, + 0x6f,0x6e,0x28,0x30,0x29,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20, + 0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x74,0x65,0x78, + 0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x32,0x66,0x2c,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28, + 0x32,0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20, + 0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x29,0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e, + 0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f, + 0x6e,0x5f,0x31,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f, + 0x72,0x64,0x30,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f, + 0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20, + 0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a, + 0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65, + 0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x28,0x67,0x6c, + 0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x75,0x76,0x2c,0x20,0x63, + 0x6f,0x6c,0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, +}; +static const char _sspine_fs_source_wgsl[1125] = { + 0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20, + 0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f, + 0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20, + 0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x20,0x7b,0x0a,0x20,0x20,0x2f,0x2a, + 0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x30,0x29,0x20,0x2a,0x2f,0x0a,0x20, + 0x20,0x70,0x6d,0x61,0x20,0x3a,0x20,0x66,0x33,0x32,0x2c,0x0a,0x7d,0x0a,0x0a,0x40, + 0x67,0x72,0x6f,0x75,0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e, + 0x67,0x28,0x33,0x32,0x29,0x20,0x76,0x61,0x72,0x20,0x74,0x65,0x78,0x20,0x3a,0x20, + 0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x5f,0x32,0x64,0x3c,0x66,0x33,0x32,0x3e,0x3b, + 0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e, + 0x64,0x69,0x6e,0x67,0x28,0x34,0x38,0x29,0x20,0x76,0x61,0x72,0x20,0x73,0x6d,0x70, + 0x20,0x3a,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x3b,0x0a,0x0a,0x76,0x61,0x72, + 0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76, + 0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61, + 0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65,0x63,0x34, + 0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e, + 0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65, + 0x63,0x34,0x66,0x3b,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,0x70,0x28,0x30,0x29,0x20, + 0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x34,0x29,0x20,0x76,0x61,0x72,0x3c, + 0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x3e,0x20,0x78,0x5f,0x35,0x33,0x20,0x3a,0x20, + 0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d, + 0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,0x76,0x61,0x72,0x20, + 0x63,0x30,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x20,0x20,0x76,0x61, + 0x72,0x20,0x63,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x20,0x20, + 0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x33,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66, + 0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32, + 0x34,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x74, + 0x75,0x72,0x65,0x53,0x61,0x6d,0x70,0x6c,0x65,0x28,0x74,0x65,0x78,0x2c,0x20,0x73, + 0x6d,0x70,0x2c,0x20,0x78,0x5f,0x32,0x33,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74, + 0x20,0x78,0x5f,0x32,0x37,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20, + 0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x63,0x30,0x20,0x3d,0x20,0x28,0x78, + 0x5f,0x32,0x34,0x20,0x2a,0x20,0x78,0x5f,0x32,0x37,0x29,0x3b,0x0a,0x20,0x20,0x6c, + 0x65,0x74,0x20,0x78,0x5f,0x33,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20, + 0x3d,0x20,0x63,0x30,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x37, + 0x20,0x3a,0x20,0x66,0x33,0x32,0x20,0x3d,0x20,0x63,0x30,0x2e,0x77,0x3b,0x0a,0x20, + 0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x38,0x20,0x3a,0x20,0x76,0x65,0x63,0x33, + 0x66,0x20,0x3d,0x20,0x28,0x76,0x65,0x63,0x33,0x66,0x28,0x78,0x5f,0x33,0x31,0x2e, + 0x78,0x2c,0x20,0x78,0x5f,0x33,0x31,0x2e,0x79,0x2c,0x20,0x78,0x5f,0x33,0x31,0x2e, + 0x7a,0x29,0x20,0x2a,0x20,0x78,0x5f,0x33,0x37,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65, + 0x74,0x20,0x78,0x5f,0x34,0x30,0x20,0x3a,0x20,0x66,0x33,0x32,0x20,0x3d,0x20,0x63, + 0x30,0x2e,0x77,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x34,0x35,0x20, + 0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b, + 0x0a,0x20,0x20,0x63,0x31,0x20,0x3d,0x20,0x28,0x76,0x65,0x63,0x34,0x66,0x28,0x78, + 0x5f,0x33,0x38,0x2e,0x78,0x2c,0x20,0x78,0x5f,0x33,0x38,0x2e,0x79,0x2c,0x20,0x78, + 0x5f,0x33,0x38,0x2e,0x7a,0x2c,0x20,0x78,0x5f,0x34,0x30,0x29,0x20,0x2a,0x20,0x78, + 0x5f,0x34,0x35,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x34,0x39, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x63,0x30,0x3b,0x0a,0x20, + 0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x35,0x30,0x20,0x3a,0x20,0x76,0x65,0x63,0x34, + 0x66,0x20,0x3d,0x20,0x63,0x31,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f, + 0x35,0x38,0x20,0x3a,0x20,0x66,0x33,0x32,0x20,0x3d,0x20,0x78,0x5f,0x35,0x33,0x2e, + 0x70,0x6d,0x61,0x3b,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f, + 0x72,0x20,0x3d,0x20,0x6d,0x69,0x78,0x28,0x78,0x5f,0x34,0x39,0x2c,0x20,0x78,0x5f, + 0x35,0x30,0x2c,0x20,0x76,0x65,0x63,0x34,0x66,0x28,0x78,0x5f,0x35,0x38,0x2c,0x20, + 0x78,0x5f,0x35,0x38,0x2c,0x20,0x78,0x5f,0x35,0x38,0x2c,0x20,0x78,0x5f,0x35,0x38, + 0x29,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,0x0a, + 0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74, + 0x20,0x7b,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30, + 0x29,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x31, + 0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x66,0x72, + 0x61,0x67,0x6d,0x65,0x6e,0x74,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x28,0x40, + 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x75,0x76,0x5f,0x70, + 0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20,0x40,0x6c, + 0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72, + 0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x29,0x20, + 0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,0x20, + 0x75,0x76,0x20,0x3d,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20, + 0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x5f,0x70, + 0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29, + 0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f, + 0x6f,0x75,0x74,0x28,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x29,0x3b, + 0x0a,0x7d,0x0a,0x0a,0x00, +}; #elif defined(SOKOL_DUMMY_BACKEND) static const char* _sspine_vs_source_dummy = ""; static const char* _sspine_fs_source_dummy = ""; @@ -4554,8 +4691,8 @@ static void _sspine_init_shared(void) { shd_desc.vs.bytecode = SG_RANGE(_sspine_vs_bytecode_hlsl4); shd_desc.fs.bytecode = SG_RANGE(_sspine_fs_bytecode_hlsl4); #elif defined(SOKOL_WGPU) - shd_desc.vs.bytecode = SG_RANGE(_sspine_vs_bytecode_wgpu); - shd_desc.fs.bytecode = SG_RANGE(_sspine_fs_bytecode_wgpu); + shd_desc.vs.source = _sspine_vs_source_wgsl; + shd_desc.fs.source = _sspine_fs_source_wgsl; #else shd_desc.vs.source = _sspine_vs_source_dummy; shd_desc.fs.source = _sspine_fs_source_dummy; From 38eee79b7dbd65f4941d613b072a70a675027b8c Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 4 Sep 2023 13:54:22 +0200 Subject: [PATCH 42/95] sokol_gfx.h wgpu: fix pixel format caps --- sokol_gfx.h | 57 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 70b2937c9..09a0bd088 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12337,40 +12337,49 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { _sg.limits.max_image_array_layers = (int) l->maxTextureArrayLayers; _sg.limits.max_vertex_attrs = SG_MAX_VERTEX_ATTRIBUTES; - _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R8SN]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8UI]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R8SI]); // NOTE: no WGPUTextureFormat_R16Unorm - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16UI]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_R16SI]); - _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16F]); + _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R8]); _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG8]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG8SN]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8UI]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG8SI]); - _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32UI]); - _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32SI]); - _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32F]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16UI]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RG16SI]); - _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16F]); _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA8]); - _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA8SN]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA8UI]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA8SI]); _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_BGRA8]); + _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_R16F]); + _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RG16F]); + _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16F]); _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGB10A2]); - // FIXME: missing SG_PIXELFORMAT_RG11B10F + + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_R8SN]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG8SN]); + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RGBA8SN]); + + // FIXME: can be made renderable via extension + _sg_pixelformat_sf(&_sg.formats[SG_PIXELFORMAT_RG11B10F]); + + // NOTE: msaa rendering is possible in WebGPU, but no resolve + // which is a combination that's not currently supported in sokol-gfx + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R8UI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R8SI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG8UI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG8SI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA8UI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA8SI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R16UI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R16SI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG16UI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG16SI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA16UI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA16SI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32UI]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32SI]); _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32UI]); _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32SI]); - _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32F]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16UI]); - _sg_pixelformat_srm(&_sg.formats[SG_PIXELFORMAT_RGBA16SI]); - _sg_pixelformat_all(&_sg.formats[SG_PIXELFORMAT_RGBA16F]); _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32UI]); _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32SI]); + + // FIXME: can be made filterable with extension + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_R32F]); + _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RG32F]); _sg_pixelformat_sr(&_sg.formats[SG_PIXELFORMAT_RGBA32F]); + _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH]); _sg_pixelformat_srmd(&_sg.formats[SG_PIXELFORMAT_DEPTH_STENCIL]); From 8b49fa778e5821ec68023d2191be63acf2a64dbc Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 4 Sep 2023 18:17:29 +0200 Subject: [PATCH 43/95] sokol_gfx.h: new sg_sampler_desc validation: max_anistropy > 1 requires all filters to be linear --- sokol_gfx.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sokol_gfx.h b/sokol_gfx.h index 09a0bd088..3c4390224 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2981,6 +2981,7 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_CANARY, "sg_sampler_desc not initialized") \ _SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_MINFILTER_NONE, "sg_sampler_desc.min_filter cannot be SG_FILTER_NONE") \ _SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_MAGFILTER_NONE, "sg_sampler_desc.mag_filter cannot be SG_FILTER_NONE") \ + _SG_LOGITEM_XMACRO(VALIDATE_SAMPLERDESC_ANISTROPIC_REQUIRES_LINEAR_FILTERING, "sg_sampler_desc.max_anisotropy > 1 requires min/mag/mipmap_filter to be SG_FILTER_LINEAR") \ _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_CANARY, "sg_shader_desc not initialized") \ _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_SOURCE, "shader source code required") \ _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_BYTECODE, "shader byte code required") \ @@ -14507,6 +14508,13 @@ _SOKOL_PRIVATE bool _sg_validate_sampler_desc(const sg_sampler_desc* desc) { _SG_VALIDATE(desc->_end_canary == 0, VALIDATE_SAMPLERDESC_CANARY); _SG_VALIDATE(desc->min_filter != SG_FILTER_NONE, VALIDATE_SAMPLERDESC_MINFILTER_NONE); _SG_VALIDATE(desc->mag_filter != SG_FILTER_NONE, VALIDATE_SAMPLERDESC_MAGFILTER_NONE); + // restriction from WebGPU: when anisotropy > 1, all filters must be linear + if (desc->max_anisotropy > 1) { + _SG_VALIDATE((desc->min_filter == SG_FILTER_LINEAR) + && (desc->mag_filter == SG_FILTER_LINEAR) + && (desc->mipmap_filter == SG_FILTER_LINEAR), + VALIDATE_SAMPLERDESC_ANISTROPIC_REQUIRES_LINEAR_FILTERING); + } return _sg_validate_end(); #endif } From 647497809ad35aaa7404d1912bde386f834d8093 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 4 Sep 2023 18:57:43 +0200 Subject: [PATCH 44/95] sokol_gfx tests: add sampler-desc validation tests --- tests/functional/sokol_gfx_test.c | 88 ++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/tests/functional/sokol_gfx_test.c b/tests/functional/sokol_gfx_test.c index 90d460afe..1f80b2a0f 100644 --- a/tests/functional/sokol_gfx_test.c +++ b/tests/functional/sokol_gfx_test.c @@ -1016,6 +1016,7 @@ UTEST(sokol_gfx, query_sampler_desc) { setup(&(sg_desc){0}); sg_sampler s0 = sg_make_sampler(&(sg_sampler_desc){ .min_filter = SG_FILTER_LINEAR, + .mag_filter = SG_FILTER_LINEAR, .mipmap_filter = SG_FILTER_LINEAR, .wrap_v = SG_WRAP_MIRRORED_REPEAT, .max_anisotropy = 8, @@ -1024,7 +1025,7 @@ UTEST(sokol_gfx, query_sampler_desc) { }); const sg_sampler_desc s0_desc = sg_query_sampler_desc(s0); T(s0_desc.min_filter == SG_FILTER_LINEAR); - T(s0_desc.mag_filter == SG_FILTER_NEAREST); + T(s0_desc.mag_filter == SG_FILTER_LINEAR); T(s0_desc.mipmap_filter == SG_FILTER_LINEAR); T(s0_desc.wrap_u == SG_WRAP_REPEAT); T(s0_desc.wrap_v == SG_WRAP_MIRRORED_REPEAT); @@ -2150,6 +2151,91 @@ UTEST(sokol_gfx, make_image_validate_wrong_mipsize) { sg_shutdown(); } +UTEST(sokol_gfx, make_sampler_validate_start_canary) { + setup(&(sg_desc){0}); + sg_sampler smp = sg_make_sampler(&(sg_sampler_desc){ + ._start_canary = 1234, + }); + T(sg_query_sampler_state(smp) == SG_RESOURCESTATE_FAILED); + T(log_items[0] == SG_LOGITEM_VALIDATE_SAMPLERDESC_CANARY); + sg_shutdown(); +} + +UTEST(sokol_gfx, make_sampler_validate_minfilter_none) { + setup(&(sg_desc){0}); + sg_sampler smp = sg_make_sampler(&(sg_sampler_desc){ + .min_filter = SG_FILTER_NONE, + }); + T(sg_query_sampler_state(smp) == SG_RESOURCESTATE_FAILED); + T(log_items[0] == SG_LOGITEM_VALIDATE_SAMPLERDESC_MINFILTER_NONE); + sg_shutdown(); +} + +UTEST(sokol_gfx, make_sampler_validate_magfilter_none) { + setup(&(sg_desc){0}); + sg_sampler smp = sg_make_sampler(&(sg_sampler_desc){ + .mag_filter = SG_FILTER_NONE, + }); + T(sg_query_sampler_state(smp) == SG_RESOURCESTATE_FAILED); + T(log_items[0] == SG_LOGITEM_VALIDATE_SAMPLERDESC_MAGFILTER_NONE); + sg_shutdown(); +} + +UTEST(sokol_gfx, make_sampler_validate_anistropic_requires_linear_filtering) { + setup(&(sg_desc){0}); + sg_sampler smp; + + smp = sg_make_sampler(&(sg_sampler_desc){ + .max_anisotropy = 2, + .min_filter = SG_FILTER_LINEAR, + .mag_filter = SG_FILTER_LINEAR, + .mipmap_filter = SG_FILTER_NONE, + }); + T(sg_query_sampler_state(smp) == SG_RESOURCESTATE_FAILED); + T(log_items[0] == SG_LOGITEM_VALIDATE_SAMPLERDESC_ANISTROPIC_REQUIRES_LINEAR_FILTERING); + + reset_log_items(); + smp = sg_make_sampler(&(sg_sampler_desc){ + .max_anisotropy = 2, + .min_filter = SG_FILTER_LINEAR, + .mag_filter = SG_FILTER_LINEAR, + .mipmap_filter = SG_FILTER_NEAREST, + }); + T(sg_query_sampler_state(smp) == SG_RESOURCESTATE_FAILED); + T(log_items[0] == SG_LOGITEM_VALIDATE_SAMPLERDESC_ANISTROPIC_REQUIRES_LINEAR_FILTERING); + + reset_log_items(); + smp = sg_make_sampler(&(sg_sampler_desc){ + .max_anisotropy = 2, + .min_filter = SG_FILTER_NEAREST, + .mag_filter = SG_FILTER_LINEAR, + .mipmap_filter = SG_FILTER_LINEAR, + }); + T(sg_query_sampler_state(smp) == SG_RESOURCESTATE_FAILED); + T(log_items[0] == SG_LOGITEM_VALIDATE_SAMPLERDESC_ANISTROPIC_REQUIRES_LINEAR_FILTERING); + + reset_log_items(); + smp = sg_make_sampler(&(sg_sampler_desc){ + .max_anisotropy = 2, + .min_filter = SG_FILTER_LINEAR, + .mag_filter = SG_FILTER_NEAREST, + .mipmap_filter = SG_FILTER_LINEAR, + }); + T(sg_query_sampler_state(smp) == SG_RESOURCESTATE_FAILED); + T(log_items[0] == SG_LOGITEM_VALIDATE_SAMPLERDESC_ANISTROPIC_REQUIRES_LINEAR_FILTERING); + + reset_log_items(); + smp = sg_make_sampler(&(sg_sampler_desc){ + .max_anisotropy = 2, + .min_filter = SG_FILTER_LINEAR, + .mag_filter = SG_FILTER_LINEAR, + .mipmap_filter = SG_FILTER_LINEAR, + }); + T(sg_query_sampler_state(smp) == SG_RESOURCESTATE_VALID); + + sg_shutdown(); +} + UTEST(sokol_gfx, make_pass_validate_start_canary) { setup(&(sg_desc){0}); sg_pass pass = sg_make_pass(&(sg_pass_desc){ From 6fe8f03da808eeb5521cf1ebee67d6dbd12f29df Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 5 Sep 2023 19:00:14 +0200 Subject: [PATCH 45/95] sokol_gfx.h: validate image sample type vs sampler type in sg_shader_desc --- sokol_gfx.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sokol_gfx.h b/sokol_gfx.h index 3c4390224..9e1cc715b 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -3002,6 +3002,8 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_NAME_BUT_NOT_USED, "shader stage: image-sampler-pair has name but .used field not true") \ _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_IMAGE_BUT_NOT_USED, "shader stage: image-sampler-pair has .image_slot != 0 but .used field not true") \ _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_SAMPLER_BUT_NOT_USED, "shader stage: image-sampler-pair .sampler_slot != 0 but .used field not true") \ + _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NONFILTERING_SAMPLER_REQUIRED, "shader stage: image sample type UNFILTERABLE_FLOAT, UINT, SINT can only be used with NONFILTERING sampler") \ + _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_COMPARISON_SAMPLER_REQUIRED, "shader stage: image sample type DEPTH can only be used with COMPARISON sampler") \ _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_IMAGE_NOT_REFERENCED_BY_IMAGE_SAMPLER_PAIRS, "shader stage: one or more images are note referenced by (sg_shader_desc.vs|fs.image_sampler_pairs[].image_slot)") \ _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_SAMPLER_NOT_REFERENCED_BY_IMAGE_SAMPLER_PAIRS, "shader stage: one or more samplers are not referenced by image-sampler-pairs (sg_shader_desc.vs|fs.image_sampler_pairs[].sampler_slot)") \ _SG_LOGITEM_XMACRO(VALIDATE_SHADERDESC_NO_CONT_IMAGE_SAMPLER_PAIRS, "shader stage image-sampler-pairs must occupy continuous slots (sg_shader_desc.vs|fs.image_samplers[])") \ @@ -14641,6 +14643,20 @@ _SOKOL_PRIVATE bool _sg_validate_shader_desc(const sg_shader_desc* desc) { #if defined(_SOKOL_ANY_GL) _SG_VALIDATE(img_smp_desc->glsl_name != 0, VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_NAME_REQUIRED_FOR_GL); #endif + if (img_slot_in_range && smp_slot_in_range) { + const sg_shader_image_desc* img_desc = &stage_desc->images[img_smp_desc->image_slot]; + const sg_shader_sampler_desc* smp_desc = &stage_desc->samplers[img_smp_desc->sampler_slot]; + const bool needs_nonfiltering = (img_desc->sample_type == SG_IMAGESAMPLETYPE_UINT) + || (img_desc->sample_type == SG_IMAGESAMPLETYPE_SINT) + || (img_desc->sample_type == SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT); + const bool needs_comparison = img_desc->sample_type == SG_IMAGESAMPLETYPE_DEPTH; + if (needs_nonfiltering) { + _SG_VALIDATE(needs_nonfiltering && (smp_desc->sampler_type == SG_SAMPLERTYPE_NONFILTERING), VALIDATE_SHADERDESC_NONFILTERING_SAMPLER_REQUIRED); + } + if (needs_comparison) { + _SG_VALIDATE(needs_comparison && (smp_desc->sampler_type == SG_SAMPLERTYPE_COMPARISON), VALIDATE_SHADERDESC_COMPARISON_SAMPLER_REQUIRED); + } + } } else { _SG_VALIDATE(img_smp_desc->glsl_name == 0, VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_NAME_BUT_NOT_USED); _SG_VALIDATE(img_smp_desc->image_slot == 0, VALIDATE_SHADERDESC_IMAGE_SAMPLER_PAIR_HAS_IMAGE_BUT_NOT_USED); From e5f5d95d6a1b853b3614136c11f5b80a51f4289c Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 5 Sep 2023 19:29:10 +0200 Subject: [PATCH 46/95] sokol_gfx.h: image sample type and sampler type validation in sg_apply_bindings() --- sokol_gfx.h | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 9e1cc715b..e79f999de 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -3074,10 +3074,13 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_IMG_EXISTS, "sg_apply_bindings: image bound to vertex stage no longer alive") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_IMAGE_TYPE_MISMATCH, "sg_apply_bindings: type of image bound to vertex stage doesn't match shader desc") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_IMAGE_MSAA, "sg_apply_bindings: cannot bind image with sample_count>1 to vertex stage") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_FILTERABLE_IMAGE, "sg_apply_bindings: filterable image expected on vertex stage") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_DEPTH_IMAGE, "sg_apply_bindings: depth image expected on vertex stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_IMAGE_BINDING, "sg_apply_bindings: unexpected image binding on vertex stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_SAMPLER_BINDING, "sg_apply_bindings: missing sampler binding on vertex stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_COMPARISON on vertex stage but sampler has SG_COMPAREFUNC_NEVER") \ - _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_FILTERING on vertex stage but sampler doesn't have SG_COMPAREFUNC_NEVER") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING on vertex stage but sampler doesn't have SG_COMPAREFUNC_NEVER") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_EXPECTED_NONFILTERING_SAMPLER, "sg_apply_bindings: shader expected SG_SAMPLERTYPE_NONFILTERING on vertex stage, but sampler has SG_FILTER_LINEAR filters") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_UNEXPECTED_SAMPLER_BINDING, "sg_apply_bindings: unexpected sampler binding on vertex stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_SMP_EXISTS, "sg_apply_bindings: sampler bound to vertex stage no longer alive") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_VS_IMG_SMP_MIPMAPS, "sg_apply_bindings: image bound to vertex stage has mipmap_count == 1, but associated sampler mipmap filer is not SG_MIPMAPFILTER_NONE") \ @@ -3085,10 +3088,13 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_IMG_EXISTS, "sg_apply_bindings: image bound to fragment stage no longer alive") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_IMAGE_TYPE_MISMATCH, "sg_apply_bindings: type of image bound to fragment stage doesn't match shader desc") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_IMAGE_MSAA, "sg_apply_bindings: cannot bind image with sample_count>1 to fragment stage") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_FILTERABLE_IMAGE, "sg_apply_bindings: filterable image expected on fragment stage") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_DEPTH_IMAGE, "sg_apply_bindings: depth image expected on fragment stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_IMAGE_BINDING, "sg_apply_bindings: unexpected image binding on fragment stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_SAMPLER_BINDING, "sg_apply_bindings: missing sampler binding on fragment stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_COMPARISON on fragment stage but sampler has SG_COMPAREFUNC_NEVER") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_SAMPLER_COMPARE_NEVER, "sg_apply_bindings: shader expects SG_SAMPLERTYPE_FILTERING on fragment stage but sampler doesn't have SG_COMPAREFUNC_NEVER") \ + _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_EXPECTED_NONFILTERING_SAMPLER, "sg_apply_bindings: shader expected SG_SAMPLERTYPE_NONFILTERING on fragment stage, but sampler has SG_FILTER_LINEAR filters") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_UNEXPECTED_SAMPLER_BINDING, "sg_apply_bindings: unexpected sampler binding on fragment stage") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_SMP_EXISTS, "sg_apply_bindings: sampler bound to fragment stage no longer alive") \ _SG_LOGITEM_XMACRO(VALIDATE_ABND_FS_IMG_SMP_MIPMAPS, "sg_apply_bindings: image bound to fragment stage has mipmap_count == 1, but associated sampler mipmap filer is not SG_MIPMAPFILTER_NONE") \ @@ -14976,6 +14982,17 @@ _SOKOL_PRIVATE bool _sg_validate_apply_bindings(const sg_bindings* bindings) { if (img && img->slot.state == SG_RESOURCESTATE_VALID) { _SG_VALIDATE(img->cmn.type == stage->images[i].image_type, VALIDATE_ABND_VS_IMAGE_TYPE_MISMATCH); _SG_VALIDATE(img->cmn.sample_count == 1, VALIDATE_ABND_VS_IMAGE_MSAA); + const sg_pixelformat_info* info = &_sg.formats[img->cmn.pixel_format]; + switch (stage->images[i].sample_type) { + case SG_IMAGESAMPLETYPE_FLOAT: + _SG_VALIDATE(info->filter, VALIDATE_ABND_VS_EXPECTED_FILTERABLE_IMAGE); + break; + case SG_IMAGESAMPLETYPE_DEPTH: + _SG_VALIDATE(info->depth, VALIDATE_ABND_VS_EXPECTED_DEPTH_IMAGE); + break; + default: + break; + } } } } else { @@ -14997,6 +15014,12 @@ _SOKOL_PRIVATE bool _sg_validate_apply_bindings(const sg_bindings* bindings) { } else { _SG_VALIDATE(smp->cmn.compare == SG_COMPAREFUNC_NEVER, VALIDATE_ABND_VS_EXPECTED_SAMPLER_COMPARE_NEVER); } + if (stage->samplers[i].sampler_type == SG_SAMPLERTYPE_NONFILTERING) { + const bool nonfiltering = (smp->cmn.min_filter != SG_FILTER_LINEAR) + && (smp->cmn.mag_filter != SG_FILTER_LINEAR) + && (smp->cmn.mipmap_filter != SG_FILTER_LINEAR); + _SG_VALIDATE(nonfiltering, VALIDATE_ABND_VS_EXPECTED_NONFILTERING_SAMPLER); + } } } } else { @@ -15015,6 +15038,17 @@ _SOKOL_PRIVATE bool _sg_validate_apply_bindings(const sg_bindings* bindings) { if (img && img->slot.state == SG_RESOURCESTATE_VALID) { _SG_VALIDATE(img->cmn.type == stage->images[i].image_type, VALIDATE_ABND_FS_IMAGE_TYPE_MISMATCH); _SG_VALIDATE(img->cmn.sample_count == 1, VALIDATE_ABND_FS_IMAGE_MSAA); + const sg_pixelformat_info* info = &_sg.formats[img->cmn.pixel_format]; + switch (stage->images[i].sample_type) { + case SG_IMAGESAMPLETYPE_FLOAT: + _SG_VALIDATE(info->filter, VALIDATE_ABND_FS_EXPECTED_FILTERABLE_IMAGE); + break; + case SG_IMAGESAMPLETYPE_DEPTH: + _SG_VALIDATE(info->depth, VALIDATE_ABND_FS_EXPECTED_DEPTH_IMAGE); + break; + default: + break; + } } } } else { @@ -15036,6 +15070,12 @@ _SOKOL_PRIVATE bool _sg_validate_apply_bindings(const sg_bindings* bindings) { } else { _SG_VALIDATE(smp->cmn.compare == SG_COMPAREFUNC_NEVER, VALIDATE_ABND_FS_EXPECTED_SAMPLER_COMPARE_NEVER); } + if (stage->samplers[i].sampler_type == SG_SAMPLERTYPE_NONFILTERING) { + const bool nonfiltering = (smp->cmn.min_filter != SG_FILTER_LINEAR) + && (smp->cmn.mag_filter != SG_FILTER_LINEAR) + && (smp->cmn.mipmap_filter != SG_FILTER_LINEAR); + _SG_VALIDATE(nonfiltering, VALIDATE_ABND_FS_EXPECTED_NONFILTERING_SAMPLER); + } } } } else { From b6ab80fc1f59a8600ddca8121cc8d06ef53fcb21 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 6 Sep 2023 18:48:24 +0200 Subject: [PATCH 47/95] fix sokol-gfx tests --- tests/functional/sokol_gfx_test.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/functional/sokol_gfx_test.c b/tests/functional/sokol_gfx_test.c index 1f80b2a0f..4e9e5db5e 100644 --- a/tests/functional/sokol_gfx_test.c +++ b/tests/functional/sokol_gfx_test.c @@ -1064,18 +1064,18 @@ UTEST(sokol_gfx, query_shader_desc) { } }, .images[0] = { .used = true, .image_type = SG_IMAGETYPE_2D, .sample_type = SG_IMAGESAMPLETYPE_FLOAT, .multisampled = true }, - .images[1] = { .used = true, .image_type = SG_IMAGETYPE_3D, .sample_type = SG_IMAGESAMPLETYPE_SINT }, + .images[1] = { .used = true, .image_type = SG_IMAGETYPE_3D, .sample_type = SG_IMAGESAMPLETYPE_DEPTH }, .samplers[0] = { .used = true, .sampler_type = SG_SAMPLERTYPE_FILTERING }, .samplers[1] = { .used = true, .sampler_type = SG_SAMPLERTYPE_COMPARISON }, - .image_sampler_pairs[0] = { .used = true, .image_slot = 0, .sampler_slot = 1, .glsl_name = "img0" }, - .image_sampler_pairs[1] = { .used = true, .image_slot = 1, .sampler_slot = 0, .glsl_name = "img1" }, + .image_sampler_pairs[0] = { .used = true, .image_slot = 0, .sampler_slot = 0, .glsl_name = "img0" }, + .image_sampler_pairs[1] = { .used = true, .image_slot = 1, .sampler_slot = 1, .glsl_name = "img1" }, }, .fs = { .source = "fs_source", .images[0] = { .used = true, .image_type = SG_IMAGETYPE_ARRAY, .sample_type = SG_IMAGESAMPLETYPE_DEPTH }, - .images[1] = { .used = true, .image_type = SG_IMAGETYPE_CUBE, .sample_type = SG_IMAGESAMPLETYPE_FLOAT }, + .images[1] = { .used = true, .image_type = SG_IMAGETYPE_CUBE, .sample_type = SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT }, .samplers[0] = { .used = true, .sampler_type = SG_SAMPLERTYPE_COMPARISON }, - .samplers[1] = { .used = true, .sampler_type = SG_SAMPLERTYPE_FILTERING }, + .samplers[1] = { .used = true, .sampler_type = SG_SAMPLERTYPE_NONFILTERING }, .image_sampler_pairs[0] = { .used = true, .image_slot = 0, .sampler_slot = 0, .glsl_name = "img3" }, .image_sampler_pairs[1] = { .used = true, .image_slot = 1, .sampler_slot = 1, .glsl_name = "img4" }, }, @@ -1097,7 +1097,7 @@ UTEST(sokol_gfx, query_shader_desc) { T(s0_desc.vs.images[0].multisampled); T(s0_desc.vs.images[1].used); T(s0_desc.vs.images[1].image_type == SG_IMAGETYPE_3D); - T(s0_desc.vs.images[1].sample_type == SG_IMAGESAMPLETYPE_SINT); + T(s0_desc.vs.images[1].sample_type == SG_IMAGESAMPLETYPE_DEPTH); T(s0_desc.vs.images[1].multisampled == false); T(s0_desc.vs.samplers[0].used); T(s0_desc.vs.samplers[0].sampler_type == SG_SAMPLERTYPE_FILTERING); @@ -1105,11 +1105,11 @@ UTEST(sokol_gfx, query_shader_desc) { T(s0_desc.vs.samplers[1].sampler_type == SG_SAMPLERTYPE_COMPARISON); T(s0_desc.vs.image_sampler_pairs[0].used); T(s0_desc.vs.image_sampler_pairs[0].image_slot == 0); - T(s0_desc.vs.image_sampler_pairs[0].sampler_slot == 1); + T(s0_desc.vs.image_sampler_pairs[0].sampler_slot == 0); T(s0_desc.vs.image_sampler_pairs[0].glsl_name == 0); T(s0_desc.vs.image_sampler_pairs[1].used); T(s0_desc.vs.image_sampler_pairs[1].image_slot == 1); - T(s0_desc.vs.image_sampler_pairs[1].sampler_slot == 0); + T(s0_desc.vs.image_sampler_pairs[1].sampler_slot == 1); T(s0_desc.vs.image_sampler_pairs[1].glsl_name == 0); T(s0_desc.fs.source == 0); T(s0_desc.fs.uniform_blocks[0].size == 0); @@ -1123,12 +1123,12 @@ UTEST(sokol_gfx, query_shader_desc) { T(s0_desc.fs.images[0].multisampled == false); T(s0_desc.fs.images[1].used); T(s0_desc.fs.images[1].image_type == SG_IMAGETYPE_CUBE); - T(s0_desc.fs.images[1].sample_type == SG_IMAGESAMPLETYPE_FLOAT); + T(s0_desc.fs.images[1].sample_type == SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT); T(s0_desc.fs.images[1].multisampled == false); T(s0_desc.fs.samplers[0].used); T(s0_desc.fs.samplers[0].sampler_type == SG_SAMPLERTYPE_COMPARISON); T(s0_desc.fs.samplers[1].used); - T(s0_desc.fs.samplers[1].sampler_type == SG_SAMPLERTYPE_FILTERING); + T(s0_desc.fs.samplers[1].sampler_type == SG_SAMPLERTYPE_NONFILTERING); T(s0_desc.fs.image_sampler_pairs[0].used); T(s0_desc.fs.image_sampler_pairs[0].image_slot == 0); T(s0_desc.fs.image_sampler_pairs[0].sampler_slot == 0); From 2d9e4bfe63cfafcded0ccb27d66c9d5c0cb578ad Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 7 Sep 2023 18:10:58 +0200 Subject: [PATCH 48/95] sokoL_imgui.h: allow unfilterable user images --- util/sokol_imgui.h | 210 ++++++++++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 90 deletions(-) diff --git a/util/sokol_imgui.h b/util/sokol_imgui.h index 51ad4eb52..786f98536 100644 --- a/util/sokol_imgui.h +++ b/util/sokol_imgui.h @@ -639,6 +639,7 @@ typedef struct { _simgui_slot_t slot; sg_image image; sg_sampler sampler; + sg_pipeline pip; // this will either be _simgui.def_pip or _simgui.pip_unfilterable } _simgui_image_t; typedef struct { @@ -657,8 +658,11 @@ typedef struct { simgui_image_t default_font; sg_image def_img; // used as default image for user images sg_sampler def_smp; // used as default sampler for user images - sg_shader shd; - sg_pipeline pip; + sg_shader def_shd; + sg_pipeline def_pip; + // separate shader and pipeline for unfilterable user images + sg_shader shd_unfilterable; + sg_pipeline pip_unfilterable; sg_range vertices; sg_range indices; bool is_osx; @@ -2081,8 +2085,15 @@ static simgui_image_t _simgui_alloc_image(void) { static _simgui_resource_state _simgui_init_image(_simgui_image_t* img, const simgui_image_desc_t* desc) { SOKOL_ASSERT(img && (img->slot.state == _SIMGUI_RESOURCESTATE_ALLOC)); SOKOL_ASSERT(desc); + SOKOL_ASSERT(_simgui.def_pip.id != SIMGUI_INVALID_ID); + SOKOL_ASSERT(_simgui.pip_unfilterable.id != SIMGUI_INVALID_ID); img->image = desc->image; img->sampler = desc->sampler; + if (sg_query_pixelformat(sg_query_image_desc(desc->image).pixel_format).filter) { + img->pip = _simgui.def_pip; + } else { + img->pip = _simgui.pip_unfilterable; + } return _SIMGUI_RESOURCESTATE_VALID; } @@ -2090,6 +2101,7 @@ static void _simgui_deinit_image(_simgui_image_t* img) { SOKOL_ASSERT(img); img->image.id = SIMGUI_INVALID_ID; img->sampler.id = SIMGUI_INVALID_ID; + img->pip.id = SIMGUI_INVALID_ID; } static void _simgui_destroy_image(simgui_image_t img_id) { @@ -2198,84 +2210,6 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) { // create sokol-gfx resources sg_push_debug_group("sokol-imgui"); - // NOTE: since we're in C++ mode here we can't use C99 designated init - sg_buffer_desc vb_desc; - _simgui_clear(&vb_desc, sizeof(vb_desc)); - vb_desc.usage = SG_USAGE_STREAM; - vb_desc.size = _simgui.vertices.size; - vb_desc.label = "sokol-imgui-vertices"; - _simgui.vbuf = sg_make_buffer(&vb_desc); - - sg_buffer_desc ib_desc; - _simgui_clear(&ib_desc, sizeof(ib_desc)); - ib_desc.type = SG_BUFFERTYPE_INDEXBUFFER; - ib_desc.usage = SG_USAGE_STREAM; - ib_desc.size = _simgui.indices.size; - ib_desc.label = "sokol-imgui-indices"; - _simgui.ibuf = sg_make_buffer(&ib_desc); - - // a default font sampler - sg_sampler_desc font_smp_desc; - _simgui_clear(&font_smp_desc, sizeof(font_smp_desc)); - font_smp_desc.wrap_u = SG_WRAP_CLAMP_TO_EDGE; - font_smp_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE; - font_smp_desc.min_filter = SG_FILTER_LINEAR; - font_smp_desc.mag_filter = SG_FILTER_LINEAR; - font_smp_desc.mipmap_filter = SG_FILTER_NONE; - font_smp_desc.label = "sokol-imgui-font-sampler"; - _simgui.font_smp = sg_make_sampler(&font_smp_desc); - - // a default user-image sampler - sg_sampler_desc def_sampler_desc; - _simgui_clear(&def_sampler_desc, sizeof(def_sampler_desc)); - def_sampler_desc.min_filter = SG_FILTER_NEAREST; - def_sampler_desc.mag_filter = SG_FILTER_NEAREST; - def_sampler_desc.wrap_u = SG_WRAP_CLAMP_TO_EDGE; - def_sampler_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE; - def_sampler_desc.label = "sokol-imgui-default-sampler"; - _simgui.def_smp = sg_make_sampler(&def_sampler_desc); - - // default font texture - if (!_simgui.desc.no_default_font) { - unsigned char* font_pixels; - int font_width, font_height; - #if defined(__cplusplus) - io->Fonts->GetTexDataAsRGBA32(&font_pixels, &font_width, &font_height); - #else - int bytes_per_pixel; - ImFontAtlas_GetTexDataAsRGBA32(io->Fonts, &font_pixels, &font_width, &font_height, &bytes_per_pixel); - #endif - sg_image_desc font_img_desc; - _simgui_clear(&font_img_desc, sizeof(font_img_desc)); - font_img_desc.width = font_width; - font_img_desc.height = font_height; - font_img_desc.pixel_format = SG_PIXELFORMAT_RGBA8; - font_img_desc.data.subimage[0][0].ptr = font_pixels; - font_img_desc.data.subimage[0][0].size = (size_t)(font_width * font_height) * sizeof(uint32_t); - font_img_desc.label = "sokol-imgui-font-image"; - _simgui.font_img = sg_make_image(&font_img_desc); - - simgui_image_desc_t img_desc; - _simgui_clear(&img_desc, sizeof(img_desc)); - img_desc.image = _simgui.font_img; - img_desc.sampler = _simgui.font_smp; - _simgui.default_font = simgui_make_image(&img_desc); - io->Fonts->TexID = simgui_imtextureid(_simgui.default_font); - } - - // a default user image - static uint32_t def_pixels[64]; - memset(def_pixels, 0xFF, sizeof(def_pixels)); - sg_image_desc def_image_desc; - _simgui_clear(&def_image_desc, sizeof(def_image_desc)); - def_image_desc.width = 8; - def_image_desc.height = 8; - def_image_desc.pixel_format = SG_PIXELFORMAT_RGBA8; - def_image_desc.data.subimage[0][0].ptr = def_pixels; - def_image_desc.data.subimage[0][0].size = sizeof(def_pixels); - def_image_desc.label = "sokol-imgui-default-image"; - _simgui.def_img = sg_make_image(&def_image_desc); - // shader object for using the embedded shader source (or bytecode) sg_shader_desc shd_desc; _simgui_clear(&shd_desc, sizeof(shd_desc)); @@ -2336,7 +2270,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) { shd_desc.vs.source = _simgui_vs_source_dummy; shd_desc.fs.source = _simgui_fs_source_dummy; #endif - _simgui.shd = sg_make_shader(&shd_desc); + _simgui.def_shd = sg_make_shader(&shd_desc); // pipeline object for imgui rendering sg_pipeline_desc pip_desc; @@ -2357,7 +2291,7 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) { attr->offset = offsetof(ImDrawVert, col); attr->format = SG_VERTEXFORMAT_UBYTE4N; } - pip_desc.shader = _simgui.shd; + pip_desc.shader = _simgui.def_shd; pip_desc.index_type = SG_INDEXTYPE_UINT16; pip_desc.sample_count = _simgui.desc.sample_count; pip_desc.depth.pixel_format = _simgui.desc.depth_format; @@ -2371,7 +2305,94 @@ SOKOL_API_IMPL void simgui_setup(const simgui_desc_t* desc) { pip_desc.colors[0].blend.dst_factor_alpha = SG_BLENDFACTOR_ONE; } pip_desc.label = "sokol-imgui-pipeline"; - _simgui.pip = sg_make_pipeline(&pip_desc); + _simgui.def_pip = sg_make_pipeline(&pip_desc); + + // create a unfilterable/nonfiltering variants of the shader and pipeline + shd_desc.fs.images[0].sample_type = SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT; + shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_NONFILTERING; + shd_desc.label = "sokol-imgui-shader-unfilterable"; + _simgui.shd_unfilterable = sg_make_shader(&shd_desc); + pip_desc.shader = _simgui.shd_unfilterable; + pip_desc.label = "sokol-imgui-pipeline-unfilterable"; + _simgui.pip_unfilterable = sg_make_pipeline(&pip_desc); + + // NOTE: since we're in C++ mode here we can't use C99 designated init + sg_buffer_desc vb_desc; + _simgui_clear(&vb_desc, sizeof(vb_desc)); + vb_desc.usage = SG_USAGE_STREAM; + vb_desc.size = _simgui.vertices.size; + vb_desc.label = "sokol-imgui-vertices"; + _simgui.vbuf = sg_make_buffer(&vb_desc); + + sg_buffer_desc ib_desc; + _simgui_clear(&ib_desc, sizeof(ib_desc)); + ib_desc.type = SG_BUFFERTYPE_INDEXBUFFER; + ib_desc.usage = SG_USAGE_STREAM; + ib_desc.size = _simgui.indices.size; + ib_desc.label = "sokol-imgui-indices"; + _simgui.ibuf = sg_make_buffer(&ib_desc); + + // a default font sampler + sg_sampler_desc font_smp_desc; + _simgui_clear(&font_smp_desc, sizeof(font_smp_desc)); + font_smp_desc.wrap_u = SG_WRAP_CLAMP_TO_EDGE; + font_smp_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE; + font_smp_desc.min_filter = SG_FILTER_LINEAR; + font_smp_desc.mag_filter = SG_FILTER_LINEAR; + font_smp_desc.mipmap_filter = SG_FILTER_NONE; + font_smp_desc.label = "sokol-imgui-font-sampler"; + _simgui.font_smp = sg_make_sampler(&font_smp_desc); + + // a default user-image sampler + sg_sampler_desc def_sampler_desc; + _simgui_clear(&def_sampler_desc, sizeof(def_sampler_desc)); + def_sampler_desc.min_filter = SG_FILTER_NEAREST; + def_sampler_desc.mag_filter = SG_FILTER_NEAREST; + def_sampler_desc.wrap_u = SG_WRAP_CLAMP_TO_EDGE; + def_sampler_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE; + def_sampler_desc.label = "sokol-imgui-default-sampler"; + _simgui.def_smp = sg_make_sampler(&def_sampler_desc); + + // a default user image + static uint32_t def_pixels[64]; + memset(def_pixels, 0xFF, sizeof(def_pixels)); + sg_image_desc def_image_desc; + _simgui_clear(&def_image_desc, sizeof(def_image_desc)); + def_image_desc.width = 8; + def_image_desc.height = 8; + def_image_desc.pixel_format = SG_PIXELFORMAT_RGBA8; + def_image_desc.data.subimage[0][0].ptr = def_pixels; + def_image_desc.data.subimage[0][0].size = sizeof(def_pixels); + def_image_desc.label = "sokol-imgui-default-image"; + _simgui.def_img = sg_make_image(&def_image_desc); + + // default font texture + if (!_simgui.desc.no_default_font) { + unsigned char* font_pixels; + int font_width, font_height; + #if defined(__cplusplus) + io->Fonts->GetTexDataAsRGBA32(&font_pixels, &font_width, &font_height); + #else + int bytes_per_pixel; + ImFontAtlas_GetTexDataAsRGBA32(io->Fonts, &font_pixels, &font_width, &font_height, &bytes_per_pixel); + #endif + sg_image_desc font_img_desc; + _simgui_clear(&font_img_desc, sizeof(font_img_desc)); + font_img_desc.width = font_width; + font_img_desc.height = font_height; + font_img_desc.pixel_format = SG_PIXELFORMAT_RGBA8; + font_img_desc.data.subimage[0][0].ptr = font_pixels; + font_img_desc.data.subimage[0][0].size = (size_t)(font_width * font_height) * sizeof(uint32_t); + font_img_desc.label = "sokol-imgui-font-image"; + _simgui.font_img = sg_make_image(&font_img_desc); + + simgui_image_desc_t img_desc; + _simgui_clear(&img_desc, sizeof(img_desc)); + img_desc.image = _simgui.font_img; + img_desc.sampler = _simgui.font_smp; + _simgui.default_font = simgui_make_image(&img_desc); + io->Fonts->TexID = simgui_imtextureid(_simgui.default_font); + } sg_pop_debug_group(); } @@ -2384,8 +2405,10 @@ SOKOL_API_IMPL void simgui_shutdown(void) { igDestroyContext(0); #endif // NOTE: it's valid to call the destroy funcs with SG_INVALID_ID - sg_destroy_pipeline(_simgui.pip); - sg_destroy_shader(_simgui.shd); + sg_destroy_pipeline(_simgui.pip_unfilterable); + sg_destroy_shader(_simgui.shd_unfilterable); + sg_destroy_pipeline(_simgui.def_pip); + sg_destroy_shader(_simgui.def_shd); sg_destroy_sampler(_simgui.font_smp); sg_destroy_image(_simgui.font_img); sg_destroy_sampler(_simgui.def_smp); @@ -2496,8 +2519,8 @@ SOKOL_API_IMPL void simgui_new_frame(const simgui_frame_desc_t* desc) { #endif } -static void _simgui_bind_image_sampler(sg_bindings* bindings, ImTextureID tex_id) { - _simgui_image_t* img = _simgui_lookup_image((uint32_t)(uintptr_t)tex_id); +static const _simgui_image_t* _simgui_bind_image_sampler(sg_bindings* bindings, ImTextureID tex_id) { + const _simgui_image_t* img = _simgui_lookup_image((uint32_t)(uintptr_t)tex_id); if (img) { bindings->fs.images[0] = img->image; bindings->fs.samplers[0] = img->sampler; @@ -2505,6 +2528,7 @@ static void _simgui_bind_image_sampler(sg_bindings* bindings, ImTextureID tex_id bindings->fs.images[0] = _simgui.def_img; bindings->fs.samplers[0] = _simgui.def_smp; } + return img; } SOKOL_API_IMPL void simgui_render(void) { @@ -2583,7 +2607,7 @@ SOKOL_API_IMPL void simgui_render(void) { sg_apply_viewport(0, 0, fb_width, fb_height, true); sg_apply_scissor_rect(0, 0, fb_width, fb_height, true); - sg_apply_pipeline(_simgui.pip); + sg_apply_pipeline(_simgui.def_pip); _simgui_vs_params_t vs_params; _simgui_clear((void*)&vs_params, sizeof(vs_params)); vs_params.disp_size.x = io->DisplaySize.x; @@ -2616,14 +2640,20 @@ SOKOL_API_IMPL void simgui_render(void) { pcmd->UserCallback(cl, pcmd); // need to re-apply all state after calling a user callback sg_apply_viewport(0, 0, fb_width, fb_height, true); - sg_apply_pipeline(_simgui.pip); + sg_apply_pipeline(_simgui.def_pip); sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(vs_params)); sg_apply_bindings(&bind); } else { if ((tex_id != pcmd->TextureId) || (vtx_offset != pcmd->VtxOffset)) { tex_id = pcmd->TextureId; vtx_offset = pcmd->VtxOffset; - _simgui_bind_image_sampler(&bind, tex_id); + const _simgui_image_t* img = _simgui_bind_image_sampler(&bind, tex_id); + if (img) { + sg_apply_pipeline(img->pip); + } else { + sg_apply_pipeline(_simgui.def_pip); + } + sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(vs_params)); bind.vertex_buffer_offsets[0] = vb_offset + (int)(pcmd->VtxOffset * sizeof(ImDrawVert)); sg_apply_bindings(&bind); } From c98be285e73c39e785e65dc8048e79d4a2a0edc8 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 9 Sep 2023 18:58:16 +0200 Subject: [PATCH 49/95] sokol_gfx.h: fix cubemap creation --- sokol_gfx.h | 87 +++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 0cb8f76ae..17aa68f95 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12641,36 +12641,40 @@ _SOKOL_PRIVATE void _sg_wgpu_copy_image_data(const _sg_image_t* img, WGPUTexture wgpu_copy_tex.aspect = WGPUTextureAspect_All; WGPUExtent3D wgpu_extent; _sg_clear(&wgpu_extent, sizeof(wgpu_extent)); - for (int mip_level = 0; mip_level < img->cmn.num_mipmaps; mip_level++) { - wgpu_copy_tex.mipLevel = (uint32_t)mip_level; - int mip_width = _sg_miplevel_dim(img->cmn.width, mip_level); - int mip_height = _sg_miplevel_dim(img->cmn.height, mip_level); - int mip_slices; - switch (img->cmn.type) { - case SG_IMAGETYPE_CUBE: - mip_slices = 6; - break; - case SG_IMAGETYPE_3D: - mip_slices = _sg_miplevel_dim(img->cmn.num_slices, mip_level); - break; - default: - mip_slices = img->cmn.num_slices; - break; - } - const int row_pitch = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1); - const int num_rows = _sg_num_rows(img->cmn.pixel_format, mip_height); - if (_sg_is_compressed_pixel_format(img->cmn.pixel_format)) { - mip_width = _sg_roundup(mip_width, 4); - mip_height = _sg_roundup(mip_height, 4); + const int num_faces = (img->cmn.type == SG_IMAGETYPE_CUBE) ? 6 : 1; + for (int face_index = 0; face_index < num_faces; face_index++) { + for (int mip_index = 0; mip_index < img->cmn.num_mipmaps; mip_index++) { + wgpu_copy_tex.mipLevel = (uint32_t)mip_index; + wgpu_copy_tex.origin.z = (uint32_t)face_index; + int mip_width = _sg_miplevel_dim(img->cmn.width, mip_index); + int mip_height = _sg_miplevel_dim(img->cmn.height, mip_index); + int mip_slices; + switch (img->cmn.type) { + case SG_IMAGETYPE_CUBE: + mip_slices = 1; + break; + case SG_IMAGETYPE_3D: + mip_slices = _sg_miplevel_dim(img->cmn.num_slices, mip_index); + break; + default: + mip_slices = img->cmn.num_slices; + break; + } + const int row_pitch = _sg_row_pitch(img->cmn.pixel_format, mip_width, 1); + const int num_rows = _sg_num_rows(img->cmn.pixel_format, mip_height); + if (_sg_is_compressed_pixel_format(img->cmn.pixel_format)) { + mip_width = _sg_roundup(mip_width, 4); + mip_height = _sg_roundup(mip_height, 4); + } + wgpu_layout.offset = 0; + wgpu_layout.bytesPerRow = (uint32_t)row_pitch; + wgpu_layout.rowsPerImage = (uint32_t)num_rows; + wgpu_extent.width = (uint32_t)mip_width; + wgpu_extent.height = (uint32_t)mip_height; + wgpu_extent.depthOrArrayLayers = (uint32_t)mip_slices; + const sg_range* mip_data = &data->subimage[face_index][mip_index]; + wgpuQueueWriteTexture(_sg.wgpu.queue, &wgpu_copy_tex, mip_data->ptr, mip_data->size, &wgpu_layout, &wgpu_extent); } - wgpu_layout.offset = 0; - wgpu_layout.bytesPerRow = (uint32_t)row_pitch; - wgpu_layout.rowsPerImage = (uint32_t)num_rows; - wgpu_extent.width = (uint32_t)mip_width; - wgpu_extent.height = (uint32_t)mip_height; - wgpu_extent.depthOrArrayLayers = (uint32_t)mip_slices; - const sg_range* mip_data = &data->subimage[0][mip_level]; - wgpuQueueWriteTexture(_sg.wgpu.queue, &wgpu_copy_tex, mip_data->ptr, mip_data->size, &wgpu_layout, &wgpu_extent); } } @@ -12688,13 +12692,17 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s if (desc->render_target) { wgpu_tex_desc.usage |= WGPUTextureUsage_RenderAttachment; } - wgpu_tex_desc.dimension = _sg_wgpu_texture_dimension(desc->type); - wgpu_tex_desc.size.width = (uint32_t) desc->width; - wgpu_tex_desc.size.height = (uint32_t) desc->height; - wgpu_tex_desc.size.depthOrArrayLayers = (uint32_t) desc->num_slices; - wgpu_tex_desc.format = _sg_wgpu_textureformat(desc->pixel_format); - wgpu_tex_desc.mipLevelCount = (uint32_t) desc->num_mipmaps; - wgpu_tex_desc.sampleCount = (uint32_t) desc->sample_count; + wgpu_tex_desc.dimension = _sg_wgpu_texture_dimension(img->cmn.type); + wgpu_tex_desc.size.width = (uint32_t) img->cmn.width; + wgpu_tex_desc.size.height = (uint32_t) img->cmn.height; + if (desc->type == SG_IMAGETYPE_CUBE) { + wgpu_tex_desc.size.depthOrArrayLayers = 6; + } else { + wgpu_tex_desc.size.depthOrArrayLayers = (uint32_t) img->cmn.num_slices; + } + wgpu_tex_desc.format = _sg_wgpu_textureformat(img->cmn.pixel_format); + wgpu_tex_desc.mipLevelCount = (uint32_t) img->cmn.num_mipmaps; + wgpu_tex_desc.sampleCount = (uint32_t) img->cmn.sample_count; img->wgpu.tex = wgpuDeviceCreateTexture(_sg.wgpu.dev, &wgpu_tex_desc); if (0 == img->wgpu.tex) { _SG_ERROR(WGPU_CREATE_TEXTURE_FAILED); @@ -12709,11 +12717,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s wgpu_texview_desc.label = desc->label; wgpu_texview_desc.dimension = _sg_wgpu_texture_view_dimension(img->cmn.type); wgpu_texview_desc.mipLevelCount = (uint32_t)img->cmn.num_mipmaps; - // FIXME: cubemap?? - if (img->cmn.type == SG_IMAGETYPE_ARRAY) { - wgpu_texview_desc.arrayLayerCount = (uint32_t)img->cmn.num_slices; + if (img->cmn.type == SG_IMAGETYPE_CUBE) { + wgpu_texview_desc.arrayLayerCount = 6; } else { - wgpu_texview_desc.arrayLayerCount = 1; + wgpu_texview_desc.arrayLayerCount = (uint32_t)img->cmn.num_slices; } // FIXME: should aspect be DepthOnly for all depth texture formats? wgpu_texview_desc.aspect = WGPUTextureAspect_All; From 681eb7801ce2431d8d2e6d457c159a3864195dc6 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 11 Sep 2023 17:49:30 +0200 Subject: [PATCH 50/95] sokol_gfx.h wgpu: add a fixme comment in _sg_wgpu_apply_uniforms() --- sokol_gfx.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sokol_gfx.h b/sokol_gfx.h index 17aa68f95..e4f7c5493 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -13385,6 +13385,8 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ SOKOL_ASSERT(data->size <= _sg.wgpu.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size); SOKOL_ASSERT(data->size <= _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); + // FIXME: memcpy into an intermediate memory buffer here, and do a single big + // wgpuQueueWriteBuffer at the end of the frame wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, _sg.wgpu.uniform.offset, data->ptr, data->size); _sg.wgpu.uniform.bind.offsets[stage_index][ub_index] = _sg.wgpu.uniform.offset; wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, From f6bdb52aa52829af10231eb605d9b5a6dbe5383b Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 12 Sep 2023 18:07:42 +0200 Subject: [PATCH 51/95] sokol_gfx.h wgpu: call wgpuBufferDestroy and wgpuTextureDestroy before the Release() call --- sokol_gfx.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index e4f7c5493..b9c4aa278 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12608,6 +12608,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_buffer(_sg_buffer_t* buf, const _SOKOL_PRIVATE void _sg_wgpu_discard_buffer(_sg_buffer_t* buf) { SOKOL_ASSERT(buf); if (buf->wgpu.buf) { + wgpuBufferDestroy(buf->wgpu.buf); wgpuBufferRelease(buf->wgpu.buf); } } @@ -12734,14 +12735,15 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s _SOKOL_PRIVATE void _sg_wgpu_discard_image(_sg_image_t* img) { SOKOL_ASSERT(img); - if (img->wgpu.tex) { - wgpuTextureRelease(img->wgpu.tex); - img->wgpu.tex = 0; - } if (img->wgpu.view) { wgpuTextureViewRelease(img->wgpu.view); img->wgpu.view = 0; } + if (img->wgpu.tex) { + wgpuTextureDestroy(img->wgpu.tex); + wgpuTextureRelease(img->wgpu.tex); + img->wgpu.tex = 0; + } } _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_sampler(_sg_sampler_t* smp, const sg_sampler_desc* desc) { From dd4c3cf43c4701f1648bd1105cde7ee51d6df849 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 12 Sep 2023 20:21:02 +0200 Subject: [PATCH 52/95] sokol_gfx.h wgpu: don't issue redundant vertex- and index-buffer binding calls --- sokol_gfx.h | 76 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index b9c4aa278..7146a92da 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4929,6 +4929,16 @@ typedef struct { const _sg_pipeline_t* cur_pipeline; sg_pipeline cur_pipeline_id; _sg_wgpu_uniform_buffer_t uniform; + struct { + struct { + sg_buffer buffer; + int offset; + } vbs[SG_MAX_VERTEX_BUFFERS]; + struct { + sg_buffer buffer; + int offset; + } ib; + } bindcache; } _sg_wgpu_backend_t; #endif @@ -5352,7 +5362,7 @@ _SOKOL_PRIVATE int _sg_roundup(int val, int round_to) { return (val+(round_to-1)) & ~(round_to-1); } -_SOKOL_PRIVATE uint64_t _sg_roundup_u32(uint32_t val, uint32_t round_to) { +_SOKOL_PRIVATE uint32_t _sg_roundup_u32(uint32_t val, uint32_t round_to) { return (val+(round_to-1)) & ~(round_to-1); } @@ -12497,6 +12507,32 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { _sg_clear(&_sg.wgpu.uniform.bind.offsets[0][0], sizeof(_sg.wgpu.uniform.bind.offsets)); } +_SOKOL_PRIVATE void _sg_wgpu_bindcache_clear(void) { + memset(&_sg.wgpu.bindcache, 0, sizeof(_sg.wgpu.bindcache)); +} + +_SOKOL_PRIVATE bool _sg_wgpu_bindcache_vb_dirty(int index, const _sg_buffer_t* vb, int offset) { + SOKOL_ASSERT(vb && (index >= 0) && (index < SG_MAX_VERTEX_BUFFERS)); + return (vb->slot.id != _sg.wgpu.bindcache.vbs[index].buffer.id) || (offset != _sg.wgpu.bindcache.vbs[index].offset); +} + +_SOKOL_PRIVATE void _sg_wgpu_bindcache_vb_update(int index, const _sg_buffer_t* vb, int offset) { + SOKOL_ASSERT(vb && (index >= 0) && (index < SG_MAX_VERTEX_BUFFERS)); + _sg.wgpu.bindcache.vbs[index].buffer.id = vb->slot.id; + _sg.wgpu.bindcache.vbs[index].offset = offset; +} + +_SOKOL_PRIVATE bool _sg_wgpu_bindcache_ib_dirty(const _sg_buffer_t* ib, int ib_offset) { + SOKOL_ASSERT(ib); + return (ib->slot.id != _sg.wgpu.bindcache.ib.buffer.id) || (ib_offset != _sg.wgpu.bindcache.ib.offset); +} + +_SOKOL_PRIVATE void _sg_wgpu_bindcache_ib_update(const _sg_buffer_t* ib, int ib_offset) { + SOKOL_ASSERT(ib); + _sg.wgpu.bindcache.ib.buffer.id = ib->slot.id; + _sg.wgpu.bindcache.ib.offset = ib_offset; +} + _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { SOKOL_ASSERT(desc); SOKOL_ASSERT(desc->context.wgpu.device); @@ -12517,6 +12553,7 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg.wgpu.queue = wgpuDeviceGetQueue(_sg.wgpu.dev); SOKOL_ASSERT(_sg.wgpu.queue); + _sg_wgpu_bindcache_clear(); _sg_wgpu_init_caps(); _sg_wgpu_uniform_buffer_init(desc); @@ -12927,7 +12964,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_pipeline(_sg_pipeline_t* pip, _ const int vb_idx = va_state->buffer_index; SOKOL_ASSERT(vb_idx < SG_MAX_VERTEX_BUFFERS); pip->cmn.vertex_buffer_layout_active[vb_idx] = true; - const uint32_t wgpu_attr_idx = wgpu_vb_layouts[vb_idx].attributeCount; + const size_t wgpu_attr_idx = wgpu_vb_layouts[vb_idx].attributeCount; wgpu_vb_layouts[vb_idx].attributeCount += 1; wgpu_vtx_attrs[vb_idx][wgpu_attr_idx].format = _sg_wgpu_vertexformat(va_state->format); wgpu_vtx_attrs[vb_idx][wgpu_attr_idx].offset = (uint64_t)va_state->offset; @@ -13166,6 +13203,7 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* _sg.wgpu.cur_height = h; _sg.wgpu.cur_pipeline = 0; _sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID; + _sg_wgpu_bindcache_clear(); WGPURenderPassDescriptor wgpu_pass_desc; WGPURenderPassColorAttachment wgpu_color_att[SG_MAX_COLOR_ATTACHMENTS]; @@ -13344,21 +13382,29 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_bindings( // index buffer if (ib) { - const WGPUIndexFormat format = _sg_wgpu_indexformat(pip->cmn.index_type); - const uint64_t buf_size = (uint64_t)ib->cmn.size; - const uint64_t offset = (uint64_t)ib_offset; - SOKOL_ASSERT(buf_size > offset); - const uint64_t max_bytes = buf_size - offset; - wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, ib->wgpu.buf, format, offset, max_bytes); + if (_sg_wgpu_bindcache_ib_dirty(ib, ib_offset)) { + _sg_wgpu_bindcache_ib_update(ib, ib_offset); + const WGPUIndexFormat format = _sg_wgpu_indexformat(pip->cmn.index_type); + const uint64_t buf_size = (uint64_t)ib->cmn.size; + const uint64_t offset = (uint64_t)ib_offset; + SOKOL_ASSERT(buf_size > offset); + const uint64_t max_bytes = buf_size - offset; + wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, ib->wgpu.buf, format, offset, max_bytes); + } } + // FIXME: else-path should actually set a null index buffer (this was just recently implemented in WebGPU) // vertex buffers - for (uint32_t slot = 0; slot < (uint32_t)num_vbs; slot++) { - const uint64_t buf_size = (uint64_t)vbs[slot]->cmn.size; - const uint64_t offset = (uint64_t)vb_offsets[slot]; - SOKOL_ASSERT(buf_size > offset); - const uint64_t max_bytes = buf_size - offset; - wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, slot, vbs[slot]->wgpu.buf, offset, max_bytes); + for (int slot = 0; slot < num_vbs; slot++) { + if (_sg_wgpu_bindcache_vb_dirty(slot, vbs[slot], vb_offsets[slot])) { + _sg_wgpu_bindcache_vb_update(slot, vbs[slot], vb_offsets[slot]); + const uint64_t buf_size = (uint64_t)vbs[slot]->cmn.size; + const uint64_t offset = (uint64_t)vb_offsets[slot]; + SOKOL_ASSERT(buf_size > offset); + const uint64_t max_bytes = buf_size - offset; + wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, (uint32_t)slot, vbs[slot]->wgpu.buf, offset, max_bytes); + } + // FIXME: else-path should actually set a null vertex buffer (this was just recently implemented in WebGPU) } // FIXME: create adhoc bind group object for images and samplers @@ -13396,7 +13442,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ _sg.wgpu.uniform.bind.group, SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS, &_sg.wgpu.uniform.bind.offsets[0][0]); - _sg.wgpu.uniform.offset = _sg_roundup_u32(_sg.wgpu.uniform.offset + data->size, alignment); + _sg.wgpu.uniform.offset = _sg_roundup_u32(_sg.wgpu.uniform.offset + (uint32_t)data->size, alignment); } _SOKOL_PRIVATE void _sg_wgpu_draw(int base_element, int num_elements, int num_instances) { From f6a2bfd335618c8c1fa0fde11d08255709d8b83a Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 16 Sep 2023 16:29:03 +0200 Subject: [PATCH 53/95] sokol_gfx.h wgpu: only do one writeBuffer per frame for uniform data --- sokol_gfx.h | 47 +++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 7146a92da..a96eaa857 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4898,6 +4898,7 @@ typedef _sg_wgpu_context_t _sg_context_t; typedef struct { uint32_t num_bytes; uint32_t offset; // current offset into buf + uint8_t* stage; // intermediate buffer for uniform data updates WGPUBuffer buf; // the GPU-side uniform buffer struct { WGPUBindGroupLayout group_layout; @@ -4906,6 +4907,17 @@ typedef struct { } bind; } _sg_wgpu_uniform_buffer_t; +typedef struct { + struct { + sg_buffer buffer; + int offset; + } vbs[SG_MAX_VERTEX_BUFFERS]; + struct { + sg_buffer buffer; + int offset; + } ib; +} _sg_wgpu_bindcache_t; + // the WGPU backend state typedef struct { bool valid; @@ -4929,16 +4941,7 @@ typedef struct { const _sg_pipeline_t* cur_pipeline; sg_pipeline cur_pipeline_id; _sg_wgpu_uniform_buffer_t uniform; - struct { - struct { - sg_buffer buffer; - int offset; - } vbs[SG_MAX_VERTEX_BUFFERS]; - struct { - sg_buffer buffer; - int offset; - } ib; - } bindcache; + _sg_wgpu_bindcache_t bindcache; } _sg_wgpu_backend_t; #endif @@ -12424,6 +12427,11 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { } _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_init(const sg_desc* desc) { + SOKOL_ASSERT(0 == _sg.wgpu.uniform.stage); + SOKOL_ASSERT(0 == _sg.wgpu.uniform.buf); + SOKOL_ASSERT(0 == _sg.wgpu.uniform.bind.group_layout); + SOKOL_ASSERT(0 == _sg.wgpu.uniform.bind.group); + // Add the max-uniform-update size (64 KB) to the requested buffer size, // this is to prevent validation errors in the WebGPU implementation // if the entire buffer size is used per frame. 64 KB is the allowed @@ -12431,6 +12439,7 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_init(const sg_desc* desc) { // // FIXME: is this still needed? _sg.wgpu.uniform.num_bytes = (uint32_t)(desc->uniform_buffer_size + _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); + _sg.wgpu.uniform.stage = (uint8_t*)_sg_malloc(_sg.wgpu.uniform.num_bytes); WGPUBufferDescriptor ub_desc; _sg_clear(&ub_desc, sizeof(ub_desc)); @@ -12491,6 +12500,10 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_discard(void) { wgpuBindGroupLayoutRelease(_sg.wgpu.uniform.bind.group_layout); _sg.wgpu.uniform.bind.group_layout = 0; } + if (_sg.wgpu.uniform.stage) { + _sg_free(_sg.wgpu.uniform.stage); + _sg.wgpu.uniform.stage = 0; + } } _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_begin_pass(void) { @@ -12502,7 +12515,7 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_begin_pass(void) { } _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { - // clear offsets + wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, 0, _sg.wgpu.uniform.stage, _sg.wgpu.uniform.offset); _sg.wgpu.uniform.offset = 0; _sg_clear(&_sg.wgpu.uniform.bind.offsets[0][0], sizeof(_sg.wgpu.uniform.bind.offsets)); } @@ -13254,6 +13267,8 @@ _SOKOL_PRIVATE void _sg_wgpu_commit(void) { SOKOL_ASSERT(!_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.cmd_enc); + _sg_wgpu_uniform_buffer_on_commit(); + WGPUCommandBufferDescriptor cmd_buf_desc; _sg_clear(&cmd_buf_desc, sizeof(cmd_buf_desc)); WGPUCommandBuffer wgpu_cmd_buf = wgpuCommandEncoderFinish(_sg.wgpu.cmd_enc, &cmd_buf_desc); @@ -13268,9 +13283,6 @@ _SOKOL_PRIVATE void _sg_wgpu_commit(void) { WGPUCommandEncoderDescriptor cmd_enc_desc; _sg_clear(&cmd_enc_desc, sizeof(cmd_enc_desc)); _sg.wgpu.cmd_enc = wgpuDeviceCreateCommandEncoder(_sg.wgpu.dev, &cmd_enc_desc); - - // reset uniform buffer offsets - _sg_wgpu_uniform_buffer_on_commit(); } _SOKOL_PRIVATE void _sg_wgpu_apply_viewport(int x, int y, int w, int h, bool origin_top_left) { @@ -13424,6 +13436,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ const uint32_t alignment = _sg.wgpu.limits.limits.minUniformBufferOffsetAlignment; SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); + SOKOL_ASSERT(_sg.wgpu.uniform.stage); SOKOL_ASSERT((_sg.wgpu.uniform.offset + data->size) <= _sg.wgpu.uniform.num_bytes); SOKOL_ASSERT((_sg.wgpu.uniform.offset & (alignment - 1)) == 0); SOKOL_ASSERT(_sg.wgpu.cur_pipeline && _sg.wgpu.cur_pipeline->shader); @@ -13433,16 +13446,14 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ SOKOL_ASSERT(data->size <= _sg.wgpu.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size); SOKOL_ASSERT(data->size <= _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); - // FIXME: memcpy into an intermediate memory buffer here, and do a single big - // wgpuQueueWriteBuffer at the end of the frame - wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, _sg.wgpu.uniform.offset, data->ptr, data->size); + memcpy(_sg.wgpu.uniform.stage + _sg.wgpu.uniform.offset, data->ptr, data->size); _sg.wgpu.uniform.bind.offsets[stage_index][ub_index] = _sg.wgpu.uniform.offset; + _sg.wgpu.uniform.offset = _sg_roundup_u32(_sg.wgpu.uniform.offset + (uint32_t)data->size, alignment); wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_UNIFORM_BINDGROUP_INDEX, _sg.wgpu.uniform.bind.group, SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_UBS, &_sg.wgpu.uniform.bind.offsets[0][0]); - _sg.wgpu.uniform.offset = _sg_roundup_u32(_sg.wgpu.uniform.offset + (uint32_t)data->size, alignment); } _SOKOL_PRIVATE void _sg_wgpu_draw(int base_element, int num_elements, int num_instances) { From e0e88804af6368177b404b9e715d5d694870ccd7 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 16 Sep 2023 17:38:47 +0200 Subject: [PATCH 54/95] sokol_gfx.h wgpu: better naming for the intermediate uniform staging memory block --- sokol_gfx.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index a96eaa857..59e225523 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4898,7 +4898,7 @@ typedef _sg_wgpu_context_t _sg_context_t; typedef struct { uint32_t num_bytes; uint32_t offset; // current offset into buf - uint8_t* stage; // intermediate buffer for uniform data updates + uint8_t* staging; // intermediate buffer for uniform data updates WGPUBuffer buf; // the GPU-side uniform buffer struct { WGPUBindGroupLayout group_layout; @@ -12427,7 +12427,7 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { } _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_init(const sg_desc* desc) { - SOKOL_ASSERT(0 == _sg.wgpu.uniform.stage); + SOKOL_ASSERT(0 == _sg.wgpu.uniform.staging); SOKOL_ASSERT(0 == _sg.wgpu.uniform.buf); SOKOL_ASSERT(0 == _sg.wgpu.uniform.bind.group_layout); SOKOL_ASSERT(0 == _sg.wgpu.uniform.bind.group); @@ -12439,7 +12439,7 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_init(const sg_desc* desc) { // // FIXME: is this still needed? _sg.wgpu.uniform.num_bytes = (uint32_t)(desc->uniform_buffer_size + _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); - _sg.wgpu.uniform.stage = (uint8_t*)_sg_malloc(_sg.wgpu.uniform.num_bytes); + _sg.wgpu.uniform.staging = (uint8_t*)_sg_malloc(_sg.wgpu.uniform.num_bytes); WGPUBufferDescriptor ub_desc; _sg_clear(&ub_desc, sizeof(ub_desc)); @@ -12500,9 +12500,9 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_discard(void) { wgpuBindGroupLayoutRelease(_sg.wgpu.uniform.bind.group_layout); _sg.wgpu.uniform.bind.group_layout = 0; } - if (_sg.wgpu.uniform.stage) { - _sg_free(_sg.wgpu.uniform.stage); - _sg.wgpu.uniform.stage = 0; + if (_sg.wgpu.uniform.staging) { + _sg_free(_sg.wgpu.uniform.staging); + _sg.wgpu.uniform.staging = 0; } } @@ -12515,7 +12515,7 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_begin_pass(void) { } _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { - wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, 0, _sg.wgpu.uniform.stage, _sg.wgpu.uniform.offset); + wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, 0, _sg.wgpu.uniform.staging, _sg.wgpu.uniform.offset); _sg.wgpu.uniform.offset = 0; _sg_clear(&_sg.wgpu.uniform.bind.offsets[0][0], sizeof(_sg.wgpu.uniform.bind.offsets)); } @@ -13436,7 +13436,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ const uint32_t alignment = _sg.wgpu.limits.limits.minUniformBufferOffsetAlignment; SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); - SOKOL_ASSERT(_sg.wgpu.uniform.stage); + SOKOL_ASSERT(_sg.wgpu.uniform.staging); SOKOL_ASSERT((_sg.wgpu.uniform.offset + data->size) <= _sg.wgpu.uniform.num_bytes); SOKOL_ASSERT((_sg.wgpu.uniform.offset & (alignment - 1)) == 0); SOKOL_ASSERT(_sg.wgpu.cur_pipeline && _sg.wgpu.cur_pipeline->shader); @@ -13446,7 +13446,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ SOKOL_ASSERT(data->size <= _sg.wgpu.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size); SOKOL_ASSERT(data->size <= _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); - memcpy(_sg.wgpu.uniform.stage + _sg.wgpu.uniform.offset, data->ptr, data->size); + memcpy(_sg.wgpu.uniform.staging + _sg.wgpu.uniform.offset, data->ptr, data->size); _sg.wgpu.uniform.bind.offsets[stage_index][ub_index] = _sg.wgpu.uniform.offset; _sg.wgpu.uniform.offset = _sg_roundup_u32(_sg.wgpu.uniform.offset + (uint32_t)data->size, alignment); wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, From 573c566e23089b4b2bcb96f38dd952e530e0e334 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 26 Sep 2023 20:07:52 +0200 Subject: [PATCH 55/95] sokol_gfx.h wgpu: bindgroup cache wip --- sokol_gfx.h | 64 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 59e225523..2853090cb 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -3330,6 +3330,8 @@ typedef struct sg_desc { int max_commit_listeners; bool disable_validation; // disable validation layer even in debug mode, useful for tests bool mtl_force_managed_storage_mode; // for debugging: use Metal managed storage mode for resources even with UMA + bool wgpu_disable_bindgroup_cache; // set to false to disable the WebGPU backend BindGroup cache + int wgpu_bindgroup_cache_size; // number of slots in the WebGPU bindgroup cache (must be 2^N) sg_allocator allocator; sg_logger logger; // optional log function override sg_context_desc context; @@ -4021,6 +4023,14 @@ typedef struct { sg_resource_state state; } _sg_slot_t; +// a common resource pool housekeeping struct +typedef struct { + int size; + int queue_top; + uint32_t* gen_ctrs; + int* free_queue; +} _sg_pool_t; + // constants enum { _SG_STRING_SIZE = 16, @@ -4036,6 +4046,7 @@ enum { _SG_DEFAULT_CONTEXT_POOL_SIZE = 16, _SG_DEFAULT_UB_SIZE = 4 * 1024 * 1024, _SG_DEFAULT_MAX_COMMIT_LISTENERS = 1024, + _SG_DEFAULT_WGPU_BINDGROUP_CACHE_SIZE = 1024, }; // fixed-size string @@ -4907,6 +4918,25 @@ typedef struct { } bind; } _sg_wgpu_uniform_buffer_t; +// an internal bindgroup wrapper object (referenced by bindgroup cache) +#define _SG_WGPU_BINDGROUP_KEY_NUM (1+SG_NUM_SHADER_STAGES*(SG_MAX_SHADERSTAGE_IMAGES+SG_MAX_SHADERSTAGE_SAMPLERS)) +typedef struct { + _sg_slot_t slot; + WGPUBindGroup bg; + uint64_t hash; + uint32_t key[_SG_WGPU_BINDGROUP_KEY_NUM]; // pipeline + image + sampler ids +} _sg_wgpu_bindgroup_t; + +typedef struct { + uint32_t id; +} _sg_wgpu_bindgroup_handle_t; + +typedef struct { + size_t num; // must be 2^n + uint64_t index_mask; // mask to turn hash into valid index + _sg_wgpu_bindgroup_handle_t* items; +} _sg_wgpu_bindgroup_cache_t; + typedef struct { struct { sg_buffer buffer; @@ -4916,7 +4946,13 @@ typedef struct { sg_buffer buffer; int offset; } ib; -} _sg_wgpu_bindcache_t; + _sg_wgpu_bindgroup_handle_t bindgroup; +} _sg_wgpu_bindings_cache_t; + +typedef struct { + _sg_pool_t pool; + _sg_wgpu_bindgroup_t* bindgroups; +} _sg_wgpu_bindgroup_pool_t; // the WGPU backend state typedef struct { @@ -4941,7 +4977,9 @@ typedef struct { const _sg_pipeline_t* cur_pipeline; sg_pipeline cur_pipeline_id; _sg_wgpu_uniform_buffer_t uniform; - _sg_wgpu_bindcache_t bindcache; + _sg_wgpu_bindings_cache_t bindings_cache; + _sg_wgpu_bindgroup_cache_t bingroup_cache; + _sg_wgpu_bindgroup_pool_t bindgroup_pool; } _sg_wgpu_backend_t; #endif @@ -4950,13 +4988,6 @@ typedef struct { // this *MUST* remain 0 #define _SG_INVALID_SLOT_INDEX (0) -typedef struct { - int size; - int queue_top; - uint32_t* gen_ctrs; - int* free_queue; -} _sg_pool_t; - typedef struct { _sg_pool_t buffer_pool; _sg_pool_t image_pool; @@ -12521,29 +12552,29 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { } _SOKOL_PRIVATE void _sg_wgpu_bindcache_clear(void) { - memset(&_sg.wgpu.bindcache, 0, sizeof(_sg.wgpu.bindcache)); + memset(&_sg.wgpu.bindings_cache, 0, sizeof(_sg.wgpu.bindings_cache)); } _SOKOL_PRIVATE bool _sg_wgpu_bindcache_vb_dirty(int index, const _sg_buffer_t* vb, int offset) { SOKOL_ASSERT(vb && (index >= 0) && (index < SG_MAX_VERTEX_BUFFERS)); - return (vb->slot.id != _sg.wgpu.bindcache.vbs[index].buffer.id) || (offset != _sg.wgpu.bindcache.vbs[index].offset); + return (vb->slot.id != _sg.wgpu.bindings_cache.vbs[index].buffer.id) || (offset != _sg.wgpu.bindings_cache.vbs[index].offset); } _SOKOL_PRIVATE void _sg_wgpu_bindcache_vb_update(int index, const _sg_buffer_t* vb, int offset) { SOKOL_ASSERT(vb && (index >= 0) && (index < SG_MAX_VERTEX_BUFFERS)); - _sg.wgpu.bindcache.vbs[index].buffer.id = vb->slot.id; - _sg.wgpu.bindcache.vbs[index].offset = offset; + _sg.wgpu.bindings_cache.vbs[index].buffer.id = vb->slot.id; + _sg.wgpu.bindings_cache.vbs[index].offset = offset; } _SOKOL_PRIVATE bool _sg_wgpu_bindcache_ib_dirty(const _sg_buffer_t* ib, int ib_offset) { SOKOL_ASSERT(ib); - return (ib->slot.id != _sg.wgpu.bindcache.ib.buffer.id) || (ib_offset != _sg.wgpu.bindcache.ib.offset); + return (ib->slot.id != _sg.wgpu.bindings_cache.ib.buffer.id) || (ib_offset != _sg.wgpu.bindings_cache.ib.offset); } _SOKOL_PRIVATE void _sg_wgpu_bindcache_ib_update(const _sg_buffer_t* ib, int ib_offset) { SOKOL_ASSERT(ib); - _sg.wgpu.bindcache.ib.buffer.id = ib->slot.id; - _sg.wgpu.bindcache.ib.offset = ib_offset; + _sg.wgpu.bindings_cache.ib.buffer.id = ib->slot.id; + _sg.wgpu.bindings_cache.ib.offset = ib_offset; } _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { @@ -15852,6 +15883,7 @@ _SOKOL_PRIVATE sg_desc _sg_desc_defaults(const sg_desc* desc) { res.context_pool_size = _sg_def(res.context_pool_size, _SG_DEFAULT_CONTEXT_POOL_SIZE); res.uniform_buffer_size = _sg_def(res.uniform_buffer_size, _SG_DEFAULT_UB_SIZE); res.max_commit_listeners = _sg_def(res.max_commit_listeners, _SG_DEFAULT_MAX_COMMIT_LISTENERS); + res.wgpu_bindgroup_cache_size = _sg_def(res.wgpu_bindgroup_cache_size, _SG_DEFAULT_WGPU_BINDGROUP_CACHE_SIZE); return res; } From fff648f9028e3be4c469bdee2558736852fcf06d Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 27 Sep 2023 19:40:50 +0200 Subject: [PATCH 56/95] sokol_gfx.h wgpu: bindgroup cache wip --- sokol_gfx.h | 83 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 11 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 2853090cb..053ca5505 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -3330,8 +3330,8 @@ typedef struct sg_desc { int max_commit_listeners; bool disable_validation; // disable validation layer even in debug mode, useful for tests bool mtl_force_managed_storage_mode; // for debugging: use Metal managed storage mode for resources even with UMA - bool wgpu_disable_bindgroup_cache; // set to false to disable the WebGPU backend BindGroup cache - int wgpu_bindgroup_cache_size; // number of slots in the WebGPU bindgroup cache (must be 2^N) + bool wgpu_disable_bindgroups_cache; // set to false to disable the WebGPU backend BindGroup cache + int wgpu_bindgroups_cache_size; // number of slots in the WebGPU bindgroup cache (must be 2^N) sg_allocator allocator; sg_logger logger; // optional log function override sg_context_desc context; @@ -4031,6 +4031,14 @@ typedef struct { int* free_queue; } _sg_pool_t; +_SOKOL_PRIVATE void _sg_init_pool(_sg_pool_t* pool, int num); +_SOKOL_PRIVATE void _sg_discard_pool(_sg_pool_t* pool); +_SOKOL_PRIVATE int _sg_pool_alloc_index(_sg_pool_t* pool); +_SOKOL_PRIVATE void _sg_pool_free_index(_sg_pool_t* pool, int slot_index); +_SOKOL_PRIVATE void _sg_reset_slot(_sg_slot_t* slot); +_SOKOL_PRIVATE uint32_t _sg_slot_alloc(_sg_pool_t* pool, _sg_slot_t* slot, int slot_index); +_SOKOL_PRIVATE int _sg_slot_index(uint32_t id); + // constants enum { _SG_STRING_SIZE = 16, @@ -4935,7 +4943,12 @@ typedef struct { size_t num; // must be 2^n uint64_t index_mask; // mask to turn hash into valid index _sg_wgpu_bindgroup_handle_t* items; -} _sg_wgpu_bindgroup_cache_t; +} _sg_wgpu_bindgroups_cache_t; + +typedef struct { + _sg_pool_t pool; + _sg_wgpu_bindgroup_t* bindgroups; +} _sg_wgpu_bindgroups_pool_t; typedef struct { struct { @@ -4949,11 +4962,6 @@ typedef struct { _sg_wgpu_bindgroup_handle_t bindgroup; } _sg_wgpu_bindings_cache_t; -typedef struct { - _sg_pool_t pool; - _sg_wgpu_bindgroup_t* bindgroups; -} _sg_wgpu_bindgroup_pool_t; - // the WGPU backend state typedef struct { bool valid; @@ -4978,8 +4986,8 @@ typedef struct { sg_pipeline cur_pipeline_id; _sg_wgpu_uniform_buffer_t uniform; _sg_wgpu_bindings_cache_t bindings_cache; - _sg_wgpu_bindgroup_cache_t bingroup_cache; - _sg_wgpu_bindgroup_pool_t bindgroup_pool; + _sg_wgpu_bindgroups_cache_t bingroups_cache; + _sg_wgpu_bindgroups_pool_t bindgroups_pool; } _sg_wgpu_backend_t; #endif @@ -12551,6 +12559,52 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { _sg_clear(&_sg.wgpu.uniform.bind.offsets[0][0], sizeof(_sg.wgpu.uniform.bind.offsets)); } +_SOKOL_PRIVATE void _sg_wgpu_bindgroups_pool_init(const sg_desc* desc) { + SOKOL_ASSERT(!desc->wgpu_disable_bindgroups_cache); + SOKOL_ASSERT((desc->wgpu_bindgroups_cache_size > 0) && (desc->wgpu_bindgroups_cache_size < _SG_MAX_POOL_SIZE)); + SOKOL_ASSERT(0 == _sg.wgpu.bindgroups_pool.bindgroups); + const int pool_size = desc->wgpu_bindgroups_cache_size; + _sg_init_pool(&_sg.wgpu.bindgroups_pool.pool, pool_size); + size_t pool_byte_size = sizeof(_sg_wgpu_bindgroup_t) * (size_t)pool_size; + _sg.wgpu.bindgroups_pool.bindgroups = _sg_malloc_clear(pool_byte_size); +} + +_SOKOL_PRIVATE void _sg_wgpu_bindgroups_pool_discard(_sg_wgpu_bindgroups_pool_t* p) { + SOKOL_ASSERT(p && p->bindgroups); + _sg_free(p->bindgroups); p->bindgroups = 0; + _sg_discard_pool(&p->pool); +} + +_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_bindgroup_at(_sg_wgpu_bindgroups_pool_t* p, uint32_t bg_id) { + SOKOL_ASSERT(p && (SG_INVALID_ID != bg_id)); + int slot_index = _sg_slot_index(bg_id); + SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->pool.size)); + return &p->bindgroups[slot_index]; +} + +_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_lookup_bindgroup(_sg_wgpu_bindgroups_pool_t* p, uint32_t bg_id) { + if (SG_INVALID_ID != bg_id) { + _sg_wgpu_bindgroup_t* bg = _sg_wgpu_bindgroup_at(p, bg_id); + if (bg->slot.id == bg_id) { + return bg; + } + } + return 0; +} + +_SOKOL_PRIVATE void _sg_wgpu_discard_bindgroup(_sg_wgpu_bindgroup_t* bg) { + // FIXME! +} + +_SOKOL_PRIVATE void _sg_wgpu_discard_all_bindgroups(_sg_wgpu_bindgroups_pool_t* p) { + for (int i = 0; i < p->pool.size; i++) { + sg_resource_state state = p->bindgroups[i].slot.state; + if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) { + _sg_wgpu_discard_bindgroup(&p->bindgroups[i]); + } + } +} + _SOKOL_PRIVATE void _sg_wgpu_bindcache_clear(void) { memset(&_sg.wgpu.bindings_cache, 0, sizeof(_sg.wgpu.bindings_cache)); } @@ -12600,6 +12654,9 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg_wgpu_bindcache_clear(); _sg_wgpu_init_caps(); _sg_wgpu_uniform_buffer_init(desc); + if (!desc->wgpu_disable_bindgroups_cache) { + _sg_wgpu_bindgroups_pool_init(desc); + } // create an empty bind group for shader stages without bound images WGPUBindGroupLayoutDescriptor bgl_desc; @@ -12624,6 +12681,10 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_backend(void) { SOKOL_ASSERT(_sg.wgpu.valid); SOKOL_ASSERT(_sg.wgpu.cmd_enc); _sg.wgpu.valid = false; + if (!_sg.desc.wgpu_disable_bindgroups_cache) { + _sg_wgpu_discard_all_bindgroups(&_sg.wgpu.bindgroups_pool); + _sg_wgpu_bindgroups_pool_discard(&_sg.wgpu.bindgroups_pool); + } _sg_wgpu_uniform_buffer_discard(); wgpuBindGroupRelease(_sg.wgpu.empty_bind_group); _sg.wgpu.empty_bind_group = 0; wgpuCommandEncoderRelease(_sg.wgpu.cmd_enc); _sg.wgpu.cmd_enc = 0; @@ -15883,7 +15944,7 @@ _SOKOL_PRIVATE sg_desc _sg_desc_defaults(const sg_desc* desc) { res.context_pool_size = _sg_def(res.context_pool_size, _SG_DEFAULT_CONTEXT_POOL_SIZE); res.uniform_buffer_size = _sg_def(res.uniform_buffer_size, _SG_DEFAULT_UB_SIZE); res.max_commit_listeners = _sg_def(res.max_commit_listeners, _SG_DEFAULT_MAX_COMMIT_LISTENERS); - res.wgpu_bindgroup_cache_size = _sg_def(res.wgpu_bindgroup_cache_size, _SG_DEFAULT_WGPU_BINDGROUP_CACHE_SIZE); + res.wgpu_bindgroups_cache_size = _sg_def(res.wgpu_bindgroups_cache_size, _SG_DEFAULT_WGPU_BINDGROUP_CACHE_SIZE); return res; } From daf519e99ecfc1be93b5922bdd472766b35d6786 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 30 Sep 2023 12:49:00 +0200 Subject: [PATCH 57/95] sokol_gfx.h wgpu: implement internal bindgroup resource pool --- sokol_gfx.h | 313 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 225 insertions(+), 88 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 053ca5505..bc56dff90 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2904,7 +2904,8 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(METAL_FRAGMENT_SHADER_ENTRY_NOT_FOUND, "fragment shader entry not found (metal)") \ _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_FAILED, "failed to create render pipeline state (metal)") \ _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_OUTPUT, "") \ - _SG_LOGITEM_XMACRO(WGPU_MAP_UNIFORM_BUFFER_FAILED, "failed to map uniform buffer (wgpu)") \ + _SG_LOGITEM_XMACRO(WGPU_BINDGROUPS_POOL_EXHAUSTED, "wgpu BindGroups pool exhausted (increase sg_desc.bindgroups_cache_size)") \ + _SG_LOGITEM_XMACRO(WGPU_CREATEBINDGROUP_FAILED, "wgpuDeviceCreateBindGroup failed") \ _SG_LOGITEM_XMACRO(WGPU_CREATE_BUFFER_FAILED, "wgpuDeviceCreateBuffer() failed") \ _SG_LOGITEM_XMACRO(WGPU_CREATE_TEXTURE_FAILED, "wgpuDeviceCreateTexture() failed") \ _SG_LOGITEM_XMACRO(WGPU_CREATE_TEXTURE_VIEW_FAILED, "wgpuTextureCreateView() failed") \ @@ -4926,25 +4927,28 @@ typedef struct { } bind; } _sg_wgpu_uniform_buffer_t; -// an internal bindgroup wrapper object (referenced by bindgroup cache) -#define _SG_WGPU_BINDGROUP_KEY_NUM (1+SG_NUM_SHADER_STAGES*(SG_MAX_SHADERSTAGE_IMAGES+SG_MAX_SHADERSTAGE_SAMPLERS)) -typedef struct { - _sg_slot_t slot; - WGPUBindGroup bg; - uint64_t hash; - uint32_t key[_SG_WGPU_BINDGROUP_KEY_NUM]; // pipeline + image + sampler ids -} _sg_wgpu_bindgroup_t; - typedef struct { uint32_t id; } _sg_wgpu_bindgroup_handle_t; +#define _SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS (1 + SG_NUM_SHADER_STAGES * (SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS)) +typedef struct { + uint64_t hash; + uint32_t items[_SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS]; +} _sg_wgpu_bindgroupscache_key_t; + typedef struct { size_t num; // must be 2^n uint64_t index_mask; // mask to turn hash into valid index _sg_wgpu_bindgroup_handle_t* items; } _sg_wgpu_bindgroups_cache_t; +typedef struct { + _sg_slot_t slot; + WGPUBindGroup bindgroup; + _sg_wgpu_bindgroupscache_key_t key; +} _sg_wgpu_bindgroup_t; + typedef struct { _sg_pool_t pool; _sg_wgpu_bindgroup_t* bindgroups; @@ -5870,7 +5874,7 @@ _SOKOL_PRIVATE void _sg_dummy_update_buffer(_sg_buffer_t* buf, const sg_range* d } } -_SOKOL_PRIVATE void _sg_dummy_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { +_SOKOL_PRIVATE bool _sg_dummy_append_buffer(_sg_buffer_t* buf, const sg_range* data, bool new_frame) { SOKOL_ASSERT(buf && data && data->ptr && (data->size > 0)); _SOKOL_UNUSED(data); if (new_frame) { @@ -5878,6 +5882,7 @@ _SOKOL_PRIVATE void _sg_dummy_append_buffer(_sg_buffer_t* buf, const sg_range* d buf->cmn.active_slot = 0; } } + return true; } _SOKOL_PRIVATE void _sg_dummy_update_image(_sg_image_t* img, const sg_image_data* data) { @@ -8158,7 +8163,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { _SG_GL_CHECK_ERROR(); } -_SOKOL_PRIVATE void _sg_gl_apply_bindings( +_SOKOL_PRIVATE bool _sg_gl_apply_bindings( _sg_pipeline_t* pip, _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, _sg_buffer_t* ib, int ib_offset, @@ -8252,6 +8257,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_bindings( } } _SG_GL_CHECK_ERROR(); + return true; } _SOKOL_PRIVATE void _sg_gl_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) { @@ -10130,7 +10136,7 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_pipeline(_sg_pipeline_t* pip) { _sg_d3d11_PSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_FS].cbufs); } -_SOKOL_PRIVATE void _sg_d3d11_apply_bindings( +_SOKOL_PRIVATE bool _sg_d3d11_apply_bindings( _sg_pipeline_t* pip, _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, _sg_buffer_t* ib, int ib_offset, @@ -10178,6 +10184,7 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_bindings( _sg_d3d11_PSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_fs_srvs); _sg_d3d11_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_SAMPLERS, d3d11_vs_smps); _sg_d3d11_PSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_SAMPLERS, d3d11_fs_smps); + return true; } _SOKOL_PRIVATE void _sg_d3d11_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) { @@ -11812,7 +11819,7 @@ _SOKOL_PRIVATE void _sg_mtl_apply_pipeline(_sg_pipeline_t* pip) { } } -_SOKOL_PRIVATE void _sg_mtl_apply_bindings( +_SOKOL_PRIVATE bool _sg_mtl_apply_bindings( _sg_pipeline_t* pip, _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, _sg_buffer_t* ib, int ib_offset, @@ -11899,6 +11906,7 @@ _SOKOL_PRIVATE void _sg_mtl_apply_bindings( [_sg.mtl.cmd_encoder setFragmentSamplerState:_sg_mtl_id(smp->mtl.sampler_state) atIndex:slot]; } } + return true; } _SOKOL_PRIVATE void _sg_mtl_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) { @@ -12560,7 +12568,6 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { } _SOKOL_PRIVATE void _sg_wgpu_bindgroups_pool_init(const sg_desc* desc) { - SOKOL_ASSERT(!desc->wgpu_disable_bindgroups_cache); SOKOL_ASSERT((desc->wgpu_bindgroups_cache_size > 0) && (desc->wgpu_bindgroups_cache_size < _SG_MAX_POOL_SIZE)); SOKOL_ASSERT(0 == _sg.wgpu.bindgroups_pool.bindgroups); const int pool_size = desc->wgpu_bindgroups_cache_size; @@ -12592,8 +12599,163 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_lookup_bindgroup(_sg_wgpu_bindgrou return 0; } -_SOKOL_PRIVATE void _sg_wgpu_discard_bindgroup(_sg_wgpu_bindgroup_t* bg) { +_SOKOL_PRIVATE _sg_wgpu_bindgroup_handle_t _sg_wgpu_alloc_bindgroup(_sg_wgpu_bindgroups_pool_t* p) { + _sg_wgpu_bindgroup_handle_t res; + int slot_index = _sg_pool_alloc_index(&p->pool); + if (_SG_INVALID_SLOT_INDEX != slot_index) { + res.id = _sg_slot_alloc(&p->pool, &p->bindgroups[slot_index].slot, slot_index); + } else { + res.id = SG_INVALID_ID; + _SG_ERROR(WGPU_BINDGROUPS_POOL_EXHAUSTED); + } + return res; +} + +_SOKOL_PRIVATE void _sg_wgpu_dealloc_bindgroup(_sg_wgpu_bindgroups_pool_t* p, _sg_wgpu_bindgroup_t* bg) { + SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_ALLOC) && (bg->slot.id != SG_INVALID_ID)); + _sg_pool_free_index(&p->pool, _sg_slot_index(bg->slot.id)); + _sg_reset_slot(&bg->slot); +} + +_SOKOL_PRIVATE void _sg_wgpu_reset_bindgroup_to_alloc_state(_sg_wgpu_bindgroup_t* bg) { + SOKOL_ASSERT(bg); + _sg_slot_t slot = bg->slot; + _sg_clear(bg, sizeof(_sg_wgpu_bindgroup_t)); + bg->slot = slot; + bg->slot.state = SG_RESOURCESTATE_ALLOC; +} + +_SOKOL_PRIVATE uint64_t _sg_wgpu_hash(void* ptr, size_t num_bytes) { // FIXME! + (void)ptr; (void)num_bytes; + return 0; +} + +_SOKOL_PRIVATE void _sg_wgpu_init_bindgroupscache_key(_sg_wgpu_bindgroupscache_key_t* key, + _sg_pipeline_t* pip, + _sg_image_t** vs_imgs, int num_vs_imgs, + _sg_sampler_t** vs_smps, int num_vs_smps, + _sg_image_t** fs_imgs, int num_fs_imgs, + _sg_sampler_t** fs_smps, int num_fs_smps) +{ + SOKOL_ASSERT(pip); + SOKOL_ASSERT(vs_imgs && (num_vs_imgs <= SG_MAX_SHADERSTAGE_IMAGES)); + SOKOL_ASSERT(vs_smps && (num_vs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS)); + SOKOL_ASSERT(fs_imgs && (num_fs_imgs <= SG_MAX_SHADERSTAGE_IMAGES)); + SOKOL_ASSERT(fs_smps && (num_fs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS)); + + _sg_clear(key->items, sizeof(key->items)); + key->items[0] = pip->slot.id; + const int vs_imgs_offset = 1; + const int vs_smps_offset = vs_imgs_offset + SG_MAX_SHADERSTAGE_IMAGES; + const int fs_imgs_offset = vs_smps_offset + SG_MAX_SHADERSTAGE_SAMPLERS; + const int fs_smps_offset = fs_imgs_offset + SG_MAX_SHADERSTAGE_IMAGES; + SOKOL_ASSERT((fs_smps_offset + SG_MAX_SHADERSTAGE_SAMPLERS) == _SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS); + for (int i = 0; i < num_vs_imgs; i++) { + SOKOL_ASSERT(vs_imgs[i]); + key->items[vs_imgs_offset + i] = vs_imgs[i]->slot.id; + } + for (int i = 0; i < num_vs_smps; i++) { + SOKOL_ASSERT(vs_smps[i]); + key->items[vs_smps_offset + i] = vs_smps[i]->slot.id; + } + for (int i = 0; i < num_fs_imgs; i++) { + SOKOL_ASSERT(fs_imgs[i]); + key->items[fs_imgs_offset + i] = fs_imgs[i]->slot.id; + } + for (int i = 0; i < num_fs_smps; i++) { + SOKOL_ASSERT(fs_smps[i]); + key->items[fs_smps_offset + i] = fs_smps[i]->slot.id; + } + key->hash = _sg_wgpu_hash(&key->items, sizeof(key->items)); +} + +_SOKOL_PRIVATE bool _sg_wgpu_compare_bindgroupscache_key(_sg_wgpu_bindgroupscache_key_t* k0, _sg_wgpu_bindgroupscache_key_t* k1) { + SOKOL_ASSERT(k0 && k1); + if (k0->hash != k1->hash) { + return false; + } + if (memcmp(&k0->items, &k1->items, sizeof(k0->items)) != 0) { + return false; + } + return true; +} + +_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup( + _sg_pipeline_t* pip, + _sg_image_t** vs_imgs, int num_vs_imgs, + _sg_sampler_t** vs_smps, int num_vs_smps, + _sg_image_t** fs_imgs, int num_fs_imgs, + _sg_sampler_t** fs_smps, int num_fs_smps) +{ + SOKOL_ASSERT(_sg.wgpu.dev); + SOKOL_ASSERT(pip); + SOKOL_ASSERT(pip->shader && (pip->cmn.shader_id.id == pip->shader->slot.id)); + _sg_wgpu_bindgroup_handle_t bg_id = _sg_wgpu_alloc_bindgroup(&_sg.wgpu.bindgroups_pool); + if (bg_id.id == SG_INVALID_ID) { + return 0; + } + _sg_wgpu_bindgroup_t* bg = _sg_wgpu_bindgroup_at(&_sg.wgpu.bindgroups_pool, bg_id.id); + SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_ALLOC)); + + // create wgpu bindgroup object + WGPUBindGroupLayout bgl = pip->shader->wgpu.bind_group_layout; + SOKOL_ASSERT(bgl); + WGPUBindGroupEntry wgpu_entries[SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS]; + _sg_clear(&wgpu_entries, sizeof(wgpu_entries)); + int bge_index = 0; + for (int i = 0; i < num_vs_imgs; i++) { + WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; + wgpu_entry->binding = _sg_wgpu_image_binding(SG_SHADERSTAGE_VS, i); + wgpu_entry->textureView = vs_imgs[i]->wgpu.view; + } + for (int i = 0; i < num_vs_smps; i++) { + WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; + wgpu_entry->binding = _sg_wgpu_sampler_binding(SG_SHADERSTAGE_VS, i); + wgpu_entry->sampler = vs_smps[i]->wgpu.smp; + } + for (int i = 0; i < num_fs_imgs; i++) { + WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; + wgpu_entry->binding = _sg_wgpu_image_binding(SG_SHADERSTAGE_FS, i); + wgpu_entry->textureView = fs_imgs[i]->wgpu.view; + } + for (int i = 0; i < num_fs_smps; i++) { + WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; + wgpu_entry->binding = _sg_wgpu_sampler_binding(SG_SHADERSTAGE_FS, i); + wgpu_entry->sampler = fs_smps[i]->wgpu.smp; + } + WGPUBindGroupDescriptor bg_desc; + _sg_clear(&bg_desc, sizeof(bg_desc)); + bg_desc.layout = bgl; + bg_desc.entryCount = (size_t)bge_index; + bg_desc.entries = &wgpu_entries[0]; + bg->bindgroup = wgpuDeviceCreateBindGroup(_sg.wgpu.dev, &bg_desc); + if (bg->bindgroup == 0) { + _SG_ERROR(WGPU_CREATEBINDGROUP_FAILED); + bg->slot.state = SG_RESOURCESTATE_FAILED; + return bg; + } + + _sg_wgpu_init_bindgroupscache_key(&bg->key, pip, vs_imgs, num_vs_imgs, vs_smps, num_vs_smps, fs_imgs, num_fs_imgs, fs_smps, num_fs_smps); + + bg->slot.state = SG_RESOURCESTATE_VALID; + return bg; +} + +_SOKOL_PRIVATE void _sg_wgpu_discard_bindgroup(_sg_wgpu_bindgroup_t* bg) { + SOKOL_ASSERT(bg); + if (bg->slot.state == SG_RESOURCESTATE_VALID) { + if (bg->bindgroup) { + wgpuBindGroupRelease(bg->bindgroup); + bg->bindgroup = 0; + } + _sg_wgpu_reset_bindgroup_to_alloc_state(bg); + SOKOL_ASSERT(bg->slot.state == SG_RESOURCESTATE_ALLOC); + } + if (bg->slot.state == SG_RESOURCESTATE_ALLOC) { + _sg_wgpu_dealloc_bindgroup(&_sg.wgpu.bindgroups_pool, bg); + SOKOL_ASSERT(bg->slot.state == SG_RESOURCESTATE_INITIAL); + } } _SOKOL_PRIVATE void _sg_wgpu_discard_all_bindgroups(_sg_wgpu_bindgroups_pool_t* p) { @@ -12631,6 +12793,31 @@ _SOKOL_PRIVATE void _sg_wgpu_bindcache_ib_update(const _sg_buffer_t* ib, int ib_ _sg.wgpu.bindings_cache.ib.offset = ib_offset; } +_SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup( + _sg_pipeline_t* pip, + _sg_image_t** vs_imgs, int num_vs_imgs, + _sg_sampler_t** vs_smps, int num_vs_smps, + _sg_image_t** fs_imgs, int num_fs_imgs, + _sg_sampler_t** fs_smps, int num_fs_smps) +{ + if ((num_vs_imgs + num_vs_smps + num_fs_imgs + num_fs_smps) > 0) { + // FIXME: use bindgroups cache! + _sg_wgpu_bindgroup_t* bg = _sg_wgpu_create_bindgroup(pip, vs_imgs, num_vs_imgs, vs_smps, num_vs_smps, fs_imgs, num_fs_imgs, fs_smps, num_fs_smps); + if (bg) { + if (bg->slot.state == SG_RESOURCESTATE_VALID) { + SOKOL_ASSERT(bg->bindgroup); + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0); + } + _sg_wgpu_discard_bindgroup(bg); + } else { + return false; + } + } else { + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); + } + return true; +} + _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { SOKOL_ASSERT(desc); SOKOL_ASSERT(desc->context.wgpu.device); @@ -12654,9 +12841,7 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg_wgpu_bindcache_clear(); _sg_wgpu_init_caps(); _sg_wgpu_uniform_buffer_init(desc); - if (!desc->wgpu_disable_bindgroups_cache) { - _sg_wgpu_bindgroups_pool_init(desc); - } + _sg_wgpu_bindgroups_pool_init(desc); // create an empty bind group for shader stages without bound images WGPUBindGroupLayoutDescriptor bgl_desc; @@ -12681,10 +12866,8 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_backend(void) { SOKOL_ASSERT(_sg.wgpu.valid); SOKOL_ASSERT(_sg.wgpu.cmd_enc); _sg.wgpu.valid = false; - if (!_sg.desc.wgpu_disable_bindgroups_cache) { - _sg_wgpu_discard_all_bindgroups(&_sg.wgpu.bindgroups_pool); - _sg_wgpu_bindgroups_pool_discard(&_sg.wgpu.bindgroups_pool); - } + _sg_wgpu_discard_all_bindgroups(&_sg.wgpu.bindgroups_pool); + _sg_wgpu_bindgroups_pool_discard(&_sg.wgpu.bindgroups_pool); _sg_wgpu_uniform_buffer_discard(); wgpuBindGroupRelease(_sg.wgpu.empty_bind_group); _sg.wgpu.empty_bind_group = 0; wgpuCommandEncoderRelease(_sg.wgpu.cmd_enc); _sg.wgpu.cmd_enc = 0; @@ -13425,53 +13608,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_pipeline(_sg_pipeline_t* pip) { wgpuRenderPassEncoderSetStencilReference(_sg.wgpu.pass_enc, pip->cmn.stencil.ref); } -_SOKOL_PRIVATE WGPUBindGroup _sg_wgpu_create_bindgroup( - WGPUBindGroupLayout bgl, - _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_sampler_t** vs_smps, int num_vs_smps, - _sg_image_t** fs_imgs, int num_fs_imgs, - _sg_sampler_t** fs_smps, int num_fs_smps) -{ - SOKOL_ASSERT(_sg.wgpu.dev); - SOKOL_ASSERT(vs_imgs && (num_vs_imgs <= SG_MAX_SHADERSTAGE_IMAGES)); - SOKOL_ASSERT(vs_smps && (num_vs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS)); - SOKOL_ASSERT(fs_imgs && (num_fs_imgs <= SG_MAX_SHADERSTAGE_IMAGES)); - SOKOL_ASSERT(fs_smps && (num_fs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS)); - - WGPUBindGroupEntry wgpu_entries[2 * SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS]; - _sg_clear(&wgpu_entries, sizeof(wgpu_entries)); - int bge_index = 0; - for (int i = 0; i < num_vs_imgs; i++) { - WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; - wgpu_entry->binding = _sg_wgpu_image_binding(SG_SHADERSTAGE_VS, i); - wgpu_entry->textureView = vs_imgs[i]->wgpu.view; - } - for (int i = 0; i < num_vs_smps; i++) { - WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; - wgpu_entry->binding = _sg_wgpu_sampler_binding(SG_SHADERSTAGE_VS, i); - wgpu_entry->sampler = vs_smps[i]->wgpu.smp; - } - for (int i = 0; i < num_fs_imgs; i++) { - WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; - wgpu_entry->binding = _sg_wgpu_image_binding(SG_SHADERSTAGE_FS, i); - wgpu_entry->textureView = fs_imgs[i]->wgpu.view; - } - for (int i = 0; i < num_fs_smps; i++) { - WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; - wgpu_entry->binding = _sg_wgpu_sampler_binding(SG_SHADERSTAGE_FS, i); - wgpu_entry->sampler = fs_smps[i]->wgpu.smp; - } - WGPUBindGroupDescriptor bg_desc; - _sg_clear(&bg_desc, sizeof(bg_desc)); - bg_desc.layout = bgl; - bg_desc.entryCount = (size_t)bge_index; - bg_desc.entries = &wgpu_entries[0]; - WGPUBindGroup bg = wgpuDeviceCreateBindGroup(_sg.wgpu.dev, &bg_desc); - SOKOL_ASSERT(bg); - return bg; -} - -_SOKOL_PRIVATE void _sg_wgpu_apply_bindings( +_SOKOL_PRIVATE bool _sg_wgpu_apply_bindings( _sg_pipeline_t* pip, _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, _sg_buffer_t* ib, int ib_offset, @@ -13483,6 +13620,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_bindings( SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); SOKOL_ASSERT(pip->shader && (pip->cmn.shader_id.id == pip->shader->slot.id)); + bool retval = true; // index buffer if (ib) { @@ -13511,17 +13649,9 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_bindings( // FIXME: else-path should actually set a null vertex buffer (this was just recently implemented in WebGPU) } - // FIXME: create adhoc bind group object for images and samplers - // (either use a bindgroup-cache or introduce bindgroups as sokol-gfx objects) - if ((num_vs_imgs + num_vs_smps + num_fs_imgs + num_fs_smps) > 0) { - WGPUBindGroupLayout bgl = pip->shader->wgpu.bind_group_layout; - SOKOL_ASSERT(bgl); - WGPUBindGroup bg = _sg_wgpu_create_bindgroup(bgl, vs_imgs, num_vs_imgs, vs_smps, num_vs_smps, fs_imgs, num_fs_imgs, fs_smps, num_fs_smps); - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg, 0, 0); - wgpuBindGroupRelease(bg); - } else { - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); - } + _sg_wgpu_apply_bindgroup(pip, vs_imgs, num_vs_imgs, vs_smps, num_vs_smps, fs_imgs, num_fs_imgs, fs_smps, num_fs_smps); + + return retval; } _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) { @@ -14000,7 +14130,7 @@ static inline void _sg_apply_pipeline(_sg_pipeline_t* pip) { #endif } -static inline void _sg_apply_bindings( +static inline bool _sg_apply_bindings( _sg_pipeline_t* pip, _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, _sg_buffer_t* ib, int ib_offset, @@ -14010,15 +14140,15 @@ static inline void _sg_apply_bindings( _sg_sampler_t** fs_smps, int num_fs_smps) { #if defined(_SOKOL_ANY_GL) - _sg_gl_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + return _sg_gl_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); #elif defined(SOKOL_METAL) - _sg_mtl_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + return _sg_mtl_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); #elif defined(SOKOL_D3D11) - _sg_d3d11_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + return _sg_d3d11_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); #elif defined(SOKOL_WGPU) - _sg_wgpu_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + return _sg_wgpu_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); #elif defined(SOKOL_DUMMY_BACKEND) - _sg_dummy_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + return _sg_dummy_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); #else #error("INVALID BACKEND"); #endif @@ -16841,7 +16971,14 @@ SOKOL_API_IMPL void sg_apply_bindings(const sg_bindings* bindings) { if (_sg.next_draw_valid) { const int* vb_offsets = bindings->vertex_buffer_offsets; int ib_offset = bindings->index_buffer_offset; - _sg_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + _sg.next_draw_valid = _sg_apply_bindings( + pip, + vbs, vb_offsets, num_vbs, + ib, ib_offset, + vs_imgs, num_vs_imgs, + fs_imgs, num_fs_imgs, + vs_smps, num_vs_smps, + fs_smps, num_fs_smps); _SG_TRACE_ARGS(apply_bindings, bindings); } } From 59bf444ae8a7ec1c78bc66457824f341dfd47ae3 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 30 Sep 2023 13:40:09 +0200 Subject: [PATCH 58/95] sokol_gfx.h: simplify bindings code across all backends --- sokol_gfx.h | 474 +++++++++++++++++++++++----------------------------- 1 file changed, 212 insertions(+), 262 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index bc56dff90..c453a6cad 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -5023,6 +5023,24 @@ typedef struct { sg_commit_listener* items; } _sg_commit_listeners_t; +// resolved resource bindings struct +typedef struct { + _sg_pipeline_t* pip; + int num_vbs; + int num_vs_imgs; + int num_vs_smps; + int num_fs_imgs; + int num_fs_smps; + int vb_offsets[SG_MAX_VERTEX_BUFFERS]; + int ib_offset; + _sg_buffer_t* vbs[SG_MAX_VERTEX_BUFFERS]; + _sg_buffer_t* ib; + _sg_image_t* vs_imgs[SG_MAX_SHADERSTAGE_IMAGES]; + _sg_sampler_t* vs_smps[SG_MAX_SHADERSTAGE_SAMPLERS]; + _sg_image_t* fs_imgs[SG_MAX_SHADERSTAGE_IMAGES]; + _sg_sampler_t* fs_smps[SG_MAX_SHADERSTAGE_SAMPLERS]; +} _sg_bindings_t; + typedef struct { bool valid; sg_desc desc; // original desc with default values patched in @@ -5031,7 +5049,7 @@ typedef struct { sg_pass cur_pass; sg_pipeline cur_pipeline; bool pass_valid; - bool bindings_valid; + bool bindings_applied; bool next_draw_valid; #if defined(SOKOL_DEBUG) sg_log_item validate_error; @@ -5830,28 +5848,11 @@ _SOKOL_PRIVATE void _sg_dummy_apply_pipeline(_sg_pipeline_t* pip) { _SOKOL_UNUSED(pip); } -_SOKOL_PRIVATE void _sg_dummy_apply_bindings( - _sg_pipeline_t* pip, - _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, - _sg_buffer_t* ib, int ib_offset, - _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_image_t** fs_imgs, int num_fs_imgs, - _sg_sampler_t** vs_smps, int num_vs_smps, - _sg_sampler_t** fs_smps, int num_fs_smps) -{ - SOKOL_ASSERT(pip); - SOKOL_ASSERT(vbs && vb_offsets); - SOKOL_ASSERT(vs_imgs); - SOKOL_ASSERT(fs_imgs); - SOKOL_ASSERT(vs_smps); - SOKOL_ASSERT(fs_smps); - _SOKOL_UNUSED(pip); - _SOKOL_UNUSED(vbs); _SOKOL_UNUSED(vb_offsets); _SOKOL_UNUSED(num_vbs); - _SOKOL_UNUSED(ib); _SOKOL_UNUSED(ib_offset); - _SOKOL_UNUSED(vs_imgs); _SOKOL_UNUSED(num_vs_imgs); - _SOKOL_UNUSED(fs_imgs); _SOKOL_UNUSED(num_fs_imgs); - _SOKOL_UNUSED(vs_smps); _SOKOL_UNUSED(num_vs_smps); - _SOKOL_UNUSED(fs_smps); _SOKOL_UNUSED(num_fs_smps); +_SOKOL_PRIVATE bool _sg_dummy_apply_bindings(_sg_bindings_t* bnd) { + SOKOL_ASSERT(bnd); + SOKOL_ASSERT(bnd->pip); + _SOKOL_UNUSED(bnd); + return true; } _SOKOL_PRIVATE void _sg_dummy_apply_uniforms(sg_shader_stage stage_index, int ub_index, const sg_range* data) { @@ -8163,28 +8164,20 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { _SG_GL_CHECK_ERROR(); } -_SOKOL_PRIVATE bool _sg_gl_apply_bindings( - _sg_pipeline_t* pip, - _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, - _sg_buffer_t* ib, int ib_offset, - _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_image_t** fs_imgs, int num_fs_imgs, - _sg_sampler_t** vs_smps, int num_vs_smps, - _sg_sampler_t** fs_smps, int num_fs_smps) -{ - SOKOL_ASSERT(pip); - _SOKOL_UNUSED(num_vbs); +_SOKOL_PRIVATE bool _sg_gl_apply_bindings(_sg_bindings_t* bnd) { + SOKOL_ASSERT(bnd); + SOKOL_ASSERT(bnd->pip); _SG_GL_CHECK_ERROR(); // bind combined image-samplers _SG_GL_CHECK_ERROR(); for (int stage_index = 0; stage_index < SG_NUM_SHADER_STAGES; stage_index++) { - const _sg_shader_stage_t* stage = &pip->shader->cmn.stage[stage_index]; - const _sg_gl_shader_stage_t* gl_stage = &pip->shader->gl.stage[stage_index]; - _sg_image_t** imgs = (stage_index == SG_SHADERSTAGE_VS) ? vs_imgs : fs_imgs; - _sg_sampler_t** smps = (stage_index == SG_SHADERSTAGE_VS) ? vs_smps : fs_smps; - const int num_imgs = (stage_index == SG_SHADERSTAGE_VS) ? num_vs_imgs : num_fs_imgs; - const int num_smps = (stage_index == SG_SHADERSTAGE_VS) ? num_vs_smps : num_fs_smps; + const _sg_shader_stage_t* stage = &bnd->pip->shader->cmn.stage[stage_index]; + const _sg_gl_shader_stage_t* gl_stage = &bnd->pip->shader->gl.stage[stage_index]; + _sg_image_t** imgs = (stage_index == SG_SHADERSTAGE_VS) ? bnd->vs_imgs : bnd->fs_imgs; + _sg_sampler_t** smps = (stage_index == SG_SHADERSTAGE_VS) ? bnd->vs_smps : bnd->fs_smps; + const int num_imgs = (stage_index == SG_SHADERSTAGE_VS) ? bnd->num_vs_imgs : bnd->num_fs_imgs; + const int num_smps = (stage_index == SG_SHADERSTAGE_VS) ? bnd->num_vs_smps : bnd->num_fs_smps; SOKOL_ASSERT(num_imgs == stage->num_images); _SOKOL_UNUSED(num_imgs); SOKOL_ASSERT(num_smps == stage->num_samplers); _SOKOL_UNUSED(num_smps); for (int img_smp_index = 0; img_smp_index < stage->num_image_samplers; img_smp_index++) { @@ -8206,24 +8199,24 @@ _SOKOL_PRIVATE bool _sg_gl_apply_bindings( _SG_GL_CHECK_ERROR(); // index buffer (can be 0) - const GLuint gl_ib = ib ? ib->gl.buf[ib->cmn.active_slot] : 0; + const GLuint gl_ib = bnd->ib ? bnd->ib->gl.buf[bnd->ib->cmn.active_slot] : 0; _sg_gl_cache_bind_buffer(GL_ELEMENT_ARRAY_BUFFER, gl_ib); - _sg.gl.cache.cur_ib_offset = ib_offset; + _sg.gl.cache.cur_ib_offset = bnd->ib_offset; // vertex attributes for (GLuint attr_index = 0; attr_index < (GLuint)_sg.limits.max_vertex_attrs; attr_index++) { - _sg_gl_attr_t* attr = &pip->gl.attrs[attr_index]; + _sg_gl_attr_t* attr = &bnd->pip->gl.attrs[attr_index]; _sg_gl_cache_attr_t* cache_attr = &_sg.gl.cache.attrs[attr_index]; bool cache_attr_dirty = false; int vb_offset = 0; GLuint gl_vb = 0; if (attr->vb_index >= 0) { // attribute is enabled - SOKOL_ASSERT(attr->vb_index < num_vbs); - _sg_buffer_t* vb = vbs[attr->vb_index]; + SOKOL_ASSERT(attr->vb_index < bnd->num_vbs); + _sg_buffer_t* vb = bnd->vbs[attr->vb_index]; SOKOL_ASSERT(vb); gl_vb = vb->gl.buf[vb->cmn.active_slot]; - vb_offset = vb_offsets[attr->vb_index] + attr->offset; + vb_offset = bnd->vb_offsets[attr->vb_index] + attr->offset; if ((gl_vb != cache_attr->gl_vbuf) || (attr->size != cache_attr->gl_attr.size) || (attr->type != cache_attr->gl_attr.type) || @@ -8233,9 +8226,7 @@ _SOKOL_PRIVATE bool _sg_gl_apply_bindings( (cache_attr->gl_attr.divisor != attr->divisor)) { _sg_gl_cache_bind_buffer(GL_ARRAY_BUFFER, gl_vb); - glVertexAttribPointer(attr_index, attr->size, attr->type, - attr->normalized, attr->stride, - (const GLvoid*)(GLintptr)vb_offset); + glVertexAttribPointer(attr_index, attr->size, attr->type, attr->normalized, attr->stride, (const GLvoid*)(GLintptr)vb_offset); glVertexAttribDivisor(attr_index, (GLuint)attr->divisor); cache_attr_dirty = true; } @@ -10136,50 +10127,43 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_pipeline(_sg_pipeline_t* pip) { _sg_d3d11_PSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_FS].cbufs); } -_SOKOL_PRIVATE bool _sg_d3d11_apply_bindings( - _sg_pipeline_t* pip, - _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, - _sg_buffer_t* ib, int ib_offset, - _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_image_t** fs_imgs, int num_fs_imgs, - _sg_sampler_t** vs_smps, int num_vs_smps, - _sg_sampler_t** fs_smps, int num_fs_smps) -{ - SOKOL_ASSERT(pip); +_SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_t* bnd) { + SOKOL_ASSERT(bnd); + SOKOL_ASSERT(bnd->pip); SOKOL_ASSERT(_sg.d3d11.ctx); SOKOL_ASSERT(_sg.d3d11.in_pass); // gather all the D3D11 resources into arrays - ID3D11Buffer* d3d11_ib = ib ? ib->d3d11.buf : 0; + ID3D11Buffer* d3d11_ib = bnd->ib ? ib->d3d11.buf : 0; ID3D11Buffer* d3d11_vbs[SG_MAX_VERTEX_BUFFERS] = {0}; UINT d3d11_vb_offsets[SG_MAX_VERTEX_BUFFERS] = {0}; ID3D11ShaderResourceView* d3d11_vs_srvs[SG_MAX_SHADERSTAGE_IMAGES] = {0}; ID3D11ShaderResourceView* d3d11_fs_srvs[SG_MAX_SHADERSTAGE_IMAGES] = {0}; ID3D11SamplerState* d3d11_vs_smps[SG_MAX_SHADERSTAGE_SAMPLERS] = {0}; ID3D11SamplerState* d3d11_fs_smps[SG_MAX_SHADERSTAGE_SAMPLERS] = {0}; - for (int i = 0; i < num_vbs; i++) { - SOKOL_ASSERT(vbs[i]->d3d11.buf); - d3d11_vbs[i] = vbs[i]->d3d11.buf; - d3d11_vb_offsets[i] = (UINT)vb_offsets[i]; + for (int i = 0; i < bnd->num_vbs; i++) { + SOKOL_ASSERT(bnd->vbs[i]->d3d11.buf); + d3d11_vbs[i] = bnd->vbs[i]->d3d11.buf; + d3d11_vb_offsets[i] = (UINT)bnd->vb_offsets[i]; } - for (int i = 0; i < num_vs_imgs; i++) { - SOKOL_ASSERT(vs_imgs[i]->d3d11.srv); - d3d11_vs_srvs[i] = vs_imgs[i]->d3d11.srv; + for (int i = 0; i < bnd->num_vs_imgs; i++) { + SOKOL_ASSERT(bnd->vs_imgs[i]->d3d11.srv); + d3d11_vs_srvs[i] = bnd->vs_imgs[i]->d3d11.srv; } - for (int i = 0; i < num_fs_imgs; i++) { - SOKOL_ASSERT(fs_imgs[i]->d3d11.srv); - d3d11_fs_srvs[i] = fs_imgs[i]->d3d11.srv; + for (int i = 0; i < bnd->num_fs_imgs; i++) { + SOKOL_ASSERT(bnd->fs_imgs[i]->d3d11.srv); + d3d11_fs_srvs[i] = bnd->fs_imgs[i]->d3d11.srv; } - for (int i = 0; i < num_vs_smps; i++) { - SOKOL_ASSERT(vs_smps[i]->d3d11.smp); - d3d11_vs_smps[i] = vs_smps[i]->d3d11.smp; + for (int i = 0; i < bnd->num_vs_smps; i++) { + SOKOL_ASSERT(bnd->vs_smps[i]->d3d11.smp); + d3d11_vs_smps[i] = bnd->vs_smps[i]->d3d11.smp; } - for (int i = 0; i < num_fs_smps; i++) { - SOKOL_ASSERT(fs_smps[i]->d3d11.smp); - d3d11_fs_smps[i] = fs_smps[i]->d3d11.smp; + for (int i = 0; i < bnd->num_fs_smps; i++) { + SOKOL_ASSERT(bnd->fs_smps[i]->d3d11.smp); + d3d11_fs_smps[i] = bnd->fs_smps[i]->d3d11.smp; } - _sg_d3d11_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_VERTEX_BUFFERS, d3d11_vbs, pip->d3d11.vb_strides, d3d11_vb_offsets); - _sg_d3d11_IASetIndexBuffer(_sg.d3d11.ctx, d3d11_ib, pip->d3d11.index_format, (UINT)ib_offset); + _sg_d3d11_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_VERTEX_BUFFERS, d3d11_vbs, bnd->pip->d3d11.vb_strides, d3d11_vb_offsets); + _sg_d3d11_IASetIndexBuffer(_sg.d3d11.ctx, d3d11_ib, pip->d3d11.index_format, (UINT)bnd->ib_offset); _sg_d3d11_VSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_vs_srvs); _sg_d3d11_PSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_fs_srvs); _sg_d3d11_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_SAMPLERS, d3d11_vs_smps); @@ -11819,53 +11803,47 @@ _SOKOL_PRIVATE void _sg_mtl_apply_pipeline(_sg_pipeline_t* pip) { } } -_SOKOL_PRIVATE bool _sg_mtl_apply_bindings( - _sg_pipeline_t* pip, - _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, - _sg_buffer_t* ib, int ib_offset, - _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_image_t** fs_imgs, int num_fs_imgs, - _sg_sampler_t** vs_smps, int num_vs_smps, - _sg_sampler_t** fs_smps, int num_fs_smps) -{ - _SOKOL_UNUSED(pip); +_SOKOL_PRIVATE bool _sg_mtl_apply_bindings(_sg_bindings_t* bnd) { + SOKOL_ASSERT(bnd); + SOKOL_ASSERT(bnd->pip); SOKOL_ASSERT(_sg.mtl.in_pass); if (!_sg.mtl.pass_valid) { - return; + return false; } SOKOL_ASSERT(nil != _sg.mtl.cmd_encoder); // store index buffer binding, this will be needed later in sg_draw() - _sg.mtl.state_cache.cur_indexbuffer = ib; - _sg.mtl.state_cache.cur_indexbuffer_offset = ib_offset; - if (ib) { - SOKOL_ASSERT(pip->cmn.index_type != SG_INDEXTYPE_NONE); - _sg.mtl.state_cache.cur_indexbuffer_id.id = ib->slot.id; + _sg.mtl.state_cache.cur_indexbuffer = bnd->ib; + _sg.mtl.state_cache.cur_indexbuffer_offset = bnd->ib_offset; + if (bnd->ib) { + SOKOL_ASSERT(bnd->pip->cmn.index_type != SG_INDEXTYPE_NONE); + _sg.mtl.state_cache.cur_indexbuffer_id.id = bnd->ib->slot.id; } else { - SOKOL_ASSERT(pip->cmn.index_type == SG_INDEXTYPE_NONE); + SOKOL_ASSERT(bnd->pip->cmn.index_type == SG_INDEXTYPE_NONE); _sg.mtl.state_cache.cur_indexbuffer_id.id = SG_INVALID_ID; } // apply vertex buffers - for (NSUInteger slot = 0; slot < (NSUInteger)num_vbs; slot++) { - const _sg_buffer_t* vb = vbs[slot]; + for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_vbs; slot++) { + const _sg_buffer_t* vb = bnd->vbs[slot]; + const int vb_offset = bnd->vb_offsets[slot]; if ((_sg.mtl.state_cache.cur_vertexbuffer_ids[slot].id != vb->slot.id) || - (_sg.mtl.state_cache.cur_vertexbuffer_offsets[slot] != vb_offsets[slot])) + (_sg.mtl.state_cache.cur_vertexbuffer_offsets[slot] != vb_offset)) { _sg.mtl.state_cache.cur_vertexbuffers[slot] = vb; - _sg.mtl.state_cache.cur_vertexbuffer_offsets[slot] = vb_offsets[slot]; + _sg.mtl.state_cache.cur_vertexbuffer_offsets[slot] = vb_offset; _sg.mtl.state_cache.cur_vertexbuffer_ids[slot].id = vb->slot.id; const NSUInteger mtl_slot = SG_MAX_SHADERSTAGE_UBS + slot; SOKOL_ASSERT(vb->mtl.buf[vb->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX); [_sg.mtl.cmd_encoder setVertexBuffer:_sg_mtl_id(vb->mtl.buf[vb->cmn.active_slot]) - offset:(NSUInteger)vb_offsets[slot] + offset:(NSUInteger)vb_offset atIndex:mtl_slot]; } } // apply vertex shader images - for (NSUInteger slot = 0; slot < (NSUInteger)num_vs_imgs; slot++) { - const _sg_image_t* img = vs_imgs[slot]; + for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_vs_imgs; slot++) { + const _sg_image_t* img = bnd->vs_imgs[slot]; if (_sg.mtl.state_cache.cur_vs_image_ids[slot].id != img->slot.id) { _sg.mtl.state_cache.cur_vs_images[slot] = img; _sg.mtl.state_cache.cur_vs_image_ids[slot].id = img->slot.id; @@ -11874,20 +11852,9 @@ _SOKOL_PRIVATE bool _sg_mtl_apply_bindings( } } - // apply fragment shader images - for (NSUInteger slot = 0; slot < (NSUInteger)num_fs_imgs; slot++) { - const _sg_image_t* img = fs_imgs[slot]; - if (_sg.mtl.state_cache.cur_fs_image_ids[slot].id != img->slot.id) { - _sg.mtl.state_cache.cur_fs_images[slot] = img; - _sg.mtl.state_cache.cur_fs_image_ids[slot].id = img->slot.id; - SOKOL_ASSERT(img->mtl.tex[img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX); - [_sg.mtl.cmd_encoder setFragmentTexture:_sg_mtl_id(img->mtl.tex[img->cmn.active_slot]) atIndex:slot]; - } - } - // apply vertex shader samplers - for (NSUInteger slot = 0; slot < (NSUInteger)num_vs_smps; slot++) { - const _sg_sampler_t* smp = vs_smps[slot]; + for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_vs_smps; slot++) { + const _sg_sampler_t* smp = bnd->vs_smps[slot]; if (_sg.mtl.state_cache.cur_vs_sampler_ids[slot].id != smp->slot.id) { _sg.mtl.state_cache.cur_vs_samplers[slot] = smp; _sg.mtl.state_cache.cur_vs_sampler_ids[slot].id = smp->slot.id; @@ -11896,9 +11863,20 @@ _SOKOL_PRIVATE bool _sg_mtl_apply_bindings( } } + // apply fragment shader images + for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_fs_imgs; slot++) { + const _sg_image_t* img = bnd->fs_imgs[slot]; + if (_sg.mtl.state_cache.cur_fs_image_ids[slot].id != img->slot.id) { + _sg.mtl.state_cache.cur_fs_images[slot] = img; + _sg.mtl.state_cache.cur_fs_image_ids[slot].id = img->slot.id; + SOKOL_ASSERT(img->mtl.tex[img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX); + [_sg.mtl.cmd_encoder setFragmentTexture:_sg_mtl_id(img->mtl.tex[img->cmn.active_slot]) atIndex:slot]; + } + } + // apply fragment shader samplers - for (NSUInteger slot = 0; slot < (NSUInteger)num_fs_smps; slot++) { - const _sg_sampler_t* smp = fs_smps[slot]; + for (NSUInteger slot = 0; slot < (NSUInteger)bnd->num_fs_smps; slot++) { + const _sg_sampler_t* smp = bnd->fs_smps[slot]; if (_sg.mtl.state_cache.cur_fs_sampler_ids[slot].id != smp->slot.id) { _sg.mtl.state_cache.cur_fs_samplers[slot] = smp; _sg.mtl.state_cache.cur_fs_sampler_ids[slot].id = smp->slot.id; @@ -12631,41 +12609,36 @@ _SOKOL_PRIVATE uint64_t _sg_wgpu_hash(void* ptr, size_t num_bytes) { return 0; } -_SOKOL_PRIVATE void _sg_wgpu_init_bindgroupscache_key(_sg_wgpu_bindgroupscache_key_t* key, - _sg_pipeline_t* pip, - _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_sampler_t** vs_smps, int num_vs_smps, - _sg_image_t** fs_imgs, int num_fs_imgs, - _sg_sampler_t** fs_smps, int num_fs_smps) -{ - SOKOL_ASSERT(pip); - SOKOL_ASSERT(vs_imgs && (num_vs_imgs <= SG_MAX_SHADERSTAGE_IMAGES)); - SOKOL_ASSERT(vs_smps && (num_vs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS)); - SOKOL_ASSERT(fs_imgs && (num_fs_imgs <= SG_MAX_SHADERSTAGE_IMAGES)); - SOKOL_ASSERT(fs_smps && (num_fs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS)); +_SOKOL_PRIVATE void _sg_wgpu_init_bindgroupscache_key(_sg_wgpu_bindgroupscache_key_t* key, const _sg_bindings_t* bnd) { + SOKOL_ASSERT(bnd); + SOKOL_ASSERT(bnd->pip); + SOKOL_ASSERT(bnd->num_vs_imgs <= SG_MAX_SHADERSTAGE_IMAGES); + SOKOL_ASSERT(bnd->num_vs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS); + SOKOL_ASSERT(bnd->num_fs_imgs <= SG_MAX_SHADERSTAGE_IMAGES); + SOKOL_ASSERT(bnd->num_fs_smps <= SG_MAX_SHADERSTAGE_SAMPLERS); _sg_clear(key->items, sizeof(key->items)); - key->items[0] = pip->slot.id; + key->items[0] = bnd->pip->slot.id; const int vs_imgs_offset = 1; const int vs_smps_offset = vs_imgs_offset + SG_MAX_SHADERSTAGE_IMAGES; const int fs_imgs_offset = vs_smps_offset + SG_MAX_SHADERSTAGE_SAMPLERS; const int fs_smps_offset = fs_imgs_offset + SG_MAX_SHADERSTAGE_IMAGES; SOKOL_ASSERT((fs_smps_offset + SG_MAX_SHADERSTAGE_SAMPLERS) == _SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS); - for (int i = 0; i < num_vs_imgs; i++) { - SOKOL_ASSERT(vs_imgs[i]); - key->items[vs_imgs_offset + i] = vs_imgs[i]->slot.id; + for (int i = 0; i < bnd->num_vs_imgs; i++) { + SOKOL_ASSERT(bnd->vs_imgs[i]); + key->items[vs_imgs_offset + i] = bnd->vs_imgs[i]->slot.id; } - for (int i = 0; i < num_vs_smps; i++) { - SOKOL_ASSERT(vs_smps[i]); - key->items[vs_smps_offset + i] = vs_smps[i]->slot.id; + for (int i = 0; i < bnd->num_vs_smps; i++) { + SOKOL_ASSERT(bnd->vs_smps[i]); + key->items[vs_smps_offset + i] = bnd->vs_smps[i]->slot.id; } - for (int i = 0; i < num_fs_imgs; i++) { - SOKOL_ASSERT(fs_imgs[i]); - key->items[fs_imgs_offset + i] = fs_imgs[i]->slot.id; + for (int i = 0; i < bnd->num_fs_imgs; i++) { + SOKOL_ASSERT(bnd->fs_imgs[i]); + key->items[fs_imgs_offset + i] = bnd->fs_imgs[i]->slot.id; } - for (int i = 0; i < num_fs_smps; i++) { - SOKOL_ASSERT(fs_smps[i]); - key->items[fs_smps_offset + i] = fs_smps[i]->slot.id; + for (int i = 0; i < bnd->num_fs_smps; i++) { + SOKOL_ASSERT(bnd->fs_smps[i]); + key->items[fs_smps_offset + i] = bnd->fs_smps[i]->slot.id; } key->hash = _sg_wgpu_hash(&key->items, sizeof(key->items)); } @@ -12681,16 +12654,10 @@ _SOKOL_PRIVATE bool _sg_wgpu_compare_bindgroupscache_key(_sg_wgpu_bindgroupscach return true; } -_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup( - _sg_pipeline_t* pip, - _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_sampler_t** vs_smps, int num_vs_smps, - _sg_image_t** fs_imgs, int num_fs_imgs, - _sg_sampler_t** fs_smps, int num_fs_smps) -{ +_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup(_sg_bindings_t* bnd) { SOKOL_ASSERT(_sg.wgpu.dev); - SOKOL_ASSERT(pip); - SOKOL_ASSERT(pip->shader && (pip->cmn.shader_id.id == pip->shader->slot.id)); + SOKOL_ASSERT(bnd->pip); + SOKOL_ASSERT(bnd->pip->shader && (bnd->pip->cmn.shader_id.id == bnd->pip->shader->slot.id)); _sg_wgpu_bindgroup_handle_t bg_id = _sg_wgpu_alloc_bindgroup(&_sg.wgpu.bindgroups_pool); if (bg_id.id == SG_INVALID_ID) { return 0; @@ -12699,30 +12666,30 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup( SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_ALLOC)); // create wgpu bindgroup object - WGPUBindGroupLayout bgl = pip->shader->wgpu.bind_group_layout; + WGPUBindGroupLayout bgl = bnd->pip->shader->wgpu.bind_group_layout; SOKOL_ASSERT(bgl); WGPUBindGroupEntry wgpu_entries[SG_NUM_SHADER_STAGES * SG_MAX_SHADERSTAGE_IMAGES + SG_MAX_SHADERSTAGE_SAMPLERS]; _sg_clear(&wgpu_entries, sizeof(wgpu_entries)); int bge_index = 0; - for (int i = 0; i < num_vs_imgs; i++) { + for (int i = 0; i < bnd->num_vs_imgs; i++) { WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; wgpu_entry->binding = _sg_wgpu_image_binding(SG_SHADERSTAGE_VS, i); - wgpu_entry->textureView = vs_imgs[i]->wgpu.view; + wgpu_entry->textureView = bnd->vs_imgs[i]->wgpu.view; } - for (int i = 0; i < num_vs_smps; i++) { + for (int i = 0; i < bnd->num_vs_smps; i++) { WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; wgpu_entry->binding = _sg_wgpu_sampler_binding(SG_SHADERSTAGE_VS, i); - wgpu_entry->sampler = vs_smps[i]->wgpu.smp; + wgpu_entry->sampler = bnd->vs_smps[i]->wgpu.smp; } - for (int i = 0; i < num_fs_imgs; i++) { + for (int i = 0; i < bnd->num_fs_imgs; i++) { WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; wgpu_entry->binding = _sg_wgpu_image_binding(SG_SHADERSTAGE_FS, i); - wgpu_entry->textureView = fs_imgs[i]->wgpu.view; + wgpu_entry->textureView = bnd->fs_imgs[i]->wgpu.view; } - for (int i = 0; i < num_fs_smps; i++) { + for (int i = 0; i < bnd->num_fs_smps; i++) { WGPUBindGroupEntry* wgpu_entry = &wgpu_entries[bge_index++]; wgpu_entry->binding = _sg_wgpu_sampler_binding(SG_SHADERSTAGE_FS, i); - wgpu_entry->sampler = fs_smps[i]->wgpu.smp; + wgpu_entry->sampler = bnd->fs_smps[i]->wgpu.smp; } WGPUBindGroupDescriptor bg_desc; _sg_clear(&bg_desc, sizeof(bg_desc)); @@ -12736,7 +12703,7 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup( return bg; } - _sg_wgpu_init_bindgroupscache_key(&bg->key, pip, vs_imgs, num_vs_imgs, vs_smps, num_vs_smps, fs_imgs, num_fs_imgs, fs_smps, num_fs_smps); + _sg_wgpu_init_bindgroupscache_key(&bg->key, bnd); bg->slot.state = SG_RESOURCESTATE_VALID; return bg; @@ -12793,16 +12760,10 @@ _SOKOL_PRIVATE void _sg_wgpu_bindcache_ib_update(const _sg_buffer_t* ib, int ib_ _sg.wgpu.bindings_cache.ib.offset = ib_offset; } -_SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup( - _sg_pipeline_t* pip, - _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_sampler_t** vs_smps, int num_vs_smps, - _sg_image_t** fs_imgs, int num_fs_imgs, - _sg_sampler_t** fs_smps, int num_fs_smps) -{ - if ((num_vs_imgs + num_vs_smps + num_fs_imgs + num_fs_smps) > 0) { +_SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { + if ((bnd->num_vs_imgs + bnd->num_vs_smps + bnd->num_fs_imgs + bnd->num_fs_smps) > 0) { // FIXME: use bindgroups cache! - _sg_wgpu_bindgroup_t* bg = _sg_wgpu_create_bindgroup(pip, vs_imgs, num_vs_imgs, vs_smps, num_vs_smps, fs_imgs, num_fs_imgs, fs_smps, num_fs_smps); + _sg_wgpu_bindgroup_t* bg = _sg_wgpu_create_bindgroup(bnd); if (bg) { if (bg->slot.state == SG_RESOURCESTATE_VALID) { SOKOL_ASSERT(bg->bindgroup); @@ -13608,48 +13569,41 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_pipeline(_sg_pipeline_t* pip) { wgpuRenderPassEncoderSetStencilReference(_sg.wgpu.pass_enc, pip->cmn.stencil.ref); } -_SOKOL_PRIVATE bool _sg_wgpu_apply_bindings( - _sg_pipeline_t* pip, - _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, - _sg_buffer_t* ib, int ib_offset, - _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_image_t** fs_imgs, int num_fs_imgs, - _sg_sampler_t** vs_smps, int num_vs_smps, - _sg_sampler_t** fs_smps, int num_fs_smps) -{ +_SOKOL_PRIVATE bool _sg_wgpu_apply_bindings(_sg_bindings_t* bnd) { SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); - SOKOL_ASSERT(pip->shader && (pip->cmn.shader_id.id == pip->shader->slot.id)); + SOKOL_ASSERT(bnd); + SOKOL_ASSERT(bnd->pip->shader && (bnd->pip->cmn.shader_id.id == bnd->pip->shader->slot.id)); bool retval = true; // index buffer - if (ib) { - if (_sg_wgpu_bindcache_ib_dirty(ib, ib_offset)) { - _sg_wgpu_bindcache_ib_update(ib, ib_offset); - const WGPUIndexFormat format = _sg_wgpu_indexformat(pip->cmn.index_type); - const uint64_t buf_size = (uint64_t)ib->cmn.size; - const uint64_t offset = (uint64_t)ib_offset; + if (bnd->ib) { + if (_sg_wgpu_bindcache_ib_dirty(bnd->ib, bnd->ib_offset)) { + _sg_wgpu_bindcache_ib_update(bnd->ib, bnd->ib_offset); + const WGPUIndexFormat format = _sg_wgpu_indexformat(bnd->pip->cmn.index_type); + const uint64_t buf_size = (uint64_t)bnd->ib->cmn.size; + const uint64_t offset = (uint64_t)bnd->ib_offset; SOKOL_ASSERT(buf_size > offset); const uint64_t max_bytes = buf_size - offset; - wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, ib->wgpu.buf, format, offset, max_bytes); + wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, bnd->ib->wgpu.buf, format, offset, max_bytes); } } // FIXME: else-path should actually set a null index buffer (this was just recently implemented in WebGPU) // vertex buffers - for (int slot = 0; slot < num_vbs; slot++) { - if (_sg_wgpu_bindcache_vb_dirty(slot, vbs[slot], vb_offsets[slot])) { - _sg_wgpu_bindcache_vb_update(slot, vbs[slot], vb_offsets[slot]); - const uint64_t buf_size = (uint64_t)vbs[slot]->cmn.size; - const uint64_t offset = (uint64_t)vb_offsets[slot]; + for (int slot = 0; slot < bnd->num_vbs; slot++) { + if (_sg_wgpu_bindcache_vb_dirty(slot, bnd->vbs[slot], bnd->vb_offsets[slot])) { + _sg_wgpu_bindcache_vb_update(slot, bnd->vbs[slot], bnd->vb_offsets[slot]); + const uint64_t buf_size = (uint64_t)bnd->vbs[slot]->cmn.size; + const uint64_t offset = (uint64_t)bnd->vb_offsets[slot]; SOKOL_ASSERT(buf_size > offset); const uint64_t max_bytes = buf_size - offset; - wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, (uint32_t)slot, vbs[slot]->wgpu.buf, offset, max_bytes); + wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, (uint32_t)slot, bnd->vbs[slot]->wgpu.buf, offset, max_bytes); } // FIXME: else-path should actually set a null vertex buffer (this was just recently implemented in WebGPU) } - _sg_wgpu_apply_bindgroup(pip, vs_imgs, num_vs_imgs, vs_smps, num_vs_smps, fs_imgs, num_fs_imgs, fs_smps, num_fs_smps); + _sg_wgpu_apply_bindgroup(bnd); return retval; } @@ -14130,25 +14084,17 @@ static inline void _sg_apply_pipeline(_sg_pipeline_t* pip) { #endif } -static inline bool _sg_apply_bindings( - _sg_pipeline_t* pip, - _sg_buffer_t** vbs, const int* vb_offsets, int num_vbs, - _sg_buffer_t* ib, int ib_offset, - _sg_image_t** vs_imgs, int num_vs_imgs, - _sg_image_t** fs_imgs, int num_fs_imgs, - _sg_sampler_t** vs_smps, int num_vs_smps, - _sg_sampler_t** fs_smps, int num_fs_smps) -{ +static inline bool _sg_apply_bindings(_sg_bindings_t* bnd) { #if defined(_SOKOL_ANY_GL) - return _sg_gl_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + return _sg_gl_apply_bindings(bnd); #elif defined(SOKOL_METAL) - return _sg_mtl_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + return _sg_mtl_apply_bindings(bnd); #elif defined(SOKOL_D3D11) - return _sg_d3d11_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + return _sg_d3d11_apply_bindings(bnd); #elif defined(SOKOL_WGPU) - return _sg_wgpu_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + return _sg_wgpu_apply_bindings(bnd); #elif defined(SOKOL_DUMMY_BACKEND) - return _sg_dummy_apply_bindings(pip, vbs, vb_offsets, num_vbs, ib, ib_offset, vs_imgs, num_vs_imgs, fs_imgs, num_fs_imgs, vs_smps, num_vs_smps, fs_smps, num_fs_smps); + return _sg_dummy_apply_bindings(bnd); #else #error("INVALID BACKEND"); #endif @@ -16869,7 +16815,7 @@ SOKOL_API_IMPL void sg_apply_scissor_rectf(float x, float y, float width, float SOKOL_API_IMPL void sg_apply_pipeline(sg_pipeline pip_id) { SOKOL_ASSERT(_sg.valid); - _sg.bindings_valid = false; + _sg.bindings_applied = false; if (!_sg_validate_apply_pipeline(pip_id)) { _sg.next_draw_valid = false; return; @@ -16894,91 +16840,95 @@ SOKOL_API_IMPL void sg_apply_bindings(const sg_bindings* bindings) { _sg.next_draw_valid = false; return; } - _sg.bindings_valid = true; + _sg.bindings_applied = true; - _sg_pipeline_t* pip = _sg_lookup_pipeline(&_sg.pools, _sg.cur_pipeline.id); - SOKOL_ASSERT(pip); + _sg_bindings_t bnd; + _sg_clear(&bnd, sizeof(bnd)); + bnd.pip = _sg_lookup_pipeline(&_sg.pools, _sg.cur_pipeline.id); + if (0 == bnd.pip) { + _sg.next_draw_valid = false; + } - _sg_buffer_t* vbs[SG_MAX_VERTEX_BUFFERS] = { 0 }; - int num_vbs = 0; - for (int i = 0; i < SG_MAX_VERTEX_BUFFERS; i++, num_vbs++) { + for (int i = 0; i < SG_MAX_VERTEX_BUFFERS; i++, bnd.num_vbs++) { if (bindings->vertex_buffers[i].id) { - vbs[i] = _sg_lookup_buffer(&_sg.pools, bindings->vertex_buffers[i].id); - SOKOL_ASSERT(vbs[i]); - _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == vbs[i]->slot.state); - _sg.next_draw_valid &= !vbs[i]->cmn.append_overflow; + bnd.vbs[i] = _sg_lookup_buffer(&_sg.pools, bindings->vertex_buffers[i].id); + bnd.vb_offsets[i] = bindings->vertex_buffer_offsets[i]; + if (bnd.vbs[i]) { + _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.vbs[i]->slot.state); + _sg.next_draw_valid &= !bnd.vbs[i]->cmn.append_overflow; + } else { + _sg.next_draw_valid = false; + } } else { break; } } - _sg_buffer_t* ib = 0; if (bindings->index_buffer.id) { - ib = _sg_lookup_buffer(&_sg.pools, bindings->index_buffer.id); - SOKOL_ASSERT(ib); - _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == ib->slot.state); - _sg.next_draw_valid &= !ib->cmn.append_overflow; + bnd.ib = _sg_lookup_buffer(&_sg.pools, bindings->index_buffer.id); + bnd.ib_offset = bindings->index_buffer_offset; + if (bnd.ib) { + _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.ib->slot.state); + _sg.next_draw_valid &= !bnd.ib->cmn.append_overflow; + } else { + _sg.next_draw_valid = false; + } } - _sg_image_t* vs_imgs[SG_MAX_SHADERSTAGE_IMAGES] = { 0 }; - int num_vs_imgs = 0; - for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++, num_vs_imgs++) { + for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++, bnd.num_vs_imgs++) { if (bindings->vs.images[i].id) { - vs_imgs[i] = _sg_lookup_image(&_sg.pools, bindings->vs.images[i].id); - SOKOL_ASSERT(vs_imgs[i]); - _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == vs_imgs[i]->slot.state); + bnd.vs_imgs[i] = _sg_lookup_image(&_sg.pools, bindings->vs.images[i].id); + if (bnd.vs_imgs[i]) { + _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.vs_imgs[i]->slot.state); + } else { + _sg.next_draw_valid = false; + } } else { break; } } - _sg_image_t* fs_imgs[SG_MAX_SHADERSTAGE_IMAGES] = { 0 }; - int num_fs_imgs = 0; - for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++, num_fs_imgs++) { - if (bindings->fs.images[i].id) { - fs_imgs[i] = _sg_lookup_image(&_sg.pools, bindings->fs.images[i].id); - SOKOL_ASSERT(fs_imgs[i]); - _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == fs_imgs[i]->slot.state); + for (int i = 0; i < SG_MAX_SHADERSTAGE_SAMPLERS; i++, bnd.num_vs_smps++) { + if (bindings->vs.samplers[i].id) { + bnd.vs_smps[i] = _sg_lookup_sampler(&_sg.pools, bindings->vs.samplers[i].id); + if (bnd.vs_smps[i]) { + _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.vs_smps[i]->slot.state); + } else { + _sg.next_draw_valid = false; + } } else { break; } } - _sg_sampler_t* vs_smps[SG_MAX_SHADERSTAGE_SAMPLERS] = { 0 }; - int num_vs_smps = 0; - for (int i = 0; i < SG_MAX_SHADERSTAGE_SAMPLERS; i++, num_vs_smps++) { - if (bindings->vs.samplers[i].id) { - vs_smps[i] = _sg_lookup_sampler(&_sg.pools, bindings->vs.samplers[i].id); - SOKOL_ASSERT(vs_smps[i]); - _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == vs_smps[i]->slot.state); + for (int i = 0; i < SG_MAX_SHADERSTAGE_IMAGES; i++, bnd.num_fs_imgs++) { + if (bindings->fs.images[i].id) { + bnd.fs_imgs[i] = _sg_lookup_image(&_sg.pools, bindings->fs.images[i].id); + if (bnd.fs_imgs[i]) { + _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.fs_imgs[i]->slot.state); + } else { + _sg.next_draw_valid = false; + } } else { break; } } - _sg_sampler_t* fs_smps[SG_MAX_SHADERSTAGE_SAMPLERS] = { 0 }; - int num_fs_smps = 0; - for (int i = 0; i < SG_MAX_SHADERSTAGE_SAMPLERS; i++, num_fs_smps++) { + for (int i = 0; i < SG_MAX_SHADERSTAGE_SAMPLERS; i++, bnd.num_fs_smps++) { if (bindings->fs.samplers[i].id) { - fs_smps[i] = _sg_lookup_sampler(&_sg.pools, bindings->fs.samplers[i].id); - SOKOL_ASSERT(fs_smps[i]); - _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == fs_smps[i]->slot.state); + bnd.fs_smps[i] = _sg_lookup_sampler(&_sg.pools, bindings->fs.samplers[i].id); + if (bnd.fs_smps[i]) { + _sg.next_draw_valid &= (SG_RESOURCESTATE_VALID == bnd.fs_smps[i]->slot.state); + } else { + _sg.next_draw_valid = false; + } } else { break; } } if (_sg.next_draw_valid) { - const int* vb_offsets = bindings->vertex_buffer_offsets; - int ib_offset = bindings->index_buffer_offset; - _sg.next_draw_valid = _sg_apply_bindings( - pip, - vbs, vb_offsets, num_vbs, - ib, ib_offset, - vs_imgs, num_vs_imgs, - fs_imgs, num_fs_imgs, - vs_smps, num_vs_smps, - fs_smps, num_fs_smps); + _sg.next_draw_valid &= _sg_apply_bindings(&bnd); _SG_TRACE_ARGS(apply_bindings, bindings); } } @@ -17008,7 +16958,7 @@ SOKOL_API_IMPL void sg_draw(int base_element, int num_elements, int num_instance SOKOL_ASSERT(num_elements >= 0); SOKOL_ASSERT(num_instances >= 0); #if defined(SOKOL_DEBUG) - if (!_sg.bindings_valid) { + if (!_sg.bindings_applied) { _SG_WARN(DRAW_WITHOUT_BINDINGS); } #endif @@ -17018,7 +16968,7 @@ SOKOL_API_IMPL void sg_draw(int base_element, int num_elements, int num_instance if (!_sg.next_draw_valid) { return; } - if (!_sg.bindings_valid) { + if (!_sg.bindings_applied) { return; } /* attempting to draw with zero elements or instances is not technically an From 60cb9f409553c3473090a0cb203a87d7afb38aa0 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 30 Sep 2023 13:44:49 +0200 Subject: [PATCH 59/95] sokol_gfx.h d3d11: fix compile errors --- sokol_gfx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index c453a6cad..0bdefcd5c 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -10134,7 +10134,7 @@ _SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_t* bnd) { SOKOL_ASSERT(_sg.d3d11.in_pass); // gather all the D3D11 resources into arrays - ID3D11Buffer* d3d11_ib = bnd->ib ? ib->d3d11.buf : 0; + ID3D11Buffer* d3d11_ib = bnd->ib ? bnd->ib->d3d11.buf : 0; ID3D11Buffer* d3d11_vbs[SG_MAX_VERTEX_BUFFERS] = {0}; UINT d3d11_vb_offsets[SG_MAX_VERTEX_BUFFERS] = {0}; ID3D11ShaderResourceView* d3d11_vs_srvs[SG_MAX_SHADERSTAGE_IMAGES] = {0}; @@ -10163,7 +10163,7 @@ _SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_t* bnd) { d3d11_fs_smps[i] = bnd->fs_smps[i]->d3d11.smp; } _sg_d3d11_IASetVertexBuffers(_sg.d3d11.ctx, 0, SG_MAX_VERTEX_BUFFERS, d3d11_vbs, bnd->pip->d3d11.vb_strides, d3d11_vb_offsets); - _sg_d3d11_IASetIndexBuffer(_sg.d3d11.ctx, d3d11_ib, pip->d3d11.index_format, (UINT)bnd->ib_offset); + _sg_d3d11_IASetIndexBuffer(_sg.d3d11.ctx, d3d11_ib, bnd->pip->d3d11.index_format, (UINT)bnd->ib_offset); _sg_d3d11_VSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_vs_srvs); _sg_d3d11_PSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_fs_srvs); _sg_d3d11_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_SAMPLERS, d3d11_vs_smps); From 7e15e72639e6f2b5d636072e0866cb63a4fbd44c Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 30 Sep 2023 17:38:40 +0200 Subject: [PATCH 60/95] sokol_gfx.h wgpu: implement bindgroups cache --- sokol_gfx.h | 188 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 150 insertions(+), 38 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 0bdefcd5c..adf860bd8 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2904,7 +2904,9 @@ typedef struct sg_pass_info { _SG_LOGITEM_XMACRO(METAL_FRAGMENT_SHADER_ENTRY_NOT_FOUND, "fragment shader entry not found (metal)") \ _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_FAILED, "failed to create render pipeline state (metal)") \ _SG_LOGITEM_XMACRO(METAL_CREATE_RPS_OUTPUT, "") \ - _SG_LOGITEM_XMACRO(WGPU_BINDGROUPS_POOL_EXHAUSTED, "wgpu BindGroups pool exhausted (increase sg_desc.bindgroups_cache_size)") \ + _SG_LOGITEM_XMACRO(WGPU_BINDGROUPS_POOL_EXHAUSTED, "bindgroups pool exhausted (increase sg_desc.bindgroups_cache_size) (wgpu)") \ + _SG_LOGITEM_XMACRO(WGPU_BINDGROUPSCACHE_SIZE_GREATER_ONE, "sg_desc.wgpu_bindgroups_cache_size must be > 1 (wgpu)") \ + _SG_LOGITEM_XMACRO(WGPU_BINDGROUPSCACHE_SIZE_POW2, "sg_desc.wgpu_bindgroups_cache_size must be a power of 2 (wgpu)") \ _SG_LOGITEM_XMACRO(WGPU_CREATEBINDGROUP_FAILED, "wgpuDeviceCreateBindGroup failed") \ _SG_LOGITEM_XMACRO(WGPU_CREATE_BUFFER_FAILED, "wgpuDeviceCreateBuffer() failed") \ _SG_LOGITEM_XMACRO(WGPU_CREATE_TEXTURE_FAILED, "wgpuDeviceCreateTexture() failed") \ @@ -4070,6 +4072,7 @@ typedef struct { #define _sg_max(a,b) (((a)>(b))?(a):(b)) #define _sg_clamp(v,v0,v1) (((v)<(v0))?(v0):(((v)>(v1))?(v1):(v))) #define _sg_fequal(val,cmp,delta) ((((val)-(cmp))> -(delta))&&(((val)-(cmp))<(delta))) +#define _sg_ispow2(val) ((val&(val-1))==0) _SOKOL_PRIVATE void* _sg_malloc_clear(size_t size); _SOKOL_PRIVATE void _sg_free(void* ptr); @@ -4935,18 +4938,18 @@ typedef struct { typedef struct { uint64_t hash; uint32_t items[_SG_WGPU_BINDGROUPSCACHE_NUM_ITEMS]; -} _sg_wgpu_bindgroupscache_key_t; +} _sg_wgpu_bindgroups_cache_key_t; typedef struct { - size_t num; // must be 2^n - uint64_t index_mask; // mask to turn hash into valid index + uint32_t num; // must be 2^n + uint32_t index_mask; // mask to turn hash into valid index _sg_wgpu_bindgroup_handle_t* items; } _sg_wgpu_bindgroups_cache_t; typedef struct { _sg_slot_t slot; WGPUBindGroup bindgroup; - _sg_wgpu_bindgroupscache_key_t key; + _sg_wgpu_bindgroups_cache_key_t key; } _sg_wgpu_bindgroup_t; typedef struct { @@ -4963,7 +4966,6 @@ typedef struct { sg_buffer buffer; int offset; } ib; - _sg_wgpu_bindgroup_handle_t bindgroup; } _sg_wgpu_bindings_cache_t; // the WGPU backend state @@ -4990,7 +4992,7 @@ typedef struct { sg_pipeline cur_pipeline_id; _sg_wgpu_uniform_buffer_t uniform; _sg_wgpu_bindings_cache_t bindings_cache; - _sg_wgpu_bindgroups_cache_t bingroups_cache; + _sg_wgpu_bindgroups_cache_t bindgroups_cache; _sg_wgpu_bindgroups_pool_t bindgroups_pool; } _sg_wgpu_backend_t; #endif @@ -12547,29 +12549,32 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { _SOKOL_PRIVATE void _sg_wgpu_bindgroups_pool_init(const sg_desc* desc) { SOKOL_ASSERT((desc->wgpu_bindgroups_cache_size > 0) && (desc->wgpu_bindgroups_cache_size < _SG_MAX_POOL_SIZE)); - SOKOL_ASSERT(0 == _sg.wgpu.bindgroups_pool.bindgroups); + _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool; + SOKOL_ASSERT(0 == p->bindgroups); const int pool_size = desc->wgpu_bindgroups_cache_size; - _sg_init_pool(&_sg.wgpu.bindgroups_pool.pool, pool_size); + _sg_init_pool(&p->pool, pool_size); size_t pool_byte_size = sizeof(_sg_wgpu_bindgroup_t) * (size_t)pool_size; - _sg.wgpu.bindgroups_pool.bindgroups = _sg_malloc_clear(pool_byte_size); + p->bindgroups = _sg_malloc_clear(pool_byte_size); } -_SOKOL_PRIVATE void _sg_wgpu_bindgroups_pool_discard(_sg_wgpu_bindgroups_pool_t* p) { - SOKOL_ASSERT(p && p->bindgroups); +_SOKOL_PRIVATE void _sg_wgpu_bindgroups_pool_discard(void) { + _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool; + SOKOL_ASSERT(p->bindgroups); _sg_free(p->bindgroups); p->bindgroups = 0; _sg_discard_pool(&p->pool); } -_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_bindgroup_at(_sg_wgpu_bindgroups_pool_t* p, uint32_t bg_id) { - SOKOL_ASSERT(p && (SG_INVALID_ID != bg_id)); +_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_bindgroup_at(uint32_t bg_id) { + SOKOL_ASSERT(SG_INVALID_ID != bg_id); + _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool; int slot_index = _sg_slot_index(bg_id); SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < p->pool.size)); return &p->bindgroups[slot_index]; } -_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_lookup_bindgroup(_sg_wgpu_bindgroups_pool_t* p, uint32_t bg_id) { +_SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_lookup_bindgroup(uint32_t bg_id) { if (SG_INVALID_ID != bg_id) { - _sg_wgpu_bindgroup_t* bg = _sg_wgpu_bindgroup_at(p, bg_id); + _sg_wgpu_bindgroup_t* bg = _sg_wgpu_bindgroup_at(bg_id); if (bg->slot.id == bg_id) { return bg; } @@ -12577,7 +12582,8 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_lookup_bindgroup(_sg_wgpu_bindgrou return 0; } -_SOKOL_PRIVATE _sg_wgpu_bindgroup_handle_t _sg_wgpu_alloc_bindgroup(_sg_wgpu_bindgroups_pool_t* p) { +_SOKOL_PRIVATE _sg_wgpu_bindgroup_handle_t _sg_wgpu_alloc_bindgroup(void) { + _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool; _sg_wgpu_bindgroup_handle_t res; int slot_index = _sg_pool_alloc_index(&p->pool); if (_SG_INVALID_SLOT_INDEX != slot_index) { @@ -12589,8 +12595,9 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_handle_t _sg_wgpu_alloc_bindgroup(_sg_wgpu_bin return res; } -_SOKOL_PRIVATE void _sg_wgpu_dealloc_bindgroup(_sg_wgpu_bindgroups_pool_t* p, _sg_wgpu_bindgroup_t* bg) { +_SOKOL_PRIVATE void _sg_wgpu_dealloc_bindgroup(_sg_wgpu_bindgroup_t* bg) { SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_ALLOC) && (bg->slot.id != SG_INVALID_ID)); + _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool; _sg_pool_free_index(&p->pool, _sg_slot_index(bg->slot.id)); _sg_reset_slot(&bg->slot); } @@ -12603,13 +12610,45 @@ _SOKOL_PRIVATE void _sg_wgpu_reset_bindgroup_to_alloc_state(_sg_wgpu_bindgroup_t bg->slot.state = SG_RESOURCESTATE_ALLOC; } -_SOKOL_PRIVATE uint64_t _sg_wgpu_hash(void* ptr, size_t num_bytes) { - // FIXME! - (void)ptr; (void)num_bytes; - return 0; +// MurmurHash64B (see: https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash2.cpp#L142) +_SOKOL_PRIVATE uint64_t _sg_wgpu_hash(const void* key, int len, uint64_t seed) { + const uint32_t m = 0x5bd1e995; + const int r = 24; + uint32_t h1 = (uint32_t)seed ^ (uint32_t)len; + uint32_t h2 = (uint32_t)(seed >> 32); + const uint32_t * data = (const uint32_t *)key; + while (len >= 8) { + uint32_t k1 = *data++; + k1 *= m; k1 ^= k1 >> r; k1 *= m; + h1 *= m; h1 ^= k1; + len -= 4; + uint32_t k2 = *data++; + k2 *= m; k2 ^= k2 >> r; k2 *= m; + h2 *= m; h2 ^= k2; + len -= 4; + } + if (len >= 4) { + uint32_t k1 = *data++; + k1 *= m; k1 ^= k1 >> r; k1 *= m; + h1 *= m; h1 ^= k1; + len -= 4; + } + switch(len) { + case 3: h2 ^= (uint32_t)(((unsigned char*)data)[2] << 16); + case 2: h2 ^= (uint32_t)(((unsigned char*)data)[1] << 8); + case 1: h2 ^= ((unsigned char*)data)[0]; + h2 *= m; + }; + h1 ^= h2 >> 18; h1 *= m; + h2 ^= h1 >> 22; h2 *= m; + h1 ^= h2 >> 17; h1 *= m; + h2 ^= h1 >> 19; h2 *= m; + uint64_t h = h1; + h = (h << 32) | h2; + return h; } -_SOKOL_PRIVATE void _sg_wgpu_init_bindgroupscache_key(_sg_wgpu_bindgroupscache_key_t* key, const _sg_bindings_t* bnd) { +_SOKOL_PRIVATE void _sg_wgpu_init_bindgroups_cache_key(_sg_wgpu_bindgroups_cache_key_t* key, const _sg_bindings_t* bnd) { SOKOL_ASSERT(bnd); SOKOL_ASSERT(bnd->pip); SOKOL_ASSERT(bnd->num_vs_imgs <= SG_MAX_SHADERSTAGE_IMAGES); @@ -12640,10 +12679,10 @@ _SOKOL_PRIVATE void _sg_wgpu_init_bindgroupscache_key(_sg_wgpu_bindgroupscache_k SOKOL_ASSERT(bnd->fs_smps[i]); key->items[fs_smps_offset + i] = bnd->fs_smps[i]->slot.id; } - key->hash = _sg_wgpu_hash(&key->items, sizeof(key->items)); + key->hash = _sg_wgpu_hash(&key->items, (int)sizeof(key->items), 0x1234567887654321); } -_SOKOL_PRIVATE bool _sg_wgpu_compare_bindgroupscache_key(_sg_wgpu_bindgroupscache_key_t* k0, _sg_wgpu_bindgroupscache_key_t* k1) { +_SOKOL_PRIVATE bool _sg_wgpu_compare_bindgroups_cache_key(_sg_wgpu_bindgroups_cache_key_t* k0, _sg_wgpu_bindgroups_cache_key_t* k1) { SOKOL_ASSERT(k0 && k1); if (k0->hash != k1->hash) { return false; @@ -12658,11 +12697,11 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup(_sg_bindings_t* b SOKOL_ASSERT(_sg.wgpu.dev); SOKOL_ASSERT(bnd->pip); SOKOL_ASSERT(bnd->pip->shader && (bnd->pip->cmn.shader_id.id == bnd->pip->shader->slot.id)); - _sg_wgpu_bindgroup_handle_t bg_id = _sg_wgpu_alloc_bindgroup(&_sg.wgpu.bindgroups_pool); + _sg_wgpu_bindgroup_handle_t bg_id = _sg_wgpu_alloc_bindgroup(); if (bg_id.id == SG_INVALID_ID) { return 0; } - _sg_wgpu_bindgroup_t* bg = _sg_wgpu_bindgroup_at(&_sg.wgpu.bindgroups_pool, bg_id.id); + _sg_wgpu_bindgroup_t* bg = _sg_wgpu_bindgroup_at(bg_id.id); SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_ALLOC)); // create wgpu bindgroup object @@ -12703,7 +12742,7 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup(_sg_bindings_t* b return bg; } - _sg_wgpu_init_bindgroupscache_key(&bg->key, bnd); + _sg_wgpu_init_bindgroups_cache_key(&bg->key, bnd); bg->slot.state = SG_RESOURCESTATE_VALID; return bg; @@ -12720,12 +12759,13 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_bindgroup(_sg_wgpu_bindgroup_t* bg) { SOKOL_ASSERT(bg->slot.state == SG_RESOURCESTATE_ALLOC); } if (bg->slot.state == SG_RESOURCESTATE_ALLOC) { - _sg_wgpu_dealloc_bindgroup(&_sg.wgpu.bindgroups_pool, bg); + _sg_wgpu_dealloc_bindgroup(bg); SOKOL_ASSERT(bg->slot.state == SG_RESOURCESTATE_INITIAL); } } -_SOKOL_PRIVATE void _sg_wgpu_discard_all_bindgroups(_sg_wgpu_bindgroups_pool_t* p) { +_SOKOL_PRIVATE void _sg_wgpu_discard_all_bindgroups(void) { + _sg_wgpu_bindgroups_pool_t* p = &_sg.wgpu.bindgroups_pool; for (int i = 0; i < p->pool.size; i++) { sg_resource_state state = p->bindgroups[i].slot.state; if ((state == SG_RESOURCESTATE_VALID) || (state == SG_RESOURCESTATE_FAILED)) { @@ -12734,6 +12774,47 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_all_bindgroups(_sg_wgpu_bindgroups_pool_t* } } +_SOKOL_PRIVATE void _sg_wgpu_bindgroups_cache_init(const sg_desc* desc) { + SOKOL_ASSERT(desc); + SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.num == 0); + SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.index_mask == 0); + SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.items == 0); + const int num = desc->wgpu_bindgroups_cache_size; + if (num <= 1) { + _SG_PANIC(WGPU_BINDGROUPSCACHE_SIZE_GREATER_ONE); + } + if (!_sg_ispow2(num)) { + _SG_PANIC(WGPU_BINDGROUPSCACHE_SIZE_POW2); + } + _sg.wgpu.bindgroups_cache.num = (uint32_t)desc->wgpu_bindgroups_cache_size; + _sg.wgpu.bindgroups_cache.index_mask = _sg.wgpu.bindgroups_cache.num - 1; + size_t size_in_bytes = sizeof(_sg_wgpu_bindgroup_handle_t) * (size_t)num; + _sg.wgpu.bindgroups_cache.items = _sg_malloc_clear(size_in_bytes); +} + +_SOKOL_PRIVATE void _sg_wgpu_bindgroups_cache_discard(void) { + if (_sg.wgpu.bindgroups_cache.items) { + _sg_free(_sg.wgpu.bindgroups_cache.items); + _sg.wgpu.bindgroups_cache.items = 0; + } + _sg.wgpu.bindgroups_cache.num = 0; + _sg.wgpu.bindgroups_cache.index_mask = 0; +} + +_SOKOL_PRIVATE void _sg_wgpu_bindgroups_cache_set(uint64_t hash, uint32_t bg_id) { + uint32_t index = hash & _sg.wgpu.bindgroups_cache.index_mask; + SOKOL_ASSERT(index < _sg.wgpu.bindgroups_cache.num); + SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.items); + _sg.wgpu.bindgroups_cache.items[index].id = bg_id; +} + +_SOKOL_PRIVATE uint32_t _sg_wgpu_bindgroups_cache_get(uint64_t hash) { + uint32_t index = hash & _sg.wgpu.bindgroups_cache.index_mask; + SOKOL_ASSERT(index < _sg.wgpu.bindgroups_cache.num); + SOKOL_ASSERT(_sg.wgpu.bindgroups_cache.items); + return _sg.wgpu.bindgroups_cache.items[index].id; +} + _SOKOL_PRIVATE void _sg_wgpu_bindcache_clear(void) { memset(&_sg.wgpu.bindings_cache, 0, sizeof(_sg.wgpu.bindings_cache)); } @@ -12762,16 +12843,45 @@ _SOKOL_PRIVATE void _sg_wgpu_bindcache_ib_update(const _sg_buffer_t* ib, int ib_ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { if ((bnd->num_vs_imgs + bnd->num_vs_smps + bnd->num_fs_imgs + bnd->num_fs_smps) > 0) { - // FIXME: use bindgroups cache! - _sg_wgpu_bindgroup_t* bg = _sg_wgpu_create_bindgroup(bnd); - if (bg) { - if (bg->slot.state == SG_RESOURCESTATE_VALID) { + if (!_sg.desc.wgpu_disable_bindgroups_cache) { + _sg_wgpu_bindgroup_t* bg = 0; + _sg_wgpu_bindgroups_cache_key_t key; + _sg_wgpu_init_bindgroups_cache_key(&key, bnd); + uint32_t bg_id = _sg_wgpu_bindgroups_cache_get(key.hash); + if (bg_id != SG_INVALID_ID) { + // potential cache hit + bg = _sg_wgpu_lookup_bindgroup(bg_id); + SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_VALID)); + if (!_sg_wgpu_compare_bindgroups_cache_key(&key, &bg->key)) { + // cache collision, need to delete cached bindgroup + _sg_wgpu_discard_bindgroup(bg); + _sg_wgpu_bindgroups_cache_set(key.hash, SG_INVALID_ID); + bg = 0; + } + } + if (bg == 0) { + // either no cache entry yet, or cache collision, create new bindgroup and store in cache + bg = _sg_wgpu_create_bindgroup(bnd); + _sg_wgpu_bindgroups_cache_set(key.hash, bg->slot.id); + } + if (bg && bg->slot.state == SG_RESOURCESTATE_VALID) { SOKOL_ASSERT(bg->bindgroup); wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0); + } else { + return false; } - _sg_wgpu_discard_bindgroup(bg); } else { - return false; + // bindgroups cache disabled, create and destroy bindgroup on the fly (expensive!) + _sg_wgpu_bindgroup_t* bg = _sg_wgpu_create_bindgroup(bnd); + if (bg) { + if (bg->slot.state == SG_RESOURCESTATE_VALID) { + SOKOL_ASSERT(bg->bindgroup); + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0); + } + _sg_wgpu_discard_bindgroup(bg); + } else { + return false; + } } } else { wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); @@ -12803,6 +12913,7 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg_wgpu_init_caps(); _sg_wgpu_uniform_buffer_init(desc); _sg_wgpu_bindgroups_pool_init(desc); + _sg_wgpu_bindgroups_cache_init(desc); // create an empty bind group for shader stages without bound images WGPUBindGroupLayoutDescriptor bgl_desc; @@ -12827,8 +12938,9 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_backend(void) { SOKOL_ASSERT(_sg.wgpu.valid); SOKOL_ASSERT(_sg.wgpu.cmd_enc); _sg.wgpu.valid = false; - _sg_wgpu_discard_all_bindgroups(&_sg.wgpu.bindgroups_pool); - _sg_wgpu_bindgroups_pool_discard(&_sg.wgpu.bindgroups_pool); + _sg_wgpu_discard_all_bindgroups(); + _sg_wgpu_bindgroups_cache_discard(); + _sg_wgpu_bindgroups_pool_discard(); _sg_wgpu_uniform_buffer_discard(); wgpuBindGroupRelease(_sg.wgpu.empty_bind_group); _sg.wgpu.empty_bind_group = 0; wgpuCommandEncoderRelease(_sg.wgpu.cmd_enc); _sg.wgpu.cmd_enc = 0; From 1b9f90bd2b7eeb5c978a40dc1995be907a81b384 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 30 Sep 2023 19:00:49 +0200 Subject: [PATCH 61/95] sokol_gfx.h wgpu: fix C++ compile problem, and a memory corruption in the new bindgroups cache --- sokol_gfx.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index adf860bd8..1d0057f1a 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12553,8 +12553,8 @@ _SOKOL_PRIVATE void _sg_wgpu_bindgroups_pool_init(const sg_desc* desc) { SOKOL_ASSERT(0 == p->bindgroups); const int pool_size = desc->wgpu_bindgroups_cache_size; _sg_init_pool(&p->pool, pool_size); - size_t pool_byte_size = sizeof(_sg_wgpu_bindgroup_t) * (size_t)pool_size; - p->bindgroups = _sg_malloc_clear(pool_byte_size); + size_t pool_byte_size = sizeof(_sg_wgpu_bindgroup_t) * (size_t)p->pool.size; + p->bindgroups = (_sg_wgpu_bindgroup_t*) _sg_malloc_clear(pool_byte_size); } _SOKOL_PRIVATE void _sg_wgpu_bindgroups_pool_discard(void) { @@ -12789,7 +12789,7 @@ _SOKOL_PRIVATE void _sg_wgpu_bindgroups_cache_init(const sg_desc* desc) { _sg.wgpu.bindgroups_cache.num = (uint32_t)desc->wgpu_bindgroups_cache_size; _sg.wgpu.bindgroups_cache.index_mask = _sg.wgpu.bindgroups_cache.num - 1; size_t size_in_bytes = sizeof(_sg_wgpu_bindgroup_handle_t) * (size_t)num; - _sg.wgpu.bindgroups_cache.items = _sg_malloc_clear(size_in_bytes); + _sg.wgpu.bindgroups_cache.items = (_sg_wgpu_bindgroup_handle_t*)_sg_malloc_clear(size_in_bytes); } _SOKOL_PRIVATE void _sg_wgpu_bindgroups_cache_discard(void) { @@ -14504,7 +14504,8 @@ _SOKOL_PRIVATE uint32_t _sg_slot_alloc(_sg_pool_t* pool, _sg_slot_t* slot, int s */ SOKOL_ASSERT(pool && pool->gen_ctrs); SOKOL_ASSERT((slot_index > _SG_INVALID_SLOT_INDEX) && (slot_index < pool->size)); - SOKOL_ASSERT((slot->state == SG_RESOURCESTATE_INITIAL) && (slot->id == SG_INVALID_ID)); + SOKOL_ASSERT(slot->id == SG_INVALID_ID); + SOKOL_ASSERT(slot->state == SG_RESOURCESTATE_INITIAL); uint32_t ctr = ++pool->gen_ctrs[slot_index]; slot->id = (ctr<<_SG_SLOT_SHIFT)|(slot_index & _SG_SLOT_MASK); slot->state = SG_RESOURCESTATE_ALLOC; From fcfda2e104bf25b7fb505326e574959a1c6c909c Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 1 Oct 2023 18:49:03 +0200 Subject: [PATCH 62/95] sokol_gfx.h: start implementing frame stats tracking --- sokol_gfx.h | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/sokol_gfx.h b/sokol_gfx.h index 1d0057f1a..224978744 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -350,6 +350,10 @@ to sokol_gfx.h internals, and may change more often than other public API functions and structs. + --- you can query various internal per-frame stats via: + + sg_query_frame_stats() + --- you can ask at runtime what backend sokol_gfx.h has been compiled for: sg_backend sg_query_backend(void) @@ -2854,6 +2858,54 @@ typedef struct sg_pass_info { sg_slot_info slot; // resource pool slot info } sg_pass_info; +/* + sg_frame_stats + + Allows to track generic and backend-specific tracking stats about a + render frame. Obtained by calling sg_query_frame_stats(). The returned + struct will contains information about the *previous* frame. +*/ +typedef struct sg_frame_stats_gl { + uint32_t fixme; +} sg_frame_stats_gl; + +typedef struct sg_frame_stats_d3d11 { + uint32_t fixme; +} sg_frame_stats_d3d11; + +typedef struct sg_frame_stats_metal { + uint32_t fixme; +} sg_frame_stats_metal; + +typedef struct sg_frame_stats_wgpu { + uint32_t fixme; +} sg_frame_stats_wgpu; + +typedef struct sg_frame_stats { + uint32_t frame_index; // current frame counter, starts at 0 + + uint32_t num_passes; + uint32_t num_apply_viewport; + uint32_t num_apply_scissor_rect; + uint32_t num_apply_pipeline; + uint32_t num_apply_bindings; + uint32_t num_apply_uniforms; + uint32_t num_draw; + uint32_t num_update_buffer; + uint32_t num_append_buffer; + uint32_t num_update_image; + + uint32_t size_apply_uniforms; + uint32_t size_update_buffer; + uint32_t size_append_buffer; + uint32_t size_update_image; + + sg_frame_stats_gl gl; + sg_frame_stats_d3d11 d3d11; + sg_frame_stats_metal metal; + sg_frame_stats_wgpu wgpu; +} sg_frame_stats; + /* sg_log_item @@ -3392,6 +3444,7 @@ SOKOL_GFX_API_DECL sg_backend sg_query_backend(void); SOKOL_GFX_API_DECL sg_features sg_query_features(void); SOKOL_GFX_API_DECL sg_limits sg_query_limits(void); SOKOL_GFX_API_DECL sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt); +SOKOL_GFX_API_DECL sg_frame_stats sg_query_frame_stats(void); // get current state of a resource (INITIAL, ALLOC, VALID, FAILED, INVALID) SOKOL_GFX_API_DECL sg_resource_state sg_query_buffer_state(sg_buffer buf); SOKOL_GFX_API_DECL sg_resource_state sg_query_image_state(sg_image img); @@ -5061,6 +5114,8 @@ typedef struct { sg_features features; sg_limits limits; sg_pixelformat_info formats[_SG_PIXELFORMAT_NUM]; + sg_frame_stats stats; + sg_frame_stats prev_stats; #if defined(_SOKOL_ANY_GL) _sg_gl_backend_t gl; #elif defined(SOKOL_METAL) @@ -16902,6 +16957,7 @@ SOKOL_API_IMPL void sg_begin_pass(sg_pass pass_id, const sg_pass_action* pass_ac SOKOL_API_IMPL void sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left) { SOKOL_ASSERT(_sg.valid); + _sg.stats.num_apply_viewport++; if (!_sg.pass_valid) { return; } @@ -16915,6 +16971,7 @@ SOKOL_API_IMPL void sg_apply_viewportf(float x, float y, float width, float heig SOKOL_API_IMPL void sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left) { SOKOL_ASSERT(_sg.valid); + _sg.stats.num_apply_scissor_rect++; if (!_sg.pass_valid) { return; } @@ -16928,6 +16985,7 @@ SOKOL_API_IMPL void sg_apply_scissor_rectf(float x, float y, float width, float SOKOL_API_IMPL void sg_apply_pipeline(sg_pipeline pip_id) { SOKOL_ASSERT(_sg.valid); + _sg.stats.num_apply_pipeline++; _sg.bindings_applied = false; if (!_sg_validate_apply_pipeline(pip_id)) { _sg.next_draw_valid = false; @@ -16949,6 +17007,7 @@ SOKOL_API_IMPL void sg_apply_bindings(const sg_bindings* bindings) { SOKOL_ASSERT(_sg.valid); SOKOL_ASSERT(bindings); SOKOL_ASSERT((bindings->_start_canary == 0) && (bindings->_end_canary==0)); + _sg.stats.num_apply_bindings++; if (!_sg_validate_apply_bindings(bindings)) { _sg.next_draw_valid = false; return; @@ -17051,6 +17110,8 @@ SOKOL_API_IMPL void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const SOKOL_ASSERT((stage == SG_SHADERSTAGE_VS) || (stage == SG_SHADERSTAGE_FS)); SOKOL_ASSERT((ub_index >= 0) && (ub_index < SG_MAX_SHADERSTAGE_UBS)); SOKOL_ASSERT(data && data->ptr && (data->size > 0)); + _sg.stats.num_apply_uniforms++; + _sg.stats.size_apply_uniforms += data->size; if (!_sg_validate_apply_uniforms(stage, ub_index, data)) { _sg.next_draw_valid = false; return; @@ -17070,6 +17131,7 @@ SOKOL_API_IMPL void sg_draw(int base_element, int num_elements, int num_instance SOKOL_ASSERT(base_element >= 0); SOKOL_ASSERT(num_elements >= 0); SOKOL_ASSERT(num_instances >= 0); + _sg.stats.num_draw++; #if defined(SOKOL_DEBUG) if (!_sg.bindings_applied) { _SG_WARN(DRAW_WITHOUT_BINDINGS); @@ -17096,6 +17158,7 @@ SOKOL_API_IMPL void sg_draw(int base_element, int num_elements, int num_instance SOKOL_API_IMPL void sg_end_pass(void) { SOKOL_ASSERT(_sg.valid); + _sg.stats.num_passes++; if (!_sg.pass_valid) { return; } @@ -17109,6 +17172,9 @@ SOKOL_API_IMPL void sg_end_pass(void) { SOKOL_API_IMPL void sg_commit(void) { SOKOL_ASSERT(_sg.valid); _sg_commit(); + _sg.stats.frame_index = _sg.frame_index; + _sg.prev_stats = _sg.stats; + _sg_clear(&_sg.stats, sizeof(_sg.stats)); _sg_notify_commit_listeners(); _SG_TRACE_NOARGS(commit); _sg.frame_index++; @@ -17123,6 +17189,8 @@ SOKOL_API_IMPL void sg_reset_state_cache(void) { SOKOL_API_IMPL void sg_update_buffer(sg_buffer buf_id, const sg_range* data) { SOKOL_ASSERT(_sg.valid); SOKOL_ASSERT(data && data->ptr && (data->size > 0)); + _sg.stats.num_update_buffer++; + _sg.stats.size_update_buffer += data->size; _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id); if ((data->size > 0) && buf && (buf->slot.state == SG_RESOURCESTATE_VALID)) { if (_sg_validate_update_buffer(buf, data)) { @@ -17141,6 +17209,8 @@ SOKOL_API_IMPL void sg_update_buffer(sg_buffer buf_id, const sg_range* data) { SOKOL_API_IMPL int sg_append_buffer(sg_buffer buf_id, const sg_range* data) { SOKOL_ASSERT(_sg.valid); SOKOL_ASSERT(data && data->ptr); + _sg.stats.num_append_buffer++; + _sg.stats.size_append_buffer += data->size; _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id); int result; if (buf) { @@ -17202,6 +17272,15 @@ SOKOL_API_IMPL bool sg_query_buffer_will_overflow(sg_buffer buf_id, size_t size) SOKOL_API_IMPL void sg_update_image(sg_image img_id, const sg_image_data* data) { SOKOL_ASSERT(_sg.valid); + _sg.stats.num_update_image++; + for (int face_index = 0; face_index < SG_CUBEFACE_NUM; face_index++) { + for (int mip_index = 0; mip_index < SG_MAX_MIPMAPS; mip_index++) { + if (data->subimage[face_index][mip_index].size == 0) { + break; + } + _sg.stats.size_update_image += data->subimage[face_index][mip_index].size; + } + } _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id); if (img && img->slot.state == SG_RESOURCESTATE_VALID) { if (_sg_validate_update_image(img, data)) { From c2a5d9768b73ff3bb010fcb89cfdf760df94df98 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 1 Oct 2023 19:26:09 +0200 Subject: [PATCH 63/95] sokol_gfx.h wgpu: webgpu specific frame stats --- sokol_gfx.h | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 224978744..f070e2c4b 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2877,8 +2877,25 @@ typedef struct sg_frame_stats_metal { uint32_t fixme; } sg_frame_stats_metal; +typedef struct sg_frame_stats_wgpu_bindings { + uint32_t num_set_vertex_buffer; + uint32_t num_redundant_vertex_buffer; + uint32_t num_set_index_buffer; + uint32_t num_redundant_index_buffer; + uint32_t num_create_bindgroup; + uint32_t num_discard_bindgroup; + uint32_t num_set_bindgroup; + uint32_t num_set_empty_bindgroup; + uint32_t num_cache_hits; + uint32_t num_cache_misses; + uint32_t num_cache_collisions; + uint32_t num_hash_vs_key_mismatch; +} sg_frame_stats_wgpu_bindings; + typedef struct sg_frame_stats_wgpu { - uint32_t fixme; + uint32_t num_uniform_set_bindgroup; + uint32_t size_uniform_write_buffer; + sg_frame_stats_wgpu_bindings bindings; } sg_frame_stats_wgpu; typedef struct sg_frame_stats { @@ -12598,6 +12615,7 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_begin_pass(void) { _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, 0, _sg.wgpu.uniform.staging, _sg.wgpu.uniform.offset); + _sg.stats.wgpu.size_uniform_write_buffer += _sg.wgpu.uniform.offset; _sg.wgpu.uniform.offset = 0; _sg_clear(&_sg.wgpu.uniform.bind.offsets[0][0], sizeof(_sg.wgpu.uniform.bind.offsets)); } @@ -12743,6 +12761,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_compare_bindgroups_cache_key(_sg_wgpu_bindgroups_ca return false; } if (memcmp(&k0->items, &k1->items, sizeof(k0->items)) != 0) { + _sg.stats.wgpu.bindings.num_hash_vs_key_mismatch++; return false; } return true; @@ -12752,6 +12771,7 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup(_sg_bindings_t* b SOKOL_ASSERT(_sg.wgpu.dev); SOKOL_ASSERT(bnd->pip); SOKOL_ASSERT(bnd->pip->shader && (bnd->pip->cmn.shader_id.id == bnd->pip->shader->slot.id)); + _sg.stats.wgpu.bindings.num_create_bindgroup++; _sg_wgpu_bindgroup_handle_t bg_id = _sg_wgpu_alloc_bindgroup(); if (bg_id.id == SG_INVALID_ID) { return 0; @@ -12805,6 +12825,7 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup(_sg_bindings_t* b _SOKOL_PRIVATE void _sg_wgpu_discard_bindgroup(_sg_wgpu_bindgroup_t* bg) { SOKOL_ASSERT(bg); + _sg.stats.wgpu.bindings.num_discard_bindgroup++; if (bg->slot.state == SG_RESOURCESTATE_VALID) { if (bg->bindgroup) { wgpuBindGroupRelease(bg->bindgroup); @@ -12909,10 +12930,15 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_VALID)); if (!_sg_wgpu_compare_bindgroups_cache_key(&key, &bg->key)) { // cache collision, need to delete cached bindgroup + _sg.stats.wgpu.bindings.num_cache_collisions++; _sg_wgpu_discard_bindgroup(bg); _sg_wgpu_bindgroups_cache_set(key.hash, SG_INVALID_ID); bg = 0; + } else { + _sg.stats.wgpu.bindings.num_cache_hits++; } + } else { + _sg.stats.wgpu.bindings.num_cache_misses++; } if (bg == 0) { // either no cache entry yet, or cache collision, create new bindgroup and store in cache @@ -12921,6 +12947,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { } if (bg && bg->slot.state == SG_RESOURCESTATE_VALID) { SOKOL_ASSERT(bg->bindgroup); + _sg.stats.wgpu.bindings.num_set_bindgroup++; wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0); } else { return false; @@ -12931,6 +12958,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { if (bg) { if (bg->slot.state == SG_RESOURCESTATE_VALID) { SOKOL_ASSERT(bg->bindgroup); + _sg.stats.wgpu.bindings.num_set_bindgroup++; wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0); } _sg_wgpu_discard_bindgroup(bg); @@ -12939,6 +12967,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { } } } else { + _sg.stats.wgpu.bindings.num_set_empty_bindgroup++; wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); } return true; @@ -13753,6 +13782,9 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindings(_sg_bindings_t* bnd) { SOKOL_ASSERT(buf_size > offset); const uint64_t max_bytes = buf_size - offset; wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, bnd->ib->wgpu.buf, format, offset, max_bytes); + _sg.stats.wgpu.bindings.num_set_index_buffer++; + } else { + _sg.stats.wgpu.bindings.num_redundant_index_buffer++; } } // FIXME: else-path should actually set a null index buffer (this was just recently implemented in WebGPU) @@ -13766,6 +13798,9 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindings(_sg_bindings_t* bnd) { SOKOL_ASSERT(buf_size > offset); const uint64_t max_bytes = buf_size - offset; wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, (uint32_t)slot, bnd->vbs[slot]->wgpu.buf, offset, max_bytes); + _sg.stats.wgpu.bindings.num_set_vertex_buffer++; + } else { + _sg.stats.wgpu.bindings.num_redundant_vertex_buffer++; } // FIXME: else-path should actually set a null vertex buffer (this was just recently implemented in WebGPU) } @@ -13789,6 +13824,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ SOKOL_ASSERT(data->size <= _sg.wgpu.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size); SOKOL_ASSERT(data->size <= _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); + _sg.stats.wgpu.num_uniform_set_bindgroup++; memcpy(_sg.wgpu.uniform.staging + _sg.wgpu.uniform.offset, data->ptr, data->size); _sg.wgpu.uniform.bind.offsets[stage_index][ub_index] = _sg.wgpu.uniform.offset; _sg.wgpu.uniform.offset = _sg_roundup_u32(_sg.wgpu.uniform.offset + (uint32_t)data->size, alignment); From 79f70be1db87483ae65d1b6fc06c19837e8ff41d Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 1 Oct 2023 19:30:13 +0200 Subject: [PATCH 64/95] sokol_gfx.h: fix msvc errors --- sokol_gfx.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index f070e2c4b..10e418d68 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -17147,7 +17147,7 @@ SOKOL_API_IMPL void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const SOKOL_ASSERT((ub_index >= 0) && (ub_index < SG_MAX_SHADERSTAGE_UBS)); SOKOL_ASSERT(data && data->ptr && (data->size > 0)); _sg.stats.num_apply_uniforms++; - _sg.stats.size_apply_uniforms += data->size; + _sg.stats.size_apply_uniforms += (uint32_t)data->size; if (!_sg_validate_apply_uniforms(stage, ub_index, data)) { _sg.next_draw_valid = false; return; @@ -17226,7 +17226,7 @@ SOKOL_API_IMPL void sg_update_buffer(sg_buffer buf_id, const sg_range* data) { SOKOL_ASSERT(_sg.valid); SOKOL_ASSERT(data && data->ptr && (data->size > 0)); _sg.stats.num_update_buffer++; - _sg.stats.size_update_buffer += data->size; + _sg.stats.size_update_buffer += (uint32_t)data->size; _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id); if ((data->size > 0) && buf && (buf->slot.state == SG_RESOURCESTATE_VALID)) { if (_sg_validate_update_buffer(buf, data)) { @@ -17246,7 +17246,7 @@ SOKOL_API_IMPL int sg_append_buffer(sg_buffer buf_id, const sg_range* data) { SOKOL_ASSERT(_sg.valid); SOKOL_ASSERT(data && data->ptr); _sg.stats.num_append_buffer++; - _sg.stats.size_append_buffer += data->size; + _sg.stats.size_append_buffer += (uint32_t)data->size; _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id); int result; if (buf) { @@ -17314,7 +17314,7 @@ SOKOL_API_IMPL void sg_update_image(sg_image img_id, const sg_image_data* data) if (data->subimage[face_index][mip_index].size == 0) { break; } - _sg.stats.size_update_image += data->subimage[face_index][mip_index].size; + _sg.stats.size_update_image += (uint32_t)data->subimage[face_index][mip_index].size; } } _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id); From 2754f96c8eb4db77d0771ca845046056e6438eac Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 12:09:16 +0200 Subject: [PATCH 65/95] sokol_gfx_imgui.h: add helper function sg_imgui_draw_menu() --- util/sokol_gfx_imgui.h | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h index 7614f61a7..d357f13b9 100644 --- a/util/sokol_gfx_imgui.h +++ b/util/sokol_gfx_imgui.h @@ -84,7 +84,12 @@ this won't draw anything yet, since no windows are open. - --- open and close windows directly by setting the following public + --- call the convenience function sg_imgui_draw_menu(ctx, title) + to render a menu which allows to open/close the provided debug windows + + sg_imgui_draw_menu(&sg_imgui, "sokol-gfx"); + + --- alternative, open and close windows directly by setting the following public booleans in the sg_imgui_t struct: sg_imgui.buffers.open = true; @@ -751,6 +756,8 @@ SOKOL_GFX_IMGUI_API_DECL void sg_imgui_init(sg_imgui_t* ctx, const sg_imgui_desc SOKOL_GFX_IMGUI_API_DECL void sg_imgui_discard(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw(sg_imgui_t* ctx); +SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_menu(sg_imgui_t* ctx, const char* title); + SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_buffers_content(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_images_content(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_samplers_content(sg_imgui_t* ctx); @@ -900,6 +907,15 @@ _SOKOL_PRIVATE bool igBegin(const char* name,bool* p_open,ImGuiWindowFlags flags _SOKOL_PRIVATE void igEnd() { return ImGui::End(); } +_SOKOL_PRIVATE bool igBeginMenu(const char* label, bool enabled) { + return ImGui::BeginMenu(label, enabled); +} +_SOKOL_PRIVATE void igEndMenu(void) { + ImGui::EndMenu(); +} +_SOKOL_PRIVATE bool igMenuItem_BoolPtr(const char* label, const char* shortcut, bool* p_selected, bool enabled) { + return ImGui::MenuItem(label, shortcut, p_selected, enabled); +} #else #define IMVEC2(x,y) (ImVec2){x,y} #define IMVEC4(x,y,z,w) (ImVec4){x,y,z,w} @@ -4328,6 +4344,22 @@ SOKOL_API_IMPL void sg_imgui_draw(sg_imgui_t* ctx) { sg_imgui_draw_capabilities_window(ctx); } +SOKOL_API_IMPL void sg_imgui_draw_menu(sg_imgui_t* ctx, const char* title) { + SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD)); + SOKOL_ASSERT(title); + if (igBeginMenu(title, true)) { + igMenuItem_BoolPtr("Capabilities", 0, &ctx->caps.open, true); + igMenuItem_BoolPtr("Buffers", 0, &ctx->buffers.open, true); + igMenuItem_BoolPtr("Images", 0, &ctx->images.open, true); + igMenuItem_BoolPtr("Samplers", 0, &ctx->samplers.open, true); + igMenuItem_BoolPtr("Shaders", 0, &ctx->shaders.open, true); + igMenuItem_BoolPtr("Pipelines", 0, &ctx->pipelines.open, true); + igMenuItem_BoolPtr("Passes", 0, &ctx->passes.open, true); + igMenuItem_BoolPtr("Calls", 0, &ctx->capture.open, true); + igEndMenu(); + } +} + SOKOL_API_IMPL void sg_imgui_draw_buffers_window(sg_imgui_t* ctx) { SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD)); if (!ctx->buffers.open) { From 4331539315641ad4fe477a954f4603b91e1e7c5b Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 12:14:30 +0200 Subject: [PATCH 66/95] sokol_gfx_imgui.h: tweak function call colors --- util/sokol_gfx_imgui.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h index d357f13b9..7bb9c251e 100644 --- a/util/sokol_gfx_imgui.h +++ b/util/sokol_gfx_imgui.h @@ -827,6 +827,8 @@ SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_capabilities_window(sg_imgui_t* ctx) #define _SG_IMGUI_LIST_WIDTH (192) #define _SG_IMGUI_COLOR_OTHER 0xFFCCCCCC #define _SG_IMGUI_COLOR_RSRC 0xFF00FFFF +#define _SG_IMGUI_COLOR_PASS 0xFFFFFF00 +#define _SG_IMGUI_COLOR_APPLY 0xFFCCCC00 #define _SG_IMGUI_COLOR_DRAW 0xFF00FF00 #define _SG_IMGUI_COLOR_ERR 0xFF8888FF @@ -2457,7 +2459,7 @@ _SOKOL_PRIVATE void _sg_imgui_begin_default_pass(const sg_pass_action* pass_acti if (item) { SOKOL_ASSERT(pass_action); item->cmd = SG_IMGUI_CMD_BEGIN_DEFAULT_PASS; - item->color = _SG_IMGUI_COLOR_DRAW; + item->color = _SG_IMGUI_COLOR_PASS; item->args.begin_default_pass.action = *pass_action; item->args.begin_default_pass.width = width; item->args.begin_default_pass.height = height; @@ -2474,7 +2476,7 @@ _SOKOL_PRIVATE void _sg_imgui_begin_pass(sg_pass pass, const sg_pass_action* pas if (item) { SOKOL_ASSERT(pass_action); item->cmd = SG_IMGUI_CMD_BEGIN_PASS; - item->color = _SG_IMGUI_COLOR_DRAW; + item->color = _SG_IMGUI_COLOR_PASS; item->args.begin_pass.pass = pass; item->args.begin_pass.action = *pass_action; } @@ -2489,7 +2491,7 @@ _SOKOL_PRIVATE void _sg_imgui_apply_viewport(int x, int y, int width, int height sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx); if (item) { item->cmd = SG_IMGUI_CMD_APPLY_VIEWPORT; - item->color = _SG_IMGUI_COLOR_DRAW; + item->color = _SG_IMGUI_COLOR_APPLY; item->args.apply_viewport.x = x; item->args.apply_viewport.y = y; item->args.apply_viewport.width = width; @@ -2507,7 +2509,7 @@ _SOKOL_PRIVATE void _sg_imgui_apply_scissor_rect(int x, int y, int width, int he sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx); if (item) { item->cmd = SG_IMGUI_CMD_APPLY_SCISSOR_RECT; - item->color = _SG_IMGUI_COLOR_DRAW; + item->color = _SG_IMGUI_COLOR_APPLY; item->args.apply_scissor_rect.x = x; item->args.apply_scissor_rect.y = y; item->args.apply_scissor_rect.width = width; @@ -2526,7 +2528,7 @@ _SOKOL_PRIVATE void _sg_imgui_apply_pipeline(sg_pipeline pip, void* user_data) { sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx); if (item) { item->cmd = SG_IMGUI_CMD_APPLY_PIPELINE; - item->color = _SG_IMGUI_COLOR_DRAW; + item->color = _SG_IMGUI_COLOR_APPLY; item->args.apply_pipeline.pipeline = pip; } if (ctx->hooks.apply_pipeline) { @@ -2541,7 +2543,7 @@ _SOKOL_PRIVATE void _sg_imgui_apply_bindings(const sg_bindings* bindings, void* if (item) { SOKOL_ASSERT(bindings); item->cmd = SG_IMGUI_CMD_APPLY_BINDINGS; - item->color = _SG_IMGUI_COLOR_DRAW; + item->color = _SG_IMGUI_COLOR_APPLY; item->args.apply_bindings.bindings = *bindings; } if (ctx->hooks.apply_bindings) { @@ -2556,7 +2558,7 @@ _SOKOL_PRIVATE void _sg_imgui_apply_uniforms(sg_shader_stage stage, int ub_index sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx); if (item) { item->cmd = SG_IMGUI_CMD_APPLY_UNIFORMS; - item->color = _SG_IMGUI_COLOR_DRAW; + item->color = _SG_IMGUI_COLOR_APPLY; sg_imgui_args_apply_uniforms_t* args = &item->args.apply_uniforms; args->stage = stage; args->ub_index = ub_index; @@ -2592,7 +2594,7 @@ _SOKOL_PRIVATE void _sg_imgui_end_pass(void* user_data) { sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx); if (item) { item->cmd = SG_IMGUI_CMD_END_PASS; - item->color = _SG_IMGUI_COLOR_DRAW; + item->color = _SG_IMGUI_COLOR_PASS; } if (ctx->hooks.end_pass) { ctx->hooks.end_pass(ctx->hooks.user_data); @@ -2605,7 +2607,7 @@ _SOKOL_PRIVATE void _sg_imgui_commit(void* user_data) { sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx); if (item) { item->cmd = SG_IMGUI_CMD_COMMIT; - item->color = _SG_IMGUI_COLOR_DRAW; + item->color = _SG_IMGUI_COLOR_OTHER; } _sg_imgui_capture_next_frame(ctx); if (ctx->hooks.commit) { From 4f41feb0e474e3d24af3ae13396edd912067fd5a Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 13:39:52 +0200 Subject: [PATCH 67/95] sokol_gfx.h: code cleanup --- sokol_gfx.h | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 10e418d68..4efd202be 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2879,17 +2879,17 @@ typedef struct sg_frame_stats_metal { typedef struct sg_frame_stats_wgpu_bindings { uint32_t num_set_vertex_buffer; - uint32_t num_redundant_vertex_buffer; + uint32_t num_skip_set_vertex_buffer; uint32_t num_set_index_buffer; - uint32_t num_redundant_index_buffer; + uint32_t num_skip_set_index_buffer; uint32_t num_create_bindgroup; uint32_t num_discard_bindgroup; uint32_t num_set_bindgroup; uint32_t num_set_empty_bindgroup; - uint32_t num_cache_hits; - uint32_t num_cache_misses; - uint32_t num_cache_collisions; - uint32_t num_hash_vs_key_mismatch; + uint32_t num_bindgroup_cache_hits; + uint32_t num_bindgroup_cache_misses; + uint32_t num_bindgroup_cache_collisions; + uint32_t num_bindgroup_cache_hash_vs_key_mismatch; } sg_frame_stats_wgpu_bindings; typedef struct sg_frame_stats_wgpu { @@ -12761,7 +12761,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_compare_bindgroups_cache_key(_sg_wgpu_bindgroups_ca return false; } if (memcmp(&k0->items, &k1->items, sizeof(k0->items)) != 0) { - _sg.stats.wgpu.bindings.num_hash_vs_key_mismatch++; + _sg.stats.wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatch++; return false; } return true; @@ -12930,15 +12930,15 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_VALID)); if (!_sg_wgpu_compare_bindgroups_cache_key(&key, &bg->key)) { // cache collision, need to delete cached bindgroup - _sg.stats.wgpu.bindings.num_cache_collisions++; + _sg.stats.wgpu.bindings.num_bindgroup_cache_collisions++; _sg_wgpu_discard_bindgroup(bg); _sg_wgpu_bindgroups_cache_set(key.hash, SG_INVALID_ID); bg = 0; } else { - _sg.stats.wgpu.bindings.num_cache_hits++; + _sg.stats.wgpu.bindings.num_bindgroup_cache_hits++; } } else { - _sg.stats.wgpu.bindings.num_cache_misses++; + _sg.stats.wgpu.bindings.num_bindgroup_cache_misses++; } if (bg == 0) { // either no cache entry yet, or cache collision, create new bindgroup and store in cache @@ -13784,7 +13784,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindings(_sg_bindings_t* bnd) { wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, bnd->ib->wgpu.buf, format, offset, max_bytes); _sg.stats.wgpu.bindings.num_set_index_buffer++; } else { - _sg.stats.wgpu.bindings.num_redundant_index_buffer++; + _sg.stats.wgpu.bindings.num_skip_set_index_buffer++; } } // FIXME: else-path should actually set a null index buffer (this was just recently implemented in WebGPU) @@ -13800,7 +13800,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindings(_sg_bindings_t* bnd) { wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, (uint32_t)slot, bnd->vbs[slot]->wgpu.buf, offset, max_bytes); _sg.stats.wgpu.bindings.num_set_vertex_buffer++; } else { - _sg.stats.wgpu.bindings.num_redundant_vertex_buffer++; + _sg.stats.wgpu.bindings.num_skip_set_vertex_buffer++; } // FIXME: else-path should actually set a null vertex buffer (this was just recently implemented in WebGPU) } @@ -16298,6 +16298,11 @@ SOKOL_API_IMPL sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt) { return _sg.formats[fmt_index]; } +SOKOL_API_IMPL sg_frame_stats sg_query_frame_stats(void) { + SOKOL_ASSERT(_sg.valid); + return _sg.prev_stats; +} + SOKOL_API_IMPL sg_context sg_setup_context(void) { SOKOL_ASSERT(_sg.valid); sg_context res; From 94321b2beb436dc45205e9b0a7cc475a136bd5cf Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 13:40:28 +0200 Subject: [PATCH 68/95] sokol_gfx_imgui.h: add frame stats window --- util/sokol_gfx_imgui.h | 111 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h index 7bb9c251e..149ee1463 100644 --- a/util/sokol_gfx_imgui.h +++ b/util/sokol_gfx_imgui.h @@ -92,6 +92,8 @@ --- alternative, open and close windows directly by setting the following public booleans in the sg_imgui_t struct: + sg_imgui.caps.open = true; + sg_imgui.frame_stats.open = true; sg_imgui.buffers.open = true; sg_imgui.images.open = true; sg_imgui.samplers.open = true; @@ -99,12 +101,15 @@ sg_imgui.pipelines.open = true; sg_imgui.passes.open = true; sg_imgui.capture.open = true; + sg_imgui.frame_stats.open = true; ...for instance, to control the window visibility through menu items, the following code can be used: if (ImGui::BeginMainMenuBar()) { if (ImGui::BeginMenu("sokol-gfx")) { + ImGui::MenuItem("Capabilities", 0, &sg_imgui.caps.open); + ImGui::MenuItem("Frame Stats", 0, &sg_imgui.frame_stats.open); ImGui::MenuItem("Buffers", 0, &sg_imgui.buffers.open); ImGui::MenuItem("Images", 0, &sg_imgui.images.open); ImGui::MenuItem("Samplers", 0, &sg_imgui.samplers.open); @@ -714,6 +719,12 @@ typedef struct sg_imgui_caps_t { bool open; } sg_imgui_caps_t; +typedef struct sg_imgui_frame_stats_t { + bool open; + sg_frame_stats stats; + // FIXME: add a ringbuffer for a stats history here +} sg_imgui_frame_stats_t; + /* sg_imgui_allocator_t @@ -748,6 +759,7 @@ typedef struct sg_imgui_t { sg_imgui_passes_t passes; sg_imgui_capture_t capture; sg_imgui_caps_t caps; + sg_imgui_frame_stats_t frame_stats; sg_pipeline cur_pipeline; sg_trace_hooks hooks; } sg_imgui_t; @@ -766,6 +778,7 @@ SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_pipelines_content(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_passes_content(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_capture_content(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_capabilities_content(sg_imgui_t* ctx); +SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_frame_stats_content(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_buffers_window(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_images_window(sg_imgui_t* ctx); @@ -775,6 +788,7 @@ SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_pipelines_window(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_passes_window(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_capture_window(sg_imgui_t* ctx); SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_capabilities_window(sg_imgui_t* ctx); +SOKOL_GFX_IMGUI_API_DECL void sg_imgui_draw_frame_stats_window(sg_imgui_t* ctx); #if defined(__cplusplus) } /* extern "C" */ @@ -918,6 +932,27 @@ _SOKOL_PRIVATE void igEndMenu(void) { _SOKOL_PRIVATE bool igMenuItem_BoolPtr(const char* label, const char* shortcut, bool* p_selected, bool enabled) { return ImGui::MenuItem(label, shortcut, p_selected, enabled); } +_SOKOL_PRIVATE bool igBeginTable(const char* str_id, int column, ImGuiTableFlags flags, const ImVec2 outer_size, float inner_width) { + return ImGui::BeginTable(str_id, column, flags, outer_size, inner_width); +} +_SOKOL_PRIVATE void igEndTable(void) { + ImGui::EndTable(); +} +_SOKOL_PRIVATE void igTableSetupScrollFreeze(int cols, int rows) { + ImGui::TableSetupScrollFreeze(cols, rows); +} +_SOKOL_PRIVATE void igTableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id) { + ImGui::TableSetupColumn(label, flags, init_width_or_weight, user_id); +} +_SOKOL_PRIVATE void igTableHeadersRow(void) { + ImGui::TableHeadersRow(); +} +_SOKOL_PRIVATE void igTableNextRow(ImGuiTableRowFlags row_flags, float min_row_height) { + ImGui::TableNextRow(row_flags, min_row_height); +} +_SOKOL_PRIVATE bool igTableSetColumnIndex(int column_n) { + return ImGui::TableSetColumnIndex(column_n); +} #else #define IMVEC2(x,y) (ImVec2){x,y} #define IMVEC4(x,y,z,w) (ImVec4){x,y,z,w} @@ -4163,6 +4198,62 @@ _SOKOL_PRIVATE void _sg_imgui_draw_caps_panel(void) { } } +_SOKOL_PRIVATE void _sg_imgui_frame_stats_row(const char* key, uint32_t value) { + igTableNextRow(0, 0.0f); + igTableSetColumnIndex(0); + igText(key); + igTableSetColumnIndex(1); + igText("%d", value); +} + +_SOKOL_PRIVATE void _sg_imgui_draw_frame_stats_panel(sg_imgui_t* ctx) { + _SOKOL_UNUSED(ctx); + const sg_frame_stats* stats = &ctx->frame_stats.stats; + const ImGuiTableFlags flags = + ImGuiTableFlags_Resizable | + ImGuiTableFlags_ScrollY | + ImGuiTableFlags_SizingFixedFit | + ImGuiTableFlags_Borders; + if (igBeginTable("##frame_stats_table", 2, flags, IMVEC2(0, 0), 0)) { + igTableSetupScrollFreeze(0, 1); + igTableSetupColumn("key", ImGuiTableColumnFlags_None, 0, 0); + igTableSetupColumn("value", ImGuiTableColumnFlags_None, 0, 0); + igTableHeadersRow(); + _sg_imgui_frame_stats_row("frame_index", stats->frame_index); + _sg_imgui_frame_stats_row("num_passes", stats->num_passes); + _sg_imgui_frame_stats_row("num_apply_viewport", stats->num_apply_viewport); + _sg_imgui_frame_stats_row("num_apply_scissor_rect", stats->num_apply_scissor_rect); + _sg_imgui_frame_stats_row("num_apply_pipeline", stats->num_apply_pipeline); + _sg_imgui_frame_stats_row("num_apply_bindings", stats->num_apply_bindings); + _sg_imgui_frame_stats_row("num_apply_uniforms", stats->num_apply_uniforms); + _sg_imgui_frame_stats_row("num_draw", stats->num_draw); + _sg_imgui_frame_stats_row("num_update_buffer", stats->num_update_buffer); + _sg_imgui_frame_stats_row("num_append_buffer", stats->num_append_buffer); + _sg_imgui_frame_stats_row("num_update_image", stats->num_update_image); + _sg_imgui_frame_stats_row("size_apply_uniforms", stats->size_apply_uniforms); + _sg_imgui_frame_stats_row("size_update_buffer", stats->size_update_buffer); + _sg_imgui_frame_stats_row("size_append_buffer", stats->size_append_buffer); + _sg_imgui_frame_stats_row("size_update_image", stats->size_update_image); + if (sg_query_backend() == SG_BACKEND_WGPU) { + _sg_imgui_frame_stats_row("wgpu.num_uniform_set_bindgroup", stats->wgpu.num_uniform_set_bindgroup); + _sg_imgui_frame_stats_row("wgpu.size_uniform_write_buffer", stats->wgpu.size_uniform_write_buffer); + _sg_imgui_frame_stats_row("wgpu.bindings.num_set_vertex_buffer", stats->wgpu.bindings.num_set_vertex_buffer); + _sg_imgui_frame_stats_row("wgpu.bindings.num_skip_set_vertex_buffer", stats->wgpu.bindings.num_skip_set_vertex_buffer); + _sg_imgui_frame_stats_row("wgpu.bindings.num_set_index_buffer", stats->wgpu.bindings.num_set_index_buffer); + _sg_imgui_frame_stats_row("wgpu.bindings.num_skip_set_index_buffer", stats->wgpu.bindings.num_skip_set_index_buffer); + _sg_imgui_frame_stats_row("wgpu.bindings.num_create_bindgroup", stats->wgpu.bindings.num_create_bindgroup); + _sg_imgui_frame_stats_row("wgpu.bindings.num_discard_bindgroup", stats->wgpu.bindings.num_discard_bindgroup); + _sg_imgui_frame_stats_row("wgpu.bindings.num_set_bindgroup", stats->wgpu.bindings.num_set_bindgroup); + _sg_imgui_frame_stats_row("wgpu.bindings.num_set_empty_bindgroup", stats->wgpu.bindings.num_set_empty_bindgroup); + _sg_imgui_frame_stats_row("wgpu.bindings.num_bindgroup_cache_hits", stats->wgpu.bindings.num_bindgroup_cache_hits); + _sg_imgui_frame_stats_row("wpgu.bindings.num_bindgroup_cache_misses", stats->wgpu.bindings.num_bindgroup_cache_misses); + _sg_imgui_frame_stats_row("wgpu.bindings.num_bindgroup_cache_collisions", stats->wgpu.bindings.num_bindgroup_cache_collisions); + _sg_imgui_frame_stats_row("wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatches", stats->wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatch); + } + igEndTable(); + } +} + #define _sg_imgui_def(val, def) (((val) == 0) ? (def) : (val)) _SOKOL_PRIVATE sg_imgui_desc_t _sg_imgui_desc_defaults(const sg_imgui_desc_t* desc) { @@ -4344,6 +4435,7 @@ SOKOL_API_IMPL void sg_imgui_draw(sg_imgui_t* ctx) { sg_imgui_draw_passes_window(ctx); sg_imgui_draw_capture_window(ctx); sg_imgui_draw_capabilities_window(ctx); + sg_imgui_draw_frame_stats_window(ctx); } SOKOL_API_IMPL void sg_imgui_draw_menu(sg_imgui_t* ctx, const char* title) { @@ -4351,6 +4443,7 @@ SOKOL_API_IMPL void sg_imgui_draw_menu(sg_imgui_t* ctx, const char* title) { SOKOL_ASSERT(title); if (igBeginMenu(title, true)) { igMenuItem_BoolPtr("Capabilities", 0, &ctx->caps.open, true); + igMenuItem_BoolPtr("Frame Stats", 0, &ctx->frame_stats.open, true); igMenuItem_BoolPtr("Buffers", 0, &ctx->buffers.open, true); igMenuItem_BoolPtr("Images", 0, &ctx->images.open, true); igMenuItem_BoolPtr("Samplers", 0, &ctx->samplers.open, true); @@ -4458,6 +4551,18 @@ SOKOL_API_IMPL void sg_imgui_draw_capabilities_window(sg_imgui_t* ctx) { igEnd(); } +SOKOL_API_IMPL void sg_imgui_draw_frame_stats_window(sg_imgui_t* ctx) { + SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD)); + if (!ctx->frame_stats.open) { + return; + } + igSetNextWindowSize(IMVEC2(512, 400), ImGuiCond_Once); + if (igBegin("Frame Stats", &ctx->frame_stats.open, 0)) { + sg_imgui_draw_frame_stats_content(ctx); + } + igEnd(); +} + SOKOL_API_IMPL void sg_imgui_draw_buffers_content(sg_imgui_t* ctx) { SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD)); _sg_imgui_draw_buffer_list(ctx); @@ -4513,4 +4618,10 @@ SOKOL_API_IMPL void sg_imgui_draw_capabilities_content(sg_imgui_t* ctx) { _sg_imgui_draw_caps_panel(); } +SOKOL_API_IMPL void sg_imgui_draw_frame_stats_content(sg_imgui_t* ctx) { + SOKOL_ASSERT(ctx && (ctx->init_tag == 0xABCDABCD)); + ctx->frame_stats.stats = sg_query_frame_stats(); + _sg_imgui_draw_frame_stats_panel(ctx); +} + #endif /* SOKOL_GFX_IMGUI_IMPL */ From 10439891ac735360be753ad1872122b325a841f1 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 16:04:42 +0200 Subject: [PATCH 69/95] sokol_gfx.h: frame stats code cleanup --- sokol_gfx.h | 87 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 4efd202be..d02a27f2a 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -350,9 +350,12 @@ to sokol_gfx.h internals, and may change more often than other public API functions and structs. - --- you can query various internal per-frame stats via: + --- you can query frame stats and control stats collection via: sg_query_frame_stats() + sg_enable_frame_stats() + sg_disable_frame_stats() + sg_frame_stats_enabled() --- you can ask at runtime what backend sokol_gfx.h has been compiled for: @@ -3461,7 +3464,6 @@ SOKOL_GFX_API_DECL sg_backend sg_query_backend(void); SOKOL_GFX_API_DECL sg_features sg_query_features(void); SOKOL_GFX_API_DECL sg_limits sg_query_limits(void); SOKOL_GFX_API_DECL sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt); -SOKOL_GFX_API_DECL sg_frame_stats sg_query_frame_stats(void); // get current state of a resource (INITIAL, ALLOC, VALID, FAILED, INVALID) SOKOL_GFX_API_DECL sg_resource_state sg_query_buffer_state(sg_buffer buf); SOKOL_GFX_API_DECL sg_resource_state sg_query_image_state(sg_image img); @@ -3523,6 +3525,12 @@ SOKOL_GFX_API_DECL void sg_fail_shader(sg_shader shd); SOKOL_GFX_API_DECL void sg_fail_pipeline(sg_pipeline pip); SOKOL_GFX_API_DECL void sg_fail_pass(sg_pass pass); +// frame stats +SOKOL_GFX_API_DECL void sg_enable_frame_stats(void); +SOKOL_GFX_API_DECL void sg_disable_frame_stats(void); +SOKOL_GFX_API_DECL bool sg_frame_stats_enabled(void); +SOKOL_GFX_API_DECL sg_frame_stats sg_query_frame_stats(void); + // rendering contexts (optional) SOKOL_GFX_API_DECL sg_context sg_setup_context(void); SOKOL_GFX_API_DECL void sg_activate_context(sg_context ctx_id); @@ -4143,6 +4151,7 @@ typedef struct { #define _sg_clamp(v,v0,v1) (((v)<(v0))?(v0):(((v)>(v1))?(v1):(v))) #define _sg_fequal(val,cmp,delta) ((((val)-(cmp))> -(delta))&&(((val)-(cmp))<(delta))) #define _sg_ispow2(val) ((val&(val-1))==0) +#define _sg_stats_add(key,val) {if(_sg.stats_enabled){ _sg.stats.key+=val;}} _SOKOL_PRIVATE void* _sg_malloc_clear(size_t size); _SOKOL_PRIVATE void _sg_free(void* ptr); @@ -5131,6 +5140,7 @@ typedef struct { sg_features features; sg_limits limits; sg_pixelformat_info formats[_SG_PIXELFORMAT_NUM]; + bool stats_enabled; sg_frame_stats stats; sg_frame_stats prev_stats; #if defined(_SOKOL_ANY_GL) @@ -12615,7 +12625,7 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_begin_pass(void) { _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, 0, _sg.wgpu.uniform.staging, _sg.wgpu.uniform.offset); - _sg.stats.wgpu.size_uniform_write_buffer += _sg.wgpu.uniform.offset; + _sg_stats_add(wgpu.size_uniform_write_buffer, _sg.wgpu.uniform.offset); _sg.wgpu.uniform.offset = 0; _sg_clear(&_sg.wgpu.uniform.bind.offsets[0][0], sizeof(_sg.wgpu.uniform.bind.offsets)); } @@ -12761,7 +12771,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_compare_bindgroups_cache_key(_sg_wgpu_bindgroups_ca return false; } if (memcmp(&k0->items, &k1->items, sizeof(k0->items)) != 0) { - _sg.stats.wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatch++; + _sg_stats_add(wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatch, 1); return false; } return true; @@ -12771,7 +12781,7 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup(_sg_bindings_t* b SOKOL_ASSERT(_sg.wgpu.dev); SOKOL_ASSERT(bnd->pip); SOKOL_ASSERT(bnd->pip->shader && (bnd->pip->cmn.shader_id.id == bnd->pip->shader->slot.id)); - _sg.stats.wgpu.bindings.num_create_bindgroup++; + _sg_stats_add(wgpu.bindings.num_create_bindgroup, 1); _sg_wgpu_bindgroup_handle_t bg_id = _sg_wgpu_alloc_bindgroup(); if (bg_id.id == SG_INVALID_ID) { return 0; @@ -12825,7 +12835,7 @@ _SOKOL_PRIVATE _sg_wgpu_bindgroup_t* _sg_wgpu_create_bindgroup(_sg_bindings_t* b _SOKOL_PRIVATE void _sg_wgpu_discard_bindgroup(_sg_wgpu_bindgroup_t* bg) { SOKOL_ASSERT(bg); - _sg.stats.wgpu.bindings.num_discard_bindgroup++; + _sg_stats_add(wgpu.bindings.num_discard_bindgroup, 1); if (bg->slot.state == SG_RESOURCESTATE_VALID) { if (bg->bindgroup) { wgpuBindGroupRelease(bg->bindgroup); @@ -12930,15 +12940,15 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { SOKOL_ASSERT(bg && (bg->slot.state == SG_RESOURCESTATE_VALID)); if (!_sg_wgpu_compare_bindgroups_cache_key(&key, &bg->key)) { // cache collision, need to delete cached bindgroup - _sg.stats.wgpu.bindings.num_bindgroup_cache_collisions++; + _sg_stats_add(wgpu.bindings.num_bindgroup_cache_collisions, 1); _sg_wgpu_discard_bindgroup(bg); _sg_wgpu_bindgroups_cache_set(key.hash, SG_INVALID_ID); bg = 0; } else { - _sg.stats.wgpu.bindings.num_bindgroup_cache_hits++; + _sg_stats_add(wgpu.bindings.num_bindgroup_cache_hits, 1); } } else { - _sg.stats.wgpu.bindings.num_bindgroup_cache_misses++; + _sg_stats_add(wgpu.bindings.num_bindgroup_cache_misses, 1); } if (bg == 0) { // either no cache entry yet, or cache collision, create new bindgroup and store in cache @@ -12947,7 +12957,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { } if (bg && bg->slot.state == SG_RESOURCESTATE_VALID) { SOKOL_ASSERT(bg->bindgroup); - _sg.stats.wgpu.bindings.num_set_bindgroup++; + _sg_stats_add(wgpu.bindings.num_set_bindgroup, 1); wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0); } else { return false; @@ -12958,7 +12968,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { if (bg) { if (bg->slot.state == SG_RESOURCESTATE_VALID) { SOKOL_ASSERT(bg->bindgroup); - _sg.stats.wgpu.bindings.num_set_bindgroup++; + _sg_stats_add(wgpu.bindings.num_set_bindgroup, 1); wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0); } _sg_wgpu_discard_bindgroup(bg); @@ -12967,7 +12977,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { } } } else { - _sg.stats.wgpu.bindings.num_set_empty_bindgroup++; + _sg_stats_add(wgpu.bindings.num_set_empty_bindgroup, 1); wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); } return true; @@ -13782,9 +13792,9 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindings(_sg_bindings_t* bnd) { SOKOL_ASSERT(buf_size > offset); const uint64_t max_bytes = buf_size - offset; wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, bnd->ib->wgpu.buf, format, offset, max_bytes); - _sg.stats.wgpu.bindings.num_set_index_buffer++; + _sg_stats_add(wgpu.bindings.num_set_index_buffer, 1); } else { - _sg.stats.wgpu.bindings.num_skip_set_index_buffer++; + _sg_stats_add(wgpu.bindings.num_skip_set_index_buffer, 1); } } // FIXME: else-path should actually set a null index buffer (this was just recently implemented in WebGPU) @@ -13798,9 +13808,9 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindings(_sg_bindings_t* bnd) { SOKOL_ASSERT(buf_size > offset); const uint64_t max_bytes = buf_size - offset; wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, (uint32_t)slot, bnd->vbs[slot]->wgpu.buf, offset, max_bytes); - _sg.stats.wgpu.bindings.num_set_vertex_buffer++; + _sg_stats_add(wgpu.bindings.num_set_vertex_buffer, 1); } else { - _sg.stats.wgpu.bindings.num_skip_set_vertex_buffer++; + _sg_stats_add(wgpu.bindings.num_skip_set_vertex_buffer, 1); } // FIXME: else-path should actually set a null vertex buffer (this was just recently implemented in WebGPU) } @@ -13824,7 +13834,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ SOKOL_ASSERT(data->size <= _sg.wgpu.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size); SOKOL_ASSERT(data->size <= _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); - _sg.stats.wgpu.num_uniform_set_bindgroup++; + _sg_stats_add(wgpu.num_uniform_set_bindgroup, 1); memcpy(_sg.wgpu.uniform.staging + _sg.wgpu.uniform.offset, data->ptr, data->size); _sg.wgpu.uniform.bind.offsets[stage_index][ub_index] = _sg.wgpu.uniform.offset; _sg.wgpu.uniform.offset = _sg_roundup_u32(_sg.wgpu.uniform.offset + (uint32_t)data->size, alignment); @@ -16244,6 +16254,7 @@ SOKOL_API_IMPL void sg_setup(const sg_desc* desc) { _sg_setup_pools(&_sg.pools, &_sg.desc); _sg_setup_commit_listeners(&_sg.desc); _sg.frame_index = 1; + _sg.stats_enabled = true; _sg_setup_backend(&_sg.desc); _sg.valid = true; sg_setup_context(); @@ -16998,7 +17009,7 @@ SOKOL_API_IMPL void sg_begin_pass(sg_pass pass_id, const sg_pass_action* pass_ac SOKOL_API_IMPL void sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left) { SOKOL_ASSERT(_sg.valid); - _sg.stats.num_apply_viewport++; + _sg_stats_add(num_apply_viewport, 1); if (!_sg.pass_valid) { return; } @@ -17012,7 +17023,7 @@ SOKOL_API_IMPL void sg_apply_viewportf(float x, float y, float width, float heig SOKOL_API_IMPL void sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left) { SOKOL_ASSERT(_sg.valid); - _sg.stats.num_apply_scissor_rect++; + _sg_stats_add(num_apply_scissor_rect, 1); if (!_sg.pass_valid) { return; } @@ -17026,7 +17037,7 @@ SOKOL_API_IMPL void sg_apply_scissor_rectf(float x, float y, float width, float SOKOL_API_IMPL void sg_apply_pipeline(sg_pipeline pip_id) { SOKOL_ASSERT(_sg.valid); - _sg.stats.num_apply_pipeline++; + _sg_stats_add(num_apply_pipeline, 1); _sg.bindings_applied = false; if (!_sg_validate_apply_pipeline(pip_id)) { _sg.next_draw_valid = false; @@ -17048,7 +17059,7 @@ SOKOL_API_IMPL void sg_apply_bindings(const sg_bindings* bindings) { SOKOL_ASSERT(_sg.valid); SOKOL_ASSERT(bindings); SOKOL_ASSERT((bindings->_start_canary == 0) && (bindings->_end_canary==0)); - _sg.stats.num_apply_bindings++; + _sg_stats_add(num_apply_bindings, 1); if (!_sg_validate_apply_bindings(bindings)) { _sg.next_draw_valid = false; return; @@ -17151,8 +17162,8 @@ SOKOL_API_IMPL void sg_apply_uniforms(sg_shader_stage stage, int ub_index, const SOKOL_ASSERT((stage == SG_SHADERSTAGE_VS) || (stage == SG_SHADERSTAGE_FS)); SOKOL_ASSERT((ub_index >= 0) && (ub_index < SG_MAX_SHADERSTAGE_UBS)); SOKOL_ASSERT(data && data->ptr && (data->size > 0)); - _sg.stats.num_apply_uniforms++; - _sg.stats.size_apply_uniforms += (uint32_t)data->size; + _sg_stats_add(num_apply_uniforms, 1); + _sg_stats_add(size_apply_uniforms, (uint32_t)data->size); if (!_sg_validate_apply_uniforms(stage, ub_index, data)) { _sg.next_draw_valid = false; return; @@ -17172,7 +17183,7 @@ SOKOL_API_IMPL void sg_draw(int base_element, int num_elements, int num_instance SOKOL_ASSERT(base_element >= 0); SOKOL_ASSERT(num_elements >= 0); SOKOL_ASSERT(num_instances >= 0); - _sg.stats.num_draw++; + _sg_stats_add(num_draw, 1); #if defined(SOKOL_DEBUG) if (!_sg.bindings_applied) { _SG_WARN(DRAW_WITHOUT_BINDINGS); @@ -17199,7 +17210,7 @@ SOKOL_API_IMPL void sg_draw(int base_element, int num_elements, int num_instance SOKOL_API_IMPL void sg_end_pass(void) { SOKOL_ASSERT(_sg.valid); - _sg.stats.num_passes++; + _sg_stats_add(num_passes, 1); if (!_sg.pass_valid) { return; } @@ -17230,8 +17241,8 @@ SOKOL_API_IMPL void sg_reset_state_cache(void) { SOKOL_API_IMPL void sg_update_buffer(sg_buffer buf_id, const sg_range* data) { SOKOL_ASSERT(_sg.valid); SOKOL_ASSERT(data && data->ptr && (data->size > 0)); - _sg.stats.num_update_buffer++; - _sg.stats.size_update_buffer += (uint32_t)data->size; + _sg_stats_add(num_update_buffer, 1); + _sg_stats_add(size_update_buffer, (uint32_t)data->size); _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id); if ((data->size > 0) && buf && (buf->slot.state == SG_RESOURCESTATE_VALID)) { if (_sg_validate_update_buffer(buf, data)) { @@ -17250,8 +17261,8 @@ SOKOL_API_IMPL void sg_update_buffer(sg_buffer buf_id, const sg_range* data) { SOKOL_API_IMPL int sg_append_buffer(sg_buffer buf_id, const sg_range* data) { SOKOL_ASSERT(_sg.valid); SOKOL_ASSERT(data && data->ptr); - _sg.stats.num_append_buffer++; - _sg.stats.size_append_buffer += (uint32_t)data->size; + _sg_stats_add(num_append_buffer, 1); + _sg_stats_add(size_append_buffer, (uint32_t)data->size); _sg_buffer_t* buf = _sg_lookup_buffer(&_sg.pools, buf_id.id); int result; if (buf) { @@ -17313,13 +17324,13 @@ SOKOL_API_IMPL bool sg_query_buffer_will_overflow(sg_buffer buf_id, size_t size) SOKOL_API_IMPL void sg_update_image(sg_image img_id, const sg_image_data* data) { SOKOL_ASSERT(_sg.valid); - _sg.stats.num_update_image++; + _sg_stats_add(num_update_image, 1); for (int face_index = 0; face_index < SG_CUBEFACE_NUM; face_index++) { for (int mip_index = 0; mip_index < SG_MAX_MIPMAPS; mip_index++) { if (data->subimage[face_index][mip_index].size == 0) { break; } - _sg.stats.size_update_image += (uint32_t)data->subimage[face_index][mip_index].size; + _sg_stats_add(size_update_image, (uint32_t)data->subimage[face_index][mip_index].size); } } _sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id); @@ -17355,6 +17366,20 @@ SOKOL_API_IMPL bool sg_remove_commit_listener(sg_commit_listener listener) { return _sg_remove_commit_listener(&listener); } +SOKOL_API_IMPL void sg_enable_frame_stats(void) { + SOKOL_ASSERT(_sg.valid); + _sg.stats_enabled = true; +} + +SOKOL_API_IMPL void sg_disable_frame_stats(void) { + SOKOL_ASSERT(_sg.valid); + _sg.stats_enabled = false; +} + +SOKOL_API_IMPL bool sg_frame_stats_enabled(void) { + return _sg.stats_enabled; +} + SOKOL_API_IMPL sg_buffer_info sg_query_buffer_info(sg_buffer buf_id) { SOKOL_ASSERT(_sg.valid); sg_buffer_info info; From 66abd127d2910b695474f19ded1ba589899c190f Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 16:05:26 +0200 Subject: [PATCH 70/95] sokol_gfx_imgui.h: allow to ignore sokol_imgui.h frame stats --- util/sokol_gfx_imgui.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h index 149ee1463..0cd60ae98 100644 --- a/util/sokol_gfx_imgui.h +++ b/util/sokol_gfx_imgui.h @@ -721,6 +721,8 @@ typedef struct sg_imgui_caps_t { typedef struct sg_imgui_frame_stats_t { bool open; + bool disable_sokol_imgui_stats; + bool in_sokol_imgui; sg_frame_stats stats; // FIXME: add a ringbuffer for a stats history here } sg_imgui_frame_stats_t; @@ -953,6 +955,9 @@ _SOKOL_PRIVATE void igTableNextRow(ImGuiTableRowFlags row_flags, float min_row_h _SOKOL_PRIVATE bool igTableSetColumnIndex(int column_n) { return ImGui::TableSetColumnIndex(column_n); } +_SOKOL_PRIVATE bool igCheckbox(const char* label, bool* v) { + return ImGui::Checkbox(label, v); +} #else #define IMVEC2(x,y) (ImVec2){x,y} #define IMVEC4(x,y,z,w) (ImVec4){x,y,z,w} @@ -3109,6 +3114,12 @@ _SOKOL_PRIVATE void _sg_imgui_fail_pass(sg_pass pass_id, void* user_data) { _SOKOL_PRIVATE void _sg_imgui_push_debug_group(const char* name, void* user_data) { sg_imgui_t* ctx = (sg_imgui_t*) user_data; SOKOL_ASSERT(ctx); + if (0 == strcmp(name, "sokol-imgui")) { + ctx->frame_stats.in_sokol_imgui = true; + if (ctx->frame_stats.disable_sokol_imgui_stats) { + sg_disable_frame_stats(); + } + } sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx); if (item) { item->cmd = SG_IMGUI_CMD_PUSH_DEBUG_GROUP; @@ -3123,6 +3134,12 @@ _SOKOL_PRIVATE void _sg_imgui_push_debug_group(const char* name, void* user_data _SOKOL_PRIVATE void _sg_imgui_pop_debug_group(void* user_data) { sg_imgui_t* ctx = (sg_imgui_t*) user_data; SOKOL_ASSERT(ctx); + if (ctx->frame_stats.in_sokol_imgui) { + ctx->frame_stats.in_sokol_imgui = false; + if (ctx->frame_stats.disable_sokol_imgui_stats) { + sg_enable_frame_stats(); + } + } sg_imgui_capture_item_t* item = _sg_imgui_capture_next_write_item(ctx); if (item) { item->cmd = SG_IMGUI_CMD_POP_DEBUG_GROUP; @@ -4208,6 +4225,7 @@ _SOKOL_PRIVATE void _sg_imgui_frame_stats_row(const char* key, uint32_t value) { _SOKOL_PRIVATE void _sg_imgui_draw_frame_stats_panel(sg_imgui_t* ctx) { _SOKOL_UNUSED(ctx); + igCheckbox("Ignore sokol_imgui.h", &ctx->frame_stats.disable_sokol_imgui_stats); const sg_frame_stats* stats = &ctx->frame_stats.stats; const ImGuiTableFlags flags = ImGuiTableFlags_Resizable | From 776dfbdfde5011d4fa38228abf281d54c7074a8e Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 16:56:36 +0200 Subject: [PATCH 71/95] sokol_gfx.h metal: add frame stats counters --- sokol_gfx.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index d02a27f2a..9d1aed452 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2876,10 +2876,47 @@ typedef struct sg_frame_stats_d3d11 { uint32_t fixme; } sg_frame_stats_d3d11; +typedef struct sg_frame_stats_metal_idpool { + uint32_t num_added; + uint32_t num_released; + uint32_t num_garbage_collected; +} sg_frame_stats_metal_idpool; + +typedef struct sg_frame_stats_metal_pipeline { + uint32_t num_set_blend_color; + uint32_t num_set_cull_mode; + uint32_t num_set_front_facing_winding; + uint32_t num_set_stencil_reference_value; + uint32_t num_set_depth_bias; + uint32_t num_set_render_pipeline_state; + uint32_t num_set_depth_stencil_state; +} sg_frame_stats_metal_pipeline; + +typedef struct sg_frame_stats_metal_bindings { + uint32_t num_set_vertex_buffer; + uint32_t num_set_vertex_texture; + uint32_t num_set_vertex_sampler_state; + uint32_t num_set_fragment_texture; + uint32_t num_set_fragment_sampler_state; +} sg_frame_stats_metal_bindings; + +typedef struct sg_frame_stats_metal_uniforms { + uint32_t num_set_vertex_buffer_offset; + uint32_t num_set_fragment_buffer_offset; +} sg_frame_stats_metal_uniforms; + typedef struct sg_frame_stats_metal { - uint32_t fixme; + sg_frame_stats_metal_idpool idpool; + sg_frame_stats_metal_pipeline pipeline; + sg_frame_stats_metal_bindings bindings; + sg_frame_stats_metal_uniforms uniforms; } sg_frame_stats_metal; +typedef struct sg_frame_stats_wgpu_uniforms { + uint32_t num_set_bindgroup; + uint32_t size_write_buffer; +} sg_frame_stats_wgpu_uniforms; + typedef struct sg_frame_stats_wgpu_bindings { uint32_t num_set_vertex_buffer; uint32_t num_skip_set_vertex_buffer; @@ -2896,8 +2933,7 @@ typedef struct sg_frame_stats_wgpu_bindings { } sg_frame_stats_wgpu_bindings; typedef struct sg_frame_stats_wgpu { - uint32_t num_uniform_set_bindgroup; - uint32_t size_uniform_write_buffer; + sg_frame_stats_wgpu_uniforms uniforms; sg_frame_stats_wgpu_bindings bindings; } sg_frame_stats_wgpu; @@ -10795,6 +10831,7 @@ _SOKOL_PRIVATE int _sg_mtl_add_resource(id res) { if (nil == res) { return _SG_MTL_INVALID_SLOT_INDEX; } + _sg_stats_add(metal.idpool.num_added, 1); const int slot_index = _sg_mtl_alloc_pool_slot(); // NOTE: the NSMutableArray will take ownership of its items SOKOL_ASSERT([NSNull null] == _sg.mtl.idpool.pool[(NSUInteger)slot_index]); @@ -10811,6 +10848,7 @@ _SOKOL_PRIVATE void _sg_mtl_release_resource(uint32_t frame_index, int slot_inde if (slot_index == _SG_MTL_INVALID_SLOT_INDEX) { return; } + _sg_stats_add(metal.idpool.num_released, 1); SOKOL_ASSERT((slot_index > 0) && (slot_index < _sg.mtl.idpool.num_slots)); SOKOL_ASSERT([NSNull null] != _sg.mtl.idpool.pool[(NSUInteger)slot_index]); int release_index = _sg.mtl.idpool.release_queue_front++; @@ -10833,6 +10871,7 @@ _SOKOL_PRIVATE void _sg_mtl_garbage_collect(uint32_t frame_index) { // don't need to check further, release-items past this are too young break; } + _sg_stats_add(metal.idpool.num_garbage_collected, 1); // safe to release this resource const int slot_index = _sg.mtl.idpool.release_queue[_sg.mtl.idpool.release_queue_back].slot_index; SOKOL_ASSERT((slot_index > 0) && (slot_index < _sg.mtl.idpool.num_slots)); @@ -11876,14 +11915,21 @@ _SOKOL_PRIVATE void _sg_mtl_apply_pipeline(_sg_pipeline_t* pip) { _sg.mtl.state_cache.cur_pipeline_id.id = pip->slot.id; sg_color c = pip->cmn.blend_color; [_sg.mtl.cmd_encoder setBlendColorRed:c.r green:c.g blue:c.b alpha:c.a]; + _sg_stats_add(metal.pipeline.num_set_blend_color, 1); [_sg.mtl.cmd_encoder setCullMode:pip->mtl.cull_mode]; + _sg_stats_add(metal.pipeline.num_set_cull_mode, 1); [_sg.mtl.cmd_encoder setFrontFacingWinding:pip->mtl.winding]; + _sg_stats_add(metal.pipeline.num_set_front_facing_winding, 1); [_sg.mtl.cmd_encoder setStencilReferenceValue:pip->mtl.stencil_ref]; + _sg_stats_add(metal.pipeline.num_set_stencil_reference_value, 1); [_sg.mtl.cmd_encoder setDepthBias:pip->cmn.depth.bias slopeScale:pip->cmn.depth.bias_slope_scale clamp:pip->cmn.depth.bias_clamp]; + _sg_stats_add(metal.pipeline.num_set_depth_bias, 1); SOKOL_ASSERT(pip->mtl.rps != _SG_MTL_INVALID_SLOT_INDEX); [_sg.mtl.cmd_encoder setRenderPipelineState:_sg_mtl_id(pip->mtl.rps)]; + _sg_stats_add(metal.pipeline.num_set_render_pipeline_state, 1); SOKOL_ASSERT(pip->mtl.dss != _SG_MTL_INVALID_SLOT_INDEX); [_sg.mtl.cmd_encoder setDepthStencilState:_sg_mtl_id(pip->mtl.dss)]; + _sg_stats_add(metal.pipeline.num_set_depth_stencil_state, 1); } } @@ -11922,6 +11968,7 @@ _SOKOL_PRIVATE bool _sg_mtl_apply_bindings(_sg_bindings_t* bnd) { [_sg.mtl.cmd_encoder setVertexBuffer:_sg_mtl_id(vb->mtl.buf[vb->cmn.active_slot]) offset:(NSUInteger)vb_offset atIndex:mtl_slot]; + _sg_stats_add(metal.bindings.num_set_vertex_buffer, 1); } } @@ -11933,6 +11980,7 @@ _SOKOL_PRIVATE bool _sg_mtl_apply_bindings(_sg_bindings_t* bnd) { _sg.mtl.state_cache.cur_vs_image_ids[slot].id = img->slot.id; SOKOL_ASSERT(img->mtl.tex[img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX); [_sg.mtl.cmd_encoder setVertexTexture:_sg_mtl_id(img->mtl.tex[img->cmn.active_slot]) atIndex:slot]; + _sg_stats_add(metal.bindings.num_set_vertex_texture, 1); } } @@ -11944,6 +11992,7 @@ _SOKOL_PRIVATE bool _sg_mtl_apply_bindings(_sg_bindings_t* bnd) { _sg.mtl.state_cache.cur_vs_sampler_ids[slot].id = smp->slot.id; SOKOL_ASSERT(smp->mtl.sampler_state != _SG_MTL_INVALID_SLOT_INDEX); [_sg.mtl.cmd_encoder setVertexSamplerState:_sg_mtl_id(smp->mtl.sampler_state) atIndex:slot]; + _sg_stats_add(metal.bindings.num_set_vertex_sampler_state, 1); } } @@ -11955,6 +12004,7 @@ _SOKOL_PRIVATE bool _sg_mtl_apply_bindings(_sg_bindings_t* bnd) { _sg.mtl.state_cache.cur_fs_image_ids[slot].id = img->slot.id; SOKOL_ASSERT(img->mtl.tex[img->cmn.active_slot] != _SG_MTL_INVALID_SLOT_INDEX); [_sg.mtl.cmd_encoder setFragmentTexture:_sg_mtl_id(img->mtl.tex[img->cmn.active_slot]) atIndex:slot]; + _sg_stats_add(metal.bindings.num_set_fragment_texture, 1); } } @@ -11966,6 +12016,7 @@ _SOKOL_PRIVATE bool _sg_mtl_apply_bindings(_sg_bindings_t* bnd) { _sg.mtl.state_cache.cur_fs_sampler_ids[slot].id = smp->slot.id; SOKOL_ASSERT(smp->mtl.sampler_state != _SG_MTL_INVALID_SLOT_INDEX); [_sg.mtl.cmd_encoder setFragmentSamplerState:_sg_mtl_id(smp->mtl.sampler_state) atIndex:slot]; + _sg_stats_add(metal.bindings.num_set_fragment_sampler_state, 1); } } return true; @@ -11990,8 +12041,10 @@ _SOKOL_PRIVATE void _sg_mtl_apply_uniforms(sg_shader_stage stage_index, int ub_i memcpy(dst, data->ptr, data->size); if (stage_index == SG_SHADERSTAGE_VS) { [_sg.mtl.cmd_encoder setVertexBufferOffset:(NSUInteger)_sg.mtl.cur_ub_offset atIndex:(NSUInteger)ub_index]; + _sg_stats_add(metal.uniforms.num_set_vertex_buffer_offset, 1); } else { [_sg.mtl.cmd_encoder setFragmentBufferOffset:(NSUInteger)_sg.mtl.cur_ub_offset atIndex:(NSUInteger)ub_index]; + _sg_stats_add(metal.uniforms.num_set_fragment_buffer_offset, 1); } _sg.mtl.cur_ub_offset = _sg_roundup(_sg.mtl.cur_ub_offset + (int)data->size, _SG_MTL_UB_ALIGN); } From f9e62ce7b9051513ca4bed3aa18c5ea414781877 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 17:06:07 +0200 Subject: [PATCH 72/95] sokol_gfx.h wgpu: stats tracking cleanup --- sokol_gfx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 9d1aed452..9d3b8b574 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12678,7 +12678,7 @@ _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_begin_pass(void) { _SOKOL_PRIVATE void _sg_wgpu_uniform_buffer_on_commit(void) { wgpuQueueWriteBuffer(_sg.wgpu.queue, _sg.wgpu.uniform.buf, 0, _sg.wgpu.uniform.staging, _sg.wgpu.uniform.offset); - _sg_stats_add(wgpu.size_uniform_write_buffer, _sg.wgpu.uniform.offset); + _sg_stats_add(wgpu.uniforms.size_write_buffer, _sg.wgpu.uniform.offset); _sg.wgpu.uniform.offset = 0; _sg_clear(&_sg.wgpu.uniform.bind.offsets[0][0], sizeof(_sg.wgpu.uniform.bind.offsets)); } @@ -13887,7 +13887,7 @@ _SOKOL_PRIVATE void _sg_wgpu_apply_uniforms(sg_shader_stage stage_index, int ub_ SOKOL_ASSERT(data->size <= _sg.wgpu.cur_pipeline->shader->cmn.stage[stage_index].uniform_blocks[ub_index].size); SOKOL_ASSERT(data->size <= _SG_WGPU_MAX_UNIFORM_UPDATE_SIZE); - _sg_stats_add(wgpu.num_uniform_set_bindgroup, 1); + _sg_stats_add(wgpu.uniforms.num_set_bindgroup, 1); memcpy(_sg.wgpu.uniform.staging + _sg.wgpu.uniform.offset, data->ptr, data->size); _sg.wgpu.uniform.bind.offsets[stage_index][ub_index] = _sg.wgpu.uniform.offset; _sg.wgpu.uniform.offset = _sg_roundup_u32(_sg.wgpu.uniform.offset + (uint32_t)data->size, alignment); From b2db2d5234e00fe3719815b383d8b902ec46c058 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 17:06:40 +0200 Subject: [PATCH 73/95] sokol_gfx_imgui.h: stats tracking panel cleanup --- util/sokol_gfx_imgui.h | 87 +++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 31 deletions(-) diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h index 0cd60ae98..00c27baf1 100644 --- a/util/sokol_gfx_imgui.h +++ b/util/sokol_gfx_imgui.h @@ -4215,7 +4215,7 @@ _SOKOL_PRIVATE void _sg_imgui_draw_caps_panel(void) { } } -_SOKOL_PRIVATE void _sg_imgui_frame_stats_row(const char* key, uint32_t value) { +_SOKOL_PRIVATE void _sg_imgui_frame_add_stats_row(const char* key, uint32_t value) { igTableNextRow(0, 0.0f); igTableSetColumnIndex(0); igText(key); @@ -4223,6 +4223,8 @@ _SOKOL_PRIVATE void _sg_imgui_frame_stats_row(const char* key, uint32_t value) { igText("%d", value); } +#define _sg_imgui_frame_stats(key) _sg_imgui_frame_add_stats_row(#key, stats->key) + _SOKOL_PRIVATE void _sg_imgui_draw_frame_stats_panel(sg_imgui_t* ctx) { _SOKOL_UNUSED(ctx); igCheckbox("Ignore sokol_imgui.h", &ctx->frame_stats.disable_sokol_imgui_stats); @@ -4237,36 +4239,59 @@ _SOKOL_PRIVATE void _sg_imgui_draw_frame_stats_panel(sg_imgui_t* ctx) { igTableSetupColumn("key", ImGuiTableColumnFlags_None, 0, 0); igTableSetupColumn("value", ImGuiTableColumnFlags_None, 0, 0); igTableHeadersRow(); - _sg_imgui_frame_stats_row("frame_index", stats->frame_index); - _sg_imgui_frame_stats_row("num_passes", stats->num_passes); - _sg_imgui_frame_stats_row("num_apply_viewport", stats->num_apply_viewport); - _sg_imgui_frame_stats_row("num_apply_scissor_rect", stats->num_apply_scissor_rect); - _sg_imgui_frame_stats_row("num_apply_pipeline", stats->num_apply_pipeline); - _sg_imgui_frame_stats_row("num_apply_bindings", stats->num_apply_bindings); - _sg_imgui_frame_stats_row("num_apply_uniforms", stats->num_apply_uniforms); - _sg_imgui_frame_stats_row("num_draw", stats->num_draw); - _sg_imgui_frame_stats_row("num_update_buffer", stats->num_update_buffer); - _sg_imgui_frame_stats_row("num_append_buffer", stats->num_append_buffer); - _sg_imgui_frame_stats_row("num_update_image", stats->num_update_image); - _sg_imgui_frame_stats_row("size_apply_uniforms", stats->size_apply_uniforms); - _sg_imgui_frame_stats_row("size_update_buffer", stats->size_update_buffer); - _sg_imgui_frame_stats_row("size_append_buffer", stats->size_append_buffer); - _sg_imgui_frame_stats_row("size_update_image", stats->size_update_image); - if (sg_query_backend() == SG_BACKEND_WGPU) { - _sg_imgui_frame_stats_row("wgpu.num_uniform_set_bindgroup", stats->wgpu.num_uniform_set_bindgroup); - _sg_imgui_frame_stats_row("wgpu.size_uniform_write_buffer", stats->wgpu.size_uniform_write_buffer); - _sg_imgui_frame_stats_row("wgpu.bindings.num_set_vertex_buffer", stats->wgpu.bindings.num_set_vertex_buffer); - _sg_imgui_frame_stats_row("wgpu.bindings.num_skip_set_vertex_buffer", stats->wgpu.bindings.num_skip_set_vertex_buffer); - _sg_imgui_frame_stats_row("wgpu.bindings.num_set_index_buffer", stats->wgpu.bindings.num_set_index_buffer); - _sg_imgui_frame_stats_row("wgpu.bindings.num_skip_set_index_buffer", stats->wgpu.bindings.num_skip_set_index_buffer); - _sg_imgui_frame_stats_row("wgpu.bindings.num_create_bindgroup", stats->wgpu.bindings.num_create_bindgroup); - _sg_imgui_frame_stats_row("wgpu.bindings.num_discard_bindgroup", stats->wgpu.bindings.num_discard_bindgroup); - _sg_imgui_frame_stats_row("wgpu.bindings.num_set_bindgroup", stats->wgpu.bindings.num_set_bindgroup); - _sg_imgui_frame_stats_row("wgpu.bindings.num_set_empty_bindgroup", stats->wgpu.bindings.num_set_empty_bindgroup); - _sg_imgui_frame_stats_row("wgpu.bindings.num_bindgroup_cache_hits", stats->wgpu.bindings.num_bindgroup_cache_hits); - _sg_imgui_frame_stats_row("wpgu.bindings.num_bindgroup_cache_misses", stats->wgpu.bindings.num_bindgroup_cache_misses); - _sg_imgui_frame_stats_row("wgpu.bindings.num_bindgroup_cache_collisions", stats->wgpu.bindings.num_bindgroup_cache_collisions); - _sg_imgui_frame_stats_row("wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatches", stats->wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatch); + _sg_imgui_frame_stats(num_passes); + _sg_imgui_frame_stats(num_apply_viewport); + _sg_imgui_frame_stats(num_apply_scissor_rect); + _sg_imgui_frame_stats(num_apply_pipeline); + _sg_imgui_frame_stats(num_apply_bindings); + _sg_imgui_frame_stats(num_apply_uniforms); + _sg_imgui_frame_stats(num_draw); + _sg_imgui_frame_stats(num_update_buffer); + _sg_imgui_frame_stats(num_append_buffer); + _sg_imgui_frame_stats(num_update_image); + _sg_imgui_frame_stats(size_apply_uniforms); + _sg_imgui_frame_stats(size_update_buffer); + _sg_imgui_frame_stats(size_append_buffer); + _sg_imgui_frame_stats(size_update_image); + switch (sg_query_backend()) { + case SG_BACKEND_WGPU: + _sg_imgui_frame_stats(wgpu.uniforms.num_set_bindgroup); + _sg_imgui_frame_stats(wgpu.uniforms.size_write_buffer); + _sg_imgui_frame_stats(wgpu.bindings.num_set_vertex_buffer); + _sg_imgui_frame_stats(wgpu.bindings.num_skip_set_vertex_buffer); + _sg_imgui_frame_stats(wgpu.bindings.num_set_index_buffer); + _sg_imgui_frame_stats(wgpu.bindings.num_skip_set_index_buffer); + _sg_imgui_frame_stats(wgpu.bindings.num_create_bindgroup); + _sg_imgui_frame_stats(wgpu.bindings.num_discard_bindgroup); + _sg_imgui_frame_stats(wgpu.bindings.num_set_bindgroup); + _sg_imgui_frame_stats(wgpu.bindings.num_set_empty_bindgroup); + _sg_imgui_frame_stats(wgpu.bindings.num_bindgroup_cache_hits); + _sg_imgui_frame_stats(wgpu.bindings.num_bindgroup_cache_misses); + _sg_imgui_frame_stats(wgpu.bindings.num_bindgroup_cache_collisions); + _sg_imgui_frame_stats(wgpu.bindings.num_bindgroup_cache_hash_vs_key_mismatch); + break; + case SG_BACKEND_METAL_MACOS: + case SG_BACKEND_METAL_IOS: + case SG_BACKEND_METAL_SIMULATOR: + _sg_imgui_frame_stats(metal.idpool.num_added); + _sg_imgui_frame_stats(metal.idpool.num_released); + _sg_imgui_frame_stats(metal.idpool.num_garbage_collected); + _sg_imgui_frame_stats(metal.pipeline.num_set_blend_color); + _sg_imgui_frame_stats(metal.pipeline.num_set_cull_mode); + _sg_imgui_frame_stats(metal.pipeline.num_set_front_facing_winding); + _sg_imgui_frame_stats(metal.pipeline.num_set_stencil_reference_value); + _sg_imgui_frame_stats(metal.pipeline.num_set_depth_bias); + _sg_imgui_frame_stats(metal.pipeline.num_set_render_pipeline_state); + _sg_imgui_frame_stats(metal.pipeline.num_set_depth_stencil_state); + _sg_imgui_frame_stats(metal.bindings.num_set_vertex_buffer); + _sg_imgui_frame_stats(metal.bindings.num_set_vertex_texture); + _sg_imgui_frame_stats(metal.bindings.num_set_vertex_sampler_state); + _sg_imgui_frame_stats(metal.bindings.num_set_fragment_texture); + _sg_imgui_frame_stats(metal.bindings.num_set_fragment_sampler_state); + _sg_imgui_frame_stats(metal.uniforms.num_set_vertex_buffer_offset); + _sg_imgui_frame_stats(metal.uniforms.num_set_fragment_buffer_offset); + break; + default: break; } igEndTable(); } From 44183993c520b5b161a6ad719d5157dced72031b Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 19:45:36 +0200 Subject: [PATCH 74/95] sokol_gfx.h gl: add frame stats --- sokol_gfx.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 9d3b8b574..8fae65eb1 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2869,7 +2869,17 @@ typedef struct sg_pass_info { struct will contains information about the *previous* frame. */ typedef struct sg_frame_stats_gl { - uint32_t fixme; + uint32_t num_bind_buffer; + uint32_t num_active_texture; + uint32_t num_bind_texture; + uint32_t num_bind_sampler; + uint32_t num_use_program; + uint32_t num_render_state; + uint32_t num_vertex_attrib_pointer; + uint32_t num_vertex_attrib_divisor; + uint32_t num_enable_vertex_attrib_array; + uint32_t num_disable_vertex_attrib_array; + uint32_t num_uniform; } sg_frame_stats_gl; typedef struct sg_frame_stats_d3d11 { @@ -6965,10 +6975,12 @@ _SOKOL_PRIVATE void _sg_gl_cache_clear_buffer_bindings(bool force) { if (force || (_sg.gl.cache.vertex_buffer != 0)) { glBindBuffer(GL_ARRAY_BUFFER, 0); _sg.gl.cache.vertex_buffer = 0; + _sg_stats_add(gl.num_bind_buffer, 1); } if (force || (_sg.gl.cache.index_buffer != 0)) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); _sg.gl.cache.index_buffer = 0; + _sg_stats_add(gl.num_bind_buffer, 1); } } @@ -6978,11 +6990,13 @@ _SOKOL_PRIVATE void _sg_gl_cache_bind_buffer(GLenum target, GLuint buffer) { if (_sg.gl.cache.vertex_buffer != buffer) { _sg.gl.cache.vertex_buffer = buffer; glBindBuffer(target, buffer); + _sg_stats_add(gl.num_bind_buffer, 1); } } else { if (_sg.gl.cache.index_buffer != buffer) { _sg.gl.cache.index_buffer = buffer; glBindBuffer(target, buffer); + _sg_stats_add(gl.num_bind_buffer, 1); } } } @@ -7016,10 +7030,12 @@ _SOKOL_PRIVATE void _sg_gl_cache_invalidate_buffer(GLuint buf) { if (buf == _sg.gl.cache.vertex_buffer) { _sg.gl.cache.vertex_buffer = 0; glBindBuffer(GL_ARRAY_BUFFER, 0); + _sg_stats_add(gl.num_bind_buffer, 1); } if (buf == _sg.gl.cache.index_buffer) { _sg.gl.cache.index_buffer = 0; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + _sg_stats_add(gl.num_bind_buffer, 1); } if (buf == _sg.gl.cache.stored_vertex_buffer) { _sg.gl.cache.stored_vertex_buffer = 0; @@ -7039,6 +7055,7 @@ _SOKOL_PRIVATE void _sg_gl_cache_active_texture(GLenum texture) { if (_sg.gl.cache.cur_active_texture != texture) { _sg.gl.cache.cur_active_texture = texture; glActiveTexture(texture); + _sg_stats_add(gl.num_active_texture, 1); } _SG_GL_CHECK_ERROR(); } @@ -7049,11 +7066,14 @@ _SOKOL_PRIVATE void _sg_gl_cache_clear_texture_sampler_bindings(bool force) { if (force || (_sg.gl.cache.texture_samplers[i].texture != 0)) { GLenum gl_texture_unit = (GLenum) (GL_TEXTURE0 + i); glActiveTexture(gl_texture_unit); + _sg_stats_add(gl.num_active_texture, 1); glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glBindTexture(GL_TEXTURE_3D, 0); glBindTexture(GL_TEXTURE_2D_ARRAY, 0); + _sg_stats_add(gl.num_bind_texture, 4); glBindSampler((GLuint)i, 0); + _sg_stats_add(gl.num_bind_sampler, 1); _sg.gl.cache.texture_samplers[i].target = 0; _sg.gl.cache.texture_samplers[i].texture = 0; _sg.gl.cache.texture_samplers[i].sampler = 0; @@ -7080,15 +7100,18 @@ _SOKOL_PRIVATE void _sg_gl_cache_bind_texture_sampler(int slot_index, GLenum tar if ((target != slot->target) && (slot->target != 0)) { glBindTexture(slot->target, 0); _SG_GL_CHECK_ERROR(); + _sg_stats_add(gl.num_bind_texture, 1); } // apply new binding (can be 0 to unbind) if (target != 0) { glBindTexture(target, texture); _SG_GL_CHECK_ERROR(); + _sg_stats_add(gl.num_bind_texture, 1); } // apply new sampler (can be 0 to unbind) glBindSampler((GLuint)slot_index, sampler); _SG_GL_CHECK_ERROR(); + _sg_stats_add(gl.num_bind_sampler, 1); slot->target = target; slot->texture = texture; @@ -7123,8 +7146,10 @@ _SOKOL_PRIVATE void _sg_gl_cache_invalidate_texture_sampler(GLuint tex, GLuint s _sg_gl_cache_active_texture((GLenum)(GL_TEXTURE0 + i)); glBindTexture(slot->target, 0); _SG_GL_CHECK_ERROR(); + _sg_stats_add(gl.num_bind_texture, 1); glBindSampler((GLuint)i, 0); _SG_GL_CHECK_ERROR(); + _sg_stats_add(gl.num_bind_sampler, 1); slot->target = 0; slot->texture = 0; slot->sampler = 0; @@ -7142,6 +7167,7 @@ _SOKOL_PRIVATE void _sg_gl_cache_invalidate_program(GLuint prog) { if (prog == _sg.gl.cache.prog) { _sg.gl.cache.prog = 0; glUseProgram(0); + _sg_stats_add(gl.num_use_program, 1); } } @@ -7169,6 +7195,7 @@ _SOKOL_PRIVATE void _sg_gl_reset_state_cache(void) { attr->divisor = -1; glDisableVertexAttribArray((GLuint)i); _SG_GL_CHECK_ERROR(); + _sg_stats_add(gl.num_disable_vertex_attrib_array, 1); } _sg.gl.cache.cur_primitive_type = GL_TRIANGLES; @@ -7193,6 +7220,7 @@ _SOKOL_PRIVATE void _sg_gl_reset_state_cache(void) { glStencilFunc(GL_ALWAYS, 0, 0); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilMask(0); + _sg_stats_add(gl.num_render_state, 7); // blend state _sg.gl.cache.blend.src_factor_rgb = SG_BLENDFACTOR_ONE; @@ -7205,6 +7233,7 @@ _SOKOL_PRIVATE void _sg_gl_reset_state_cache(void) { glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO); glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD); glBlendColor(0.0f, 0.0f, 0.0f, 0.0f); + _sg_stats_add(gl.num_render_state, 4); // standalone state for (int i = 0; i < SG_MAX_COLOR_ATTACHMENTS; i++) { @@ -7223,9 +7252,11 @@ _SOKOL_PRIVATE void _sg_gl_reset_state_cache(void) { glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); glEnable(GL_DITHER); glDisable(GL_POLYGON_OFFSET_FILL); + _sg_stats_add(gl.num_render_state, 10); #if defined(SOKOL_GLCORE33) glEnable(GL_MULTISAMPLE); glEnable(GL_PROGRAM_POINT_SIZE); + _sg_stats_add(gl.num_render_state, 2); #endif } } @@ -8095,10 +8126,12 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { if (state_ds->compare != cache_ds->compare) { cache_ds->compare = state_ds->compare; glDepthFunc(_sg_gl_compare_func(state_ds->compare)); + _sg_stats_add(gl.num_render_state, 1); } if (state_ds->write_enabled != cache_ds->write_enabled) { cache_ds->write_enabled = state_ds->write_enabled; glDepthMask(state_ds->write_enabled); + _sg_stats_add(gl.num_render_state, 1); } if (!_sg_fequal(state_ds->bias, cache_ds->bias, 0.000001f) || !_sg_fequal(state_ds->bias_slope_scale, cache_ds->bias_slope_scale, 0.000001f)) @@ -8111,6 +8144,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { cache_ds->bias = state_ds->bias; cache_ds->bias_slope_scale = state_ds->bias_slope_scale; glPolygonOffset(state_ds->bias_slope_scale, state_ds->bias); + _sg_stats_add(gl.num_render_state, 1); bool po_enabled = true; if (_sg_fequal(state_ds->bias, 0.0f, 0.000001f) && _sg_fequal(state_ds->bias_slope_scale, 0.0f, 0.000001f)) @@ -8124,6 +8158,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { } else { glDisable(GL_POLYGON_OFFSET_FILL); } + _sg_stats_add(gl.num_render_state, 1); } } } @@ -8139,10 +8174,12 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { } else { glDisable(GL_STENCIL_TEST); } + _sg_stats_add(gl.num_render_state, 1); } if (state_ss->write_mask != cache_ss->write_mask) { cache_ss->write_mask = state_ss->write_mask; glStencilMask(state_ss->write_mask); + _sg_stats_add(gl.num_render_state, 1); } for (int i = 0; i < 2; i++) { const sg_stencil_face_state* state_sfs = (i==0)? &state_ss->front : &state_ss->back; @@ -8157,6 +8194,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { _sg_gl_compare_func(state_sfs->compare), state_ss->ref, state_ss->read_mask); + _sg_stats_add(gl.num_render_state, 1); } if ((state_sfs->fail_op != cache_sfs->fail_op) || (state_sfs->depth_fail_op != cache_sfs->depth_fail_op) || @@ -8169,6 +8207,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { _sg_gl_stencil_op(state_sfs->fail_op), _sg_gl_stencil_op(state_sfs->depth_fail_op), _sg_gl_stencil_op(state_sfs->pass_op)); + _sg_stats_add(gl.num_render_state, 1); } } cache_ss->read_mask = state_ss->read_mask; @@ -8187,6 +8226,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { } else { glDisable(GL_BLEND); } + _sg_stats_add(gl.num_render_state, 1); } if ((state_bs->src_factor_rgb != cache_bs->src_factor_rgb) || (state_bs->dst_factor_rgb != cache_bs->dst_factor_rgb) || @@ -8201,11 +8241,13 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { _sg_gl_blend_factor(state_bs->dst_factor_rgb), _sg_gl_blend_factor(state_bs->src_factor_alpha), _sg_gl_blend_factor(state_bs->dst_factor_alpha)); + _sg_stats_add(gl.num_render_state, 1); } if ((state_bs->op_rgb != cache_bs->op_rgb) || (state_bs->op_alpha != cache_bs->op_alpha)) { cache_bs->op_rgb = state_bs->op_rgb; cache_bs->op_alpha = state_bs->op_alpha; glBlendEquationSeparate(_sg_gl_blend_op(state_bs->op_rgb), _sg_gl_blend_op(state_bs->op_alpha)); + _sg_stats_add(gl.num_render_state, 1); } // standalone color target state @@ -8227,6 +8269,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { (cm & SG_COLORMASK_A) != 0); } #endif + _sg_stats_add(gl.num_render_state, 1); } } @@ -8238,6 +8281,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { sg_color c = pip->cmn.blend_color; _sg.gl.cache.blend_color = c; glBlendColor(c.r, c.g, c.b, c.a); + _sg_stats_add(gl.num_render_state, 1); } } // pip->cmn.color_count > 0 @@ -8245,16 +8289,19 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { _sg.gl.cache.cull_mode = pip->gl.cull_mode; if (SG_CULLMODE_NONE == pip->gl.cull_mode) { glDisable(GL_CULL_FACE); + _sg_stats_add(gl.num_render_state, 1); } else { glEnable(GL_CULL_FACE); GLenum gl_mode = (SG_CULLMODE_FRONT == pip->gl.cull_mode) ? GL_FRONT : GL_BACK; glCullFace(gl_mode); + _sg_stats_add(gl.num_render_state, 2); } } if (pip->gl.face_winding != _sg.gl.cache.face_winding) { _sg.gl.cache.face_winding = pip->gl.face_winding; GLenum gl_winding = (SG_FACEWINDING_CW == pip->gl.face_winding) ? GL_CW : GL_CCW; glFrontFace(gl_winding); + _sg_stats_add(gl.num_render_state, 1); } if (pip->gl.alpha_to_coverage_enabled != _sg.gl.cache.alpha_to_coverage_enabled) { _sg.gl.cache.alpha_to_coverage_enabled = pip->gl.alpha_to_coverage_enabled; @@ -8263,6 +8310,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { } else { glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); } + _sg_stats_add(gl.num_render_state, 1); } #ifdef SOKOL_GLCORE33 if (pip->gl.sample_count != _sg.gl.cache.sample_count) { @@ -8272,6 +8320,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { } else { glDisable(GL_MULTISAMPLE); } + _sg_stats_add(gl.num_render_state, 1); } #endif @@ -8279,6 +8328,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_pipeline(_sg_pipeline_t* pip) { if (pip->shader->gl.prog != _sg.gl.cache.prog) { _sg.gl.cache.prog = pip->shader->gl.prog; glUseProgram(pip->shader->gl.prog); + _sg_stats_add(gl.num_use_program, 1); } } _SG_GL_CHECK_ERROR(); @@ -8347,17 +8397,21 @@ _SOKOL_PRIVATE bool _sg_gl_apply_bindings(_sg_bindings_t* bnd) { { _sg_gl_cache_bind_buffer(GL_ARRAY_BUFFER, gl_vb); glVertexAttribPointer(attr_index, attr->size, attr->type, attr->normalized, attr->stride, (const GLvoid*)(GLintptr)vb_offset); + _sg_stats_add(gl.num_vertex_attrib_pointer, 1); glVertexAttribDivisor(attr_index, (GLuint)attr->divisor); + _sg_stats_add(gl.num_vertex_attrib_divisor, 1); cache_attr_dirty = true; } if (cache_attr->gl_attr.vb_index == -1) { glEnableVertexAttribArray(attr_index); + _sg_stats_add(gl.num_enable_vertex_attrib_array, 1); cache_attr_dirty = true; } } else { // attribute is disabled if (cache_attr->gl_attr.vb_index != -1) { glDisableVertexAttribArray(attr_index); + _sg_stats_add(gl.num_disable_vertex_attrib_array, 1); cache_attr_dirty = true; } } @@ -8385,6 +8439,7 @@ _SOKOL_PRIVATE void _sg_gl_apply_uniforms(sg_shader_stage stage_index, int ub_in if (u->gl_loc == -1) { continue; } + _sg_stats_add(gl.num_uniform, 1); GLfloat* fptr = (GLfloat*) (((uint8_t*)data->ptr) + u->offset); GLint* iptr = (GLint*) (((uint8_t*)data->ptr) + u->offset); switch (u->type) { From 43be6e751683a134292bbdd747fbba7a727962e5 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 2 Oct 2023 19:45:51 +0200 Subject: [PATCH 75/95] sokol_gfx_imgui.h: add gl stats to frame stats panel --- util/sokol_gfx_imgui.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h index 00c27baf1..ac9cf13e0 100644 --- a/util/sokol_gfx_imgui.h +++ b/util/sokol_gfx_imgui.h @@ -4254,6 +4254,20 @@ _SOKOL_PRIVATE void _sg_imgui_draw_frame_stats_panel(sg_imgui_t* ctx) { _sg_imgui_frame_stats(size_append_buffer); _sg_imgui_frame_stats(size_update_image); switch (sg_query_backend()) { + case SG_BACKEND_GLCORE33: + case SG_BACKEND_GLES3: + _sg_imgui_frame_stats(gl.num_bind_buffer); + _sg_imgui_frame_stats(gl.num_active_texture); + _sg_imgui_frame_stats(gl.num_bind_texture); + _sg_imgui_frame_stats(gl.num_bind_sampler); + _sg_imgui_frame_stats(gl.num_use_program); + _sg_imgui_frame_stats(gl.num_render_state); + _sg_imgui_frame_stats(gl.num_vertex_attrib_pointer); + _sg_imgui_frame_stats(gl.num_vertex_attrib_divisor); + _sg_imgui_frame_stats(gl.num_enable_vertex_attrib_array); + _sg_imgui_frame_stats(gl.num_disable_vertex_attrib_array); + _sg_imgui_frame_stats(gl.num_uniform); + break; case SG_BACKEND_WGPU: _sg_imgui_frame_stats(wgpu.uniforms.num_set_bindgroup); _sg_imgui_frame_stats(wgpu.uniforms.size_write_buffer); From a61ae2dd38ce3a7d2d6c105bc36ba9bb3c9e7c08 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 3 Oct 2023 14:20:16 +0200 Subject: [PATCH 76/95] sokol_gfx.h d3d11: add d3d11 specific frame stats --- sokol_gfx.h | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 8fae65eb1..cf3ee1a5b 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -2882,8 +2882,53 @@ typedef struct sg_frame_stats_gl { uint32_t num_uniform; } sg_frame_stats_gl; +typedef struct sg_frame_stats_d3d11_pass { + uint32_t num_om_set_render_targets; + uint32_t num_clear_render_target_view; + uint32_t num_clear_depth_stencil_view; + uint32_t num_resolve_subresource; +} sg_frame_stats_d3d11_pass; + +typedef struct sg_frame_stats_d3d11_pipeline { + uint32_t num_rs_set_state; + uint32_t num_om_set_depth_stencil_state; + uint32_t num_om_set_blend_state; + uint32_t num_ia_set_primitive_topology; + uint32_t num_ia_set_input_layout; + uint32_t num_vs_set_shader; + uint32_t num_vs_set_constant_buffers; + uint32_t num_ps_set_shader; + uint32_t num_ps_set_constant_buffers; +} sg_frame_stats_d3d11_pipeline; + +typedef struct sg_frame_stats_d3d11_bindings { + uint32_t num_ia_set_vertex_buffers; + uint32_t num_ia_set_index_buffer; + uint32_t num_vs_set_shader_resources; + uint32_t num_ps_set_shader_resources; + uint32_t num_vs_set_samplers; + uint32_t num_ps_set_samplers; +} sg_frame_stats_d3d11_bindings; + +typedef struct sg_frame_stats_d3d11_uniforms { + uint32_t num_update_subresource; +} sg_frame_stats_d3d11_uniforms; + +typedef struct sg_frame_stats_d3d11_draw { + uint32_t num_draw_indexed_instanced; + uint32_t num_draw_indexed; + uint32_t num_draw_instanced; + uint32_t num_draw; +} sg_frame_stats_d3d11_draw; + typedef struct sg_frame_stats_d3d11 { - uint32_t fixme; + sg_frame_stats_d3d11_pass pass; + sg_frame_stats_d3d11_pipeline pipeline; + sg_frame_stats_d3d11_bindings bindings; + sg_frame_stats_d3d11_uniforms uniforms; + sg_frame_stats_d3d11_draw draw; + uint32_t num_map; + uint32_t num_unmap; } sg_frame_stats_d3d11; typedef struct sg_frame_stats_metal_idpool { @@ -10171,6 +10216,7 @@ _SOKOL_PRIVATE void _sg_d3d11_begin_pass(_sg_pass_t* pass, const sg_pass_action* } // apply the render-target- and depth-stencil-views _sg_d3d11_OMSetRenderTargets(_sg.d3d11.ctx, SG_MAX_COLOR_ATTACHMENTS, _sg.d3d11.cur_rtvs, _sg.d3d11.cur_dsv); + _sg_stats_add(d3d11.pass.num_om_set_render_targets, 1); // set viewport and scissor rect to cover whole screen D3D11_VIEWPORT vp; @@ -10190,6 +10236,7 @@ _SOKOL_PRIVATE void _sg_d3d11_begin_pass(_sg_pass_t* pass, const sg_pass_action* for (int i = 0; i < _sg.d3d11.num_rtvs; i++) { if (action->colors[i].load_action == SG_LOADACTION_CLEAR) { _sg_d3d11_ClearRenderTargetView(_sg.d3d11.ctx, _sg.d3d11.cur_rtvs[i], &action->colors[i].clear_value.r); + _sg_stats_add(d3d11.pass.num_clear_render_target_view, 1); } } UINT ds_flags = 0; @@ -10201,6 +10248,7 @@ _SOKOL_PRIVATE void _sg_d3d11_begin_pass(_sg_pass_t* pass, const sg_pass_action* } if ((0 != ds_flags) && _sg.d3d11.cur_dsv) { _sg_d3d11_ClearDepthStencilView(_sg.d3d11.ctx, _sg.d3d11.cur_dsv, ds_flags, action->depth.clear_value, action->stencil.clear_value); + _sg_stats_add(d3d11.pass.num_clear_depth_stencil_view, 1); } } @@ -10240,6 +10288,7 @@ _SOKOL_PRIVATE void _sg_d3d11_end_pass(void) { color_img->d3d11.res, src_subres, color_img->d3d11.format); + _sg_stats_add(d3d11.pass.num_resolve_subresource, 1); } } } @@ -10300,6 +10349,15 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_pipeline(_sg_pipeline_t* pip) { _sg_d3d11_VSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_VS].cbufs); _sg_d3d11_PSSetShader(_sg.d3d11.ctx, pip->shader->d3d11.fs, NULL, 0); _sg_d3d11_PSSetConstantBuffers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_UBS, pip->shader->d3d11.stage[SG_SHADERSTAGE_FS].cbufs); + _sg_stats_add(d3d11.pipeline.num_rs_set_state, 1); + _sg_stats_add(d3d11.pipeline.num_om_set_depth_stencil_state, 1); + _sg_stats_add(d3d11.pipeline.num_om_set_blend_state, 1); + _sg_stats_add(d3d11.pipeline.num_ia_set_primitive_topology, 1); + _sg_stats_add(d3d11.pipeline.num_ia_set_input_layout, 1); + _sg_stats_add(d3d11.pipeline.num_vs_set_shader, 1); + _sg_stats_add(d3d11.pipeline.num_vs_set_constant_buffers, 1); + _sg_stats_add(d3d11.pipeline.num_ps_set_shader, 1); + _sg_stats_add(d3d11.pipeline.num_ps_set_constant_buffers, 1); } _SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_t* bnd) { @@ -10343,6 +10401,12 @@ _SOKOL_PRIVATE bool _sg_d3d11_apply_bindings(_sg_bindings_t* bnd) { _sg_d3d11_PSSetShaderResources(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_IMAGES, d3d11_fs_srvs); _sg_d3d11_VSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_SAMPLERS, d3d11_vs_smps); _sg_d3d11_PSSetSamplers(_sg.d3d11.ctx, 0, SG_MAX_SHADERSTAGE_SAMPLERS, d3d11_fs_smps); + _sg_stats_add(d3d11.bindings.num_ia_set_vertex_buffers, 1); + _sg_stats_add(d3d11.bindings.num_ia_set_index_buffer, 1); + _sg_stats_add(d3d11.bindings.num_vs_set_shader_resources, 1); + _sg_stats_add(d3d11.bindings.num_ps_set_shader_resources, 1); + _sg_stats_add(d3d11.bindings.num_vs_set_samplers, 1); + _sg_stats_add(d3d11.bindings.num_ps_set_samplers, 1); return true; } @@ -10355,6 +10419,7 @@ _SOKOL_PRIVATE void _sg_d3d11_apply_uniforms(sg_shader_stage stage_index, int ub ID3D11Buffer* cb = _sg.d3d11.cur_pipeline->shader->d3d11.stage[stage_index].cbufs[ub_index]; SOKOL_ASSERT(cb); _sg_d3d11_UpdateSubresource(_sg.d3d11.ctx, (ID3D11Resource*)cb, 0, NULL, data->ptr, 0, 0); + _sg_stats_add(d3d11.uniforms.num_update_subresource, 1); } _SOKOL_PRIVATE void _sg_d3d11_draw(int base_element, int num_elements, int num_instances) { @@ -10362,14 +10427,18 @@ _SOKOL_PRIVATE void _sg_d3d11_draw(int base_element, int num_elements, int num_i if (_sg.d3d11.use_indexed_draw) { if (_sg.d3d11.use_instanced_draw) { _sg_d3d11_DrawIndexedInstanced(_sg.d3d11.ctx, (UINT)num_elements, (UINT)num_instances, (UINT)base_element, 0, 0); + _sg_stats_add(d3d11.draw.num_draw_indexed_instanced, 1); } else { _sg_d3d11_DrawIndexed(_sg.d3d11.ctx, (UINT)num_elements, (UINT)base_element, 0); + _sg_stats_add(d3d11.draw.num_draw_indexed, 1); } } else { if (_sg.d3d11.use_instanced_draw) { _sg_d3d11_DrawInstanced(_sg.d3d11.ctx, (UINT)num_elements, (UINT)num_instances, (UINT)base_element, 0); + _sg_stats_add(d3d11.draw.num_draw_instanced, 1); } else { _sg_d3d11_Draw(_sg.d3d11.ctx, (UINT)num_elements, (UINT)base_element); + _sg_stats_add(d3d11.draw.num_draw, 1); } } } @@ -10384,9 +10453,11 @@ _SOKOL_PRIVATE void _sg_d3d11_update_buffer(_sg_buffer_t* buf, const sg_range* d SOKOL_ASSERT(buf->d3d11.buf); D3D11_MAPPED_SUBRESOURCE d3d11_msr; HRESULT hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr); + _sg_stats_add(d3d11.num_map, 1); if (SUCCEEDED(hr)) { memcpy(d3d11_msr.pData, data->ptr, data->size); _sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0); + _sg_stats_add(d3d11.num_unmap, 1); } else { _SG_ERROR(D3D11_MAP_FOR_UPDATE_BUFFER_FAILED); } @@ -10399,10 +10470,12 @@ _SOKOL_PRIVATE void _sg_d3d11_append_buffer(_sg_buffer_t* buf, const sg_range* d D3D11_MAP map_type = new_frame ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE; D3D11_MAPPED_SUBRESOURCE d3d11_msr; HRESULT hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0, map_type, 0, &d3d11_msr); + _sg_stats_add(d3d11.num_map, 1); if (SUCCEEDED(hr)) { uint8_t* dst_ptr = (uint8_t*)d3d11_msr.pData + buf->cmn.append_pos; memcpy(dst_ptr, data->ptr, data->size); _sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)buf->d3d11.buf, 0); + _sg_stats_add(d3d11.num_unmap, 1); } else { _SG_ERROR(D3D11_MAP_FOR_APPEND_BUFFER_FAILED); } @@ -10429,6 +10502,7 @@ _SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_data const size_t slice_offset = slice_size * (size_t)slice_index; const uint8_t* slice_ptr = ((const uint8_t*)subimg_data->ptr) + slice_offset; hr = _sg_d3d11_Map(_sg.d3d11.ctx, img->d3d11.res, subres_index, D3D11_MAP_WRITE_DISCARD, 0, &d3d11_msr); + _sg_stats_add(d3d11.num_map, 1); if (SUCCEEDED(hr)) { // FIXME: need to handle difference in depth-pitch for 3D textures as well! if (src_pitch == (int)d3d11_msr.RowPitch) { @@ -10444,6 +10518,7 @@ _SOKOL_PRIVATE void _sg_d3d11_update_image(_sg_image_t* img, const sg_image_data } } _sg_d3d11_Unmap(_sg.d3d11.ctx, img->d3d11.res, subres_index); + _sg_stats_add(d3d11.num_unmap, 1); } else { _SG_ERROR(D3D11_MAP_FOR_UPDATE_IMAGE_FAILED); } From df394f8e0105030ead34776048e1a4236b1f3c69 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 3 Oct 2023 14:20:46 +0200 Subject: [PATCH 77/95] sokol_gfx_imgui.h: add d3d11 frame stats to stats panel --- util/sokol_gfx_imgui.h | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h index ac9cf13e0..4d29a7418 100644 --- a/util/sokol_gfx_imgui.h +++ b/util/sokol_gfx_imgui.h @@ -4235,10 +4235,11 @@ _SOKOL_PRIVATE void _sg_imgui_draw_frame_stats_panel(sg_imgui_t* ctx) { ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Borders; if (igBeginTable("##frame_stats_table", 2, flags, IMVEC2(0, 0), 0)) { - igTableSetupScrollFreeze(0, 1); + igTableSetupScrollFreeze(0, 2); igTableSetupColumn("key", ImGuiTableColumnFlags_None, 0, 0); igTableSetupColumn("value", ImGuiTableColumnFlags_None, 0, 0); igTableHeadersRow(); + _sg_imgui_frame_stats(frame_index); _sg_imgui_frame_stats(num_passes); _sg_imgui_frame_stats(num_apply_viewport); _sg_imgui_frame_stats(num_apply_scissor_rect); @@ -4305,6 +4306,34 @@ _SOKOL_PRIVATE void _sg_imgui_draw_frame_stats_panel(sg_imgui_t* ctx) { _sg_imgui_frame_stats(metal.uniforms.num_set_vertex_buffer_offset); _sg_imgui_frame_stats(metal.uniforms.num_set_fragment_buffer_offset); break; + case SG_BACKEND_D3D11: + _sg_imgui_frame_stats(d3d11.pass.num_om_set_render_targets); + _sg_imgui_frame_stats(d3d11.pass.num_clear_render_target_view); + _sg_imgui_frame_stats(d3d11.pass.num_clear_depth_stencil_view); + _sg_imgui_frame_stats(d3d11.pass.num_resolve_subresource); + _sg_imgui_frame_stats(d3d11.pipeline.num_rs_set_state); + _sg_imgui_frame_stats(d3d11.pipeline.num_om_set_depth_stencil_state); + _sg_imgui_frame_stats(d3d11.pipeline.num_om_set_blend_state); + _sg_imgui_frame_stats(d3d11.pipeline.num_ia_set_primitive_topology); + _sg_imgui_frame_stats(d3d11.pipeline.num_ia_set_input_layout); + _sg_imgui_frame_stats(d3d11.pipeline.num_vs_set_shader); + _sg_imgui_frame_stats(d3d11.pipeline.num_vs_set_constant_buffers); + _sg_imgui_frame_stats(d3d11.pipeline.num_ps_set_shader); + _sg_imgui_frame_stats(d3d11.pipeline.num_ps_set_constant_buffers); + _sg_imgui_frame_stats(d3d11.bindings.num_ia_set_vertex_buffers); + _sg_imgui_frame_stats(d3d11.bindings.num_ia_set_index_buffer); + _sg_imgui_frame_stats(d3d11.bindings.num_vs_set_shader_resources); + _sg_imgui_frame_stats(d3d11.bindings.num_ps_set_shader_resources); + _sg_imgui_frame_stats(d3d11.bindings.num_vs_set_samplers); + _sg_imgui_frame_stats(d3d11.bindings.num_ps_set_samplers); + _sg_imgui_frame_stats(d3d11.uniforms.num_update_subresource); + _sg_imgui_frame_stats(d3d11.draw.num_draw_indexed_instanced); + _sg_imgui_frame_stats(d3d11.draw.num_draw_indexed); + _sg_imgui_frame_stats(d3d11.draw.num_draw_instanced); + _sg_imgui_frame_stats(d3d11.draw.num_draw); + _sg_imgui_frame_stats(d3d11.num_map); + _sg_imgui_frame_stats(d3d11.num_unmap); + break; default: break; } igEndTable(); From 639c202b7d8718aa56a906df78fff53fc91f5091 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 3 Oct 2023 15:24:09 +0200 Subject: [PATCH 78/95] add webgpu compilation tests --- tests/CMakeLists.txt | 7 ++++++- tests/CMakePresets.json | 28 ++++++++++++++++++++++++++++ tests/test_emscripten.sh | 2 ++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3545b7584..c30d5571f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -69,7 +69,12 @@ endif() if (EMSCRIPTEN) set(CMAKE_EXECUTABLE_SUFFIX ".html") - set(link_flags ${link-flags} -sNO_FILESYSTEM=1 -sASSERTIONS=0 -sMALLOC=emmalloc -sINITIAL_MEMORY=33554432 --closure=1) + set(link_flags ${link_flags} -sNO_FILESYSTEM=1 -sASSERTIONS=0 -sMALLOC=emmalloc -sINITIAL_MEMORY=33554432 --closure=1) + if (SOKOL_BACKEND STREQUAL SOKOL_WGPU) + set(link_flags ${link_flags} -sUSE_WEBGPU=1) + else() + set(link_flags ${link_flags} -sUSE_WEBGL2=1) + endif() elseif (OSX_IOS) set(exe_type MACOSX_BUNDLE) if (USE_ARC) diff --git a/tests/CMakePresets.json b/tests/CMakePresets.json index df7a56599..fe0b89640 100644 --- a/tests/CMakePresets.json +++ b/tests/CMakePresets.json @@ -390,6 +390,26 @@ "CMAKE_BUILD_TYPE": "Release" } }, + { + "name": "emsc_wgpu_debug", + "generator": "Ninja", + "binaryDir": "build/emsc_wgpu_debug", + "toolchainFile": "build/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake", + "cacheVariables": { + "SOKOL_BACKEND": "SOKOL_WGPU", + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "emsc_wgpu_release", + "generator": "Ninja", + "binaryDir": "build/emsc_wgpu_release", + "toolchainFile": "build/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake", + "cacheVariables": { + "SOKOL_BACKEND": "SOKOL_WGPU", + "CMAKE_BUILD_TYPE": "Release" + } + }, { "name": "android_debug", "generator": "Ninja", @@ -644,6 +664,14 @@ "name": "emsc_webgl2_release", "configurePreset": "emsc_webgl2_release" }, + { + "name": "emsc_wgpu_debug", + "configurePreset": "emsc_wgpu_debug" + }, + { + "name": "emsc_wgpu_release", + "configurePreset": "emsc_wgpu_release" + }, { "name": "android_debug", "configurePreset": "android_debug" diff --git a/tests/test_emscripten.sh b/tests/test_emscripten.sh index 74f0ad1ba..aff4b08ed 100755 --- a/tests/test_emscripten.sh +++ b/tests/test_emscripten.sh @@ -4,3 +4,5 @@ source test_common.sh setup_emsdk build emsc_webgl2_debug emsc_webgl2_debug build emsc_webgl2_release emsc_webgl2_release +build emsc_wgpu_debug emsc_wgpu_debug +build emsc_wgpu_release emsc_wgpu_release From e81a05e2cbc73d96c62610837547e13781616f45 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Tue, 3 Oct 2023 15:25:06 +0200 Subject: [PATCH 79/95] sokol_app.h: fix comment typo --- sokol_app.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sokol_app.h b/sokol_app.h index 32b41daa2..ed7431dfd 100644 --- a/sokol_app.h +++ b/sokol_app.h @@ -1493,7 +1493,7 @@ typedef struct sapp_icon_desc { Used in sapp_desc to provide custom memory-alloc and -free functions to sokol_app.h. If memory management should be overridden, both the - alloc_fb and free_fn function must be provided (e.g. it's not valid to + alloc_fn and free_fn function must be provided (e.g. it's not valid to override one function but not the other). */ typedef struct sapp_allocator { From 88d03f50ebef965877dd483dad044de6f60ff962 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Wed, 4 Oct 2023 19:21:30 +0200 Subject: [PATCH 80/95] sokol_gfx.h gl: enable GL_TEXTURE_CUBE_MAP_SEAMLESS (see #910) --- sokol_gfx.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sokol_gfx.h b/sokol_gfx.h index 11035bad0..06ef6e735 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4103,6 +4103,7 @@ inline int sg_append_buffer(sg_buffer buf_id, const sg_range& data) { return sg_ #define GL_TEXTURE_COMPARE_MODE 0x884C #define GL_TEXTURE_COMPARE_FUNC 0x884D #define GL_COMPARE_REF_TO_TEXTURE 0x884E + #define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F #endif #ifndef GL_UNSIGNED_INT_2_10_10_10_REV @@ -7366,6 +7367,10 @@ _SOKOL_PRIVATE sg_resource_state _sg_gl_create_context(_sg_context_t* ctx) { _SG_GL_CHECK_ERROR(); // incoming texture data is generally expected to be packed tightly glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + #if defined(SOKOL_GLCORE33) + // enable seamless cubemap sampling (only desktop GL) + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + #endif return SG_RESOURCESTATE_VALID; } From ca02b4aeb4cb8630a49b730c86f16a7a8729678e Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 5 Oct 2023 19:58:03 +0200 Subject: [PATCH 81/95] sokol_gfx.h metal, wgpu: unify scissor rect clipping, wgpu: add viewport clipping (even if this is wrong) --- sokol_gfx.h | 74 ++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 06ef6e735..00ac30480 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -5387,6 +5387,23 @@ _SOKOL_PRIVATE uint32_t _sg_align_u32(uint32_t val, uint32_t align) { return (val + (align - 1)) & ~(align - 1); } +typedef struct { int x, y, w, h; } _sg_recti_t; + +_SOKOL_PRIVATE _sg_recti_t _sg_clipi(int x, int y, int w, int h, int clip_width, int clip_height) { + x = _sg_min(_sg_max(0, x), clip_width-1); + y = _sg_min(_sg_max(0, y), clip_height-1); + if ((x + w) > clip_width) { + w = clip_width - x; + } + if ((y + h) > clip_height) { + h = clip_height - y; + } + w = _sg_max(w, 1); + h = _sg_max(h, 1); + const _sg_recti_t res = { x, y, w, h }; + return res; +} + _SOKOL_PRIVATE int _sg_vertexformat_bytesize(sg_vertex_format fmt) { switch (fmt) { case SG_VERTEXFORMAT_FLOAT: return 4; @@ -12102,22 +12119,12 @@ _SOKOL_PRIVATE void _sg_mtl_apply_scissor_rect(int x, int y, int w, int h, bool } SOKOL_ASSERT(nil != _sg.mtl.cmd_encoder); // clip against framebuffer rect - x = _sg_min(_sg_max(0, x), _sg.mtl.cur_width-1); - y = _sg_min(_sg_max(0, y), _sg.mtl.cur_height-1); - if ((x + w) > _sg.mtl.cur_width) { - w = _sg.mtl.cur_width - x; - } - if ((y + h) > _sg.mtl.cur_height) { - h = _sg.mtl.cur_height - y; - } - w = _sg_max(w, 1); - h = _sg_max(h, 1); - + const _sg_recti_t clip = _sg_clipi(x, y, w, h, _sg.mtl.cur_width, _sg.mtl.cur_height); MTLScissorRect r; - r.x = (NSUInteger)x; - r.y = (NSUInteger) (origin_top_left ? y : (_sg.mtl.cur_height - (y + h))); - r.width = (NSUInteger)w; - r.height = (NSUInteger)h; + r.x = (NSUInteger)clip.x; + r.y = (NSUInteger) (origin_top_left ? clip.y : (_sg.mtl.cur_height - (clip.y + clip.h))); + r.width = (NSUInteger)clip.w; + r.height = (NSUInteger)clip.h; [_sg.mtl.cmd_encoder setScissorRect:r]; } @@ -14016,35 +14023,26 @@ _SOKOL_PRIVATE void _sg_wgpu_commit(void) { _SOKOL_PRIVATE void _sg_wgpu_apply_viewport(int x, int y, int w, int h, bool origin_top_left) { SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); - float xf = (float) x; - float yf = (float) (origin_top_left ? y : (_sg.wgpu.cur_height - (y + h))); - float wf = (float) w; - float hf = (float) h; + // FIXME FIXME FIXME: CLIPPING THE VIEWPORT HERE IS WRONG!!! + // (but currently required because WebGPU insists that the viewport rectangle must be + // fully contained inside the framebuffer, but this doesn't make any sense, and also + // isn't required by the backend APIs) + const _sg_recti_t clip = _sg_clipi(x, y, w, h, _sg.wgpu.cur_width, _sg.wgpu.cur_height); + float xf = (float) clip.x; + float yf = (float) (origin_top_left ? clip.y : (_sg.wgpu.cur_height - (clip.y + clip.h))); + float wf = (float) clip.w; + float hf = (float) clip.h; wgpuRenderPassEncoderSetViewport(_sg.wgpu.pass_enc, xf, yf, wf, hf, 0.0f, 1.0f); } _SOKOL_PRIVATE void _sg_wgpu_apply_scissor_rect(int x, int y, int w, int h, bool origin_top_left) { SOKOL_ASSERT(_sg.wgpu.in_pass); SOKOL_ASSERT(_sg.wgpu.pass_enc); - SOKOL_ASSERT(_sg.wgpu.in_pass); - SOKOL_ASSERT(_sg.wgpu.pass_enc); - - // clip against framebuffer rect - x = _sg_min(_sg_max(0, x), _sg.wgpu.cur_width-1); - y = _sg_min(_sg_max(0, y), _sg.wgpu.cur_height-1); - if ((x + w) > _sg.wgpu.cur_width) { - w = _sg.wgpu.cur_width - x; - } - if ((y + h) > _sg.wgpu.cur_height) { - h = _sg.wgpu.cur_height - y; - } - w = _sg_max(w, 1); - h = _sg_max(h, 1); - - uint32_t sx = (uint32_t) x; - uint32_t sy = (uint32_t) (origin_top_left ? y : (_sg.wgpu.cur_height - (y + h))); - uint32_t sw = (uint32_t) w; - uint32_t sh = (uint32_t) h; + const _sg_recti_t clip = _sg_clipi(x, y, w, h, _sg.wgpu.cur_width, _sg.wgpu.cur_height); + uint32_t sx = (uint32_t) clip.x; + uint32_t sy = (uint32_t) (origin_top_left ? clip.y : (_sg.wgpu.cur_height - (clip.y + clip.h))); + uint32_t sw = (uint32_t) clip.w; + uint32_t sh = (uint32_t) clip.h; wgpuRenderPassEncoderSetScissorRect(_sg.wgpu.pass_enc, sx, sy, sw, sh); } From dff70598b1eba16f53cfb5de60ea89cbea6a4d1b Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 8 Oct 2023 16:36:53 +0200 Subject: [PATCH 82/95] sokol_gfx.h wgpu: fix 3d texture view creation, use aspect DepthOnly for depth-stencil textures --- sokol_gfx.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 00ac30480..75148c9fe 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -13506,10 +13506,13 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s if (img->cmn.type == SG_IMAGETYPE_CUBE) { wgpu_texview_desc.arrayLayerCount = 6; } else { - wgpu_texview_desc.arrayLayerCount = (uint32_t)img->cmn.num_slices; + wgpu_texview_desc.arrayLayerCount = 1; + } + if (_sg_is_depth_or_depth_stencil_format(img->cmn.pixel_format)) { + wgpu_texview_desc.aspect = WGPUTextureAspect_DepthOnly; + } else { + wgpu_texview_desc.aspect = WGPUTextureAspect_All; } - // FIXME: should aspect be DepthOnly for all depth texture formats? - wgpu_texview_desc.aspect = WGPUTextureAspect_All; img->wgpu.view = wgpuTextureCreateView(img->wgpu.tex, &wgpu_texview_desc); if (0 == img->wgpu.view) { _SG_ERROR(WGPU_CREATE_TEXTURE_VIEW_FAILED); From 61675b5c621563619c19ca99dbf42d7fcf5d2165 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 8 Oct 2023 16:48:08 +0200 Subject: [PATCH 83/95] sokol_gfx.h wgpu: fix ETC2 texture compression support --- sokol_gfx.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 75148c9fe..e2866b671 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12606,6 +12606,11 @@ _SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) { case SG_PIXELFORMAT_BC6H_RGBF: return WGPUTextureFormat_BC6HRGBFloat; case SG_PIXELFORMAT_BC6H_RGBUF: return WGPUTextureFormat_BC6HRGBUfloat; case SG_PIXELFORMAT_BC7_RGBA: return WGPUTextureFormat_BC7RGBAUnorm; + case SG_PIXELFORMAT_ETC2_RGB8: return WGPUTextureFormat_ETC2RGB8Unorm; + case SG_PIXELFORMAT_ETC2_RGB8A1: return WGPUTextureFormat_ETC2RGB8A1Unorm; + case SG_PIXELFORMAT_ETC2_RGBA8: return WGPUTextureFormat_ETC2RGBA8Unorm; + case SG_PIXELFORMAT_ETC2_RG11: return WGPUTextureFormat_EACR11Unorm; + case SG_PIXELFORMAT_ETC2_RG11SN: return WGPUTextureFormat_EACR11Snorm; // NOT SUPPORTED case SG_PIXELFORMAT_R16: @@ -12620,11 +12625,6 @@ _SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) { case SG_PIXELFORMAT_PVRTC_RGB_4BPP: case SG_PIXELFORMAT_PVRTC_RGBA_2BPP: case SG_PIXELFORMAT_PVRTC_RGBA_4BPP: - case SG_PIXELFORMAT_ETC2_RGB8: - case SG_PIXELFORMAT_ETC2_RGB8A1: - case SG_PIXELFORMAT_ETC2_RGBA8: - case SG_PIXELFORMAT_ETC2_RG11: - case SG_PIXELFORMAT_ETC2_RG11SN: default: SOKOL_UNREACHABLE; return WGPUTextureFormat_Force32; From be548e5a0d11a62cf0e9d2ec2d860f89d819cebb Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sun, 8 Oct 2023 18:12:50 +0200 Subject: [PATCH 84/95] sokol_gfx.h wgpu: fix array texture creation --- sokol_gfx.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sokol_gfx.h b/sokol_gfx.h index e2866b671..356358435 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -13505,6 +13505,8 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_image(_sg_image_t* img, const s wgpu_texview_desc.mipLevelCount = (uint32_t)img->cmn.num_mipmaps; if (img->cmn.type == SG_IMAGETYPE_CUBE) { wgpu_texview_desc.arrayLayerCount = 6; + } else if (img->cmn.type == SG_IMAGETYPE_ARRAY) { + wgpu_texview_desc.arrayLayerCount = (uint32_t)img->cmn.num_slices; } else { wgpu_texview_desc.arrayLayerCount = 1; } From 06ea82c65c51f26c0ff8697146555e07d7b41013 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 9 Oct 2023 14:37:58 +0200 Subject: [PATCH 85/95] sokol_gfx.h wgpu: cleanup comments and wgpu bindings cache code --- sokol_gfx.h | 240 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 162 insertions(+), 78 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 356358435..22ba72742 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -68,7 +68,7 @@ sokol_gfx DOES NOT: =================== - - create a window or the 3D-API context/device, you must do this + - create a window, swapchain or the 3D-API context/device, you must do this before sokol_gfx is initialized, and pass any required information (like 3D device pointers) to the sokol_gfx initialization call @@ -404,7 +404,7 @@ - https://floooh.github.io/sokol-html5/mrt-sapp.html - https://floooh.github.io/sokol-html5/mrt-pixelformats-sapp.html - A render pass wraps rendering commands into a common set of render target images + A render pass groups rendering commands into a set of render target images (called 'pass attachments'). Render target images can be used in subsequent passes as textures (it is invalid to use the same image both as render target and as texture in the same pass). @@ -1259,7 +1259,7 @@ extern "C" { sg_buffer: vertex- and index-buffers sg_image: images used as textures and render targets sg_sampler sampler object describing how a texture is sampled in a shader - sg_shader: vertex- and fragment-shaders, uniform blocks + sg_shader: vertex- and fragment-shaders and shader interface information sg_pipeline: associated shader and vertex-layouts, and render states sg_pass: a bundle of render targets and actions on them sg_context: a 'context handle' for switching between 3D-API contexts @@ -2974,13 +2974,13 @@ typedef struct sg_frame_stats_wgpu_uniforms { typedef struct sg_frame_stats_wgpu_bindings { uint32_t num_set_vertex_buffer; - uint32_t num_skip_set_vertex_buffer; + uint32_t num_skip_redundant_vertex_buffer; uint32_t num_set_index_buffer; - uint32_t num_skip_set_index_buffer; + uint32_t num_skip_redundant_index_buffer; uint32_t num_create_bindgroup; uint32_t num_discard_bindgroup; uint32_t num_set_bindgroup; - uint32_t num_set_empty_bindgroup; + uint32_t num_skip_redundant_bindgroup; uint32_t num_bindgroup_cache_hits; uint32_t num_bindgroup_cache_misses; uint32_t num_bindgroup_cache_collisions; @@ -3313,6 +3313,9 @@ typedef enum sg_log_item { .uniform_buffer_size 4 MB (4*1024*1024) .max_commit_listeners 1024 .disable_validation false + .mtl_force_managed_storage_mode false + .wgpu_disable_bindgroups_cache false + .wgpu_bindgroups_cache_size 1024 .allocator.alloc_fn 0 (in this case, malloc() will be called) .allocator.free_fn 0 (in this case, free() will be called) @@ -3333,6 +3336,10 @@ typedef enum sg_log_item { must hold a strong reference to the Objective-C object for the duration of the sokol_gfx call! + .mtl_force_managed_storage_mode + when enabled, Metal buffers and texture resources are created in managed storage + mode, otherwise sokol-gfx will decide whether to create buffers and + textures in managed or shared storage mode (this is mainly a debugging option) .context.metal.device a pointer to the MTLDevice object .context.metal.renderpass_descriptor_cb @@ -3372,6 +3379,19 @@ typedef enum sg_log_item { callback functions WebGPU specific: + .wgpu_disable_bindgroups_cache + When this is true, the WebGPU backend will create and immediately + release a BindGroup object in the sg_apply_bindings() call, only + use this for debugging purposes. + .wgpu_bindgroups_cache_size + The size of the bindgroups cache for re-using BindGroup objects + between sg_apply_bindings() calls. The smaller the cache size, + the more likely are cache slot collisions which will cause + a BindGroups object to be destroyed and a new one created. + Use the information returned by sg_query_stats() to check + if this is a frequent occurence, and increase the cache size as + needed (the default is 1024). + NOTE: wgpu_bindgroups_cache_size must be a power-of-2 number! .context.wgpu.device a WGPUDevice handle .context.wgpu.render_format @@ -3507,7 +3527,7 @@ typedef struct sg_desc { int max_commit_listeners; bool disable_validation; // disable validation layer even in debug mode, useful for tests bool mtl_force_managed_storage_mode; // for debugging: use Metal managed storage mode for resources even with UMA - bool wgpu_disable_bindgroups_cache; // set to false to disable the WebGPU backend BindGroup cache + bool wgpu_disable_bindgroups_cache; // set to true to disable the WebGPU backend BindGroup cache int wgpu_bindgroups_cache_size; // number of slots in the WebGPU bindgroup cache (must be 2^N) sg_allocator allocator; sg_logger logger; // optional log function override @@ -4207,7 +4227,7 @@ typedef struct { sg_resource_state state; } _sg_slot_t; -// a common resource pool housekeeping struct +// resource pool housekeeping struct typedef struct { int size; int queue_top; @@ -5147,6 +5167,7 @@ typedef struct { sg_buffer buffer; int offset; } ib; + _sg_wgpu_bindgroup_handle_t bg; } _sg_wgpu_bindings_cache_t; // the WGPU backend state @@ -12526,8 +12547,8 @@ _SOKOL_PRIVATE WGPUVertexFormat _sg_wgpu_vertexformat(sg_vertex_format f) { case SG_VERTEXFORMAT_USHORT4N: return WGPUVertexFormat_Unorm16x4; case SG_VERTEXFORMAT_HALF2: return WGPUVertexFormat_Float16x2; case SG_VERTEXFORMAT_HALF4: return WGPUVertexFormat_Float16x4; - // FIXME! UINT10_N2 - case SG_VERTEXFORMAT_UINT10_N2: + // FIXME! UINT10_N2 (see https://github.com/gpuweb/gpuweb/issues/4275) + case SG_VERTEXFORMAT_UINT10_N2: return WGPUVertexFormat_Undefined; default: SOKOL_UNREACHABLE; return WGPUVertexFormat_Force32; @@ -12541,7 +12562,9 @@ _SOKOL_PRIVATE WGPUPrimitiveTopology _sg_wgpu_topology(sg_primitive_type t) { case SG_PRIMITIVETYPE_LINE_STRIP: return WGPUPrimitiveTopology_LineStrip; case SG_PRIMITIVETYPE_TRIANGLES: return WGPUPrimitiveTopology_TriangleList; case SG_PRIMITIVETYPE_TRIANGLE_STRIP: return WGPUPrimitiveTopology_TriangleStrip; - default: SOKOL_UNREACHABLE; return WGPUPrimitiveTopology_Force32; + default: + SOKOL_UNREACHABLE; + return WGPUPrimitiveTopology_Force32; } } @@ -12554,7 +12577,9 @@ _SOKOL_PRIVATE WGPUCullMode _sg_wgpu_cullmode(sg_cull_mode cm) { case SG_CULLMODE_NONE: return WGPUCullMode_None; case SG_CULLMODE_FRONT: return WGPUCullMode_Front; case SG_CULLMODE_BACK: return WGPUCullMode_Back; - default: SOKOL_UNREACHABLE; return WGPUCullMode_Force32; + default: + SOKOL_UNREACHABLE; + return WGPUCullMode_Force32; } } @@ -12625,6 +12650,8 @@ _SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) { case SG_PIXELFORMAT_PVRTC_RGB_4BPP: case SG_PIXELFORMAT_PVRTC_RGBA_2BPP: case SG_PIXELFORMAT_PVRTC_RGBA_4BPP: + return WGPUTextureFormat_Undefined; + default: SOKOL_UNREACHABLE; return WGPUTextureFormat_Force32; @@ -12641,7 +12668,9 @@ _SOKOL_PRIVATE WGPUCompareFunction _sg_wgpu_comparefunc(sg_compare_func f) { case SG_COMPAREFUNC_NOT_EQUAL: return WGPUCompareFunction_NotEqual; case SG_COMPAREFUNC_GREATER_EQUAL: return WGPUCompareFunction_GreaterEqual; case SG_COMPAREFUNC_ALWAYS: return WGPUCompareFunction_Always; - default: SOKOL_UNREACHABLE; return WGPUCompareFunction_Force32; + default: + SOKOL_UNREACHABLE; + return WGPUCompareFunction_Force32; } } @@ -12655,7 +12684,9 @@ _SOKOL_PRIVATE WGPUStencilOperation _sg_wgpu_stencilop(sg_stencil_op op) { case SG_STENCILOP_INVERT: return WGPUStencilOperation_Invert; case SG_STENCILOP_INCR_WRAP: return WGPUStencilOperation_IncrementWrap; case SG_STENCILOP_DECR_WRAP: return WGPUStencilOperation_DecrementWrap; - default: SOKOL_UNREACHABLE; return WGPUStencilOperation_Force32; + default: + SOKOL_UNREACHABLE; + return WGPUStencilOperation_Force32; } } @@ -12664,7 +12695,9 @@ _SOKOL_PRIVATE WGPUBlendOperation _sg_wgpu_blendop(sg_blend_op op) { case SG_BLENDOP_ADD: return WGPUBlendOperation_Add; case SG_BLENDOP_SUBTRACT: return WGPUBlendOperation_Subtract; case SG_BLENDOP_REVERSE_SUBTRACT: return WGPUBlendOperation_ReverseSubtract; - default: SOKOL_UNREACHABLE; return WGPUBlendOperation_Force32; + default: + SOKOL_UNREACHABLE; + return WGPUBlendOperation_Force32; } } @@ -12687,7 +12720,8 @@ _SOKOL_PRIVATE WGPUBlendFactor _sg_wgpu_blendfactor(sg_blend_factor f) { case SG_BLENDFACTOR_BLEND_ALPHA: return WGPUBlendFactor_Constant; case SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA: return WGPUBlendFactor_OneMinusConstant; default: - SOKOL_UNREACHABLE; return WGPUBlendFactor_Force32; + SOKOL_UNREACHABLE; + return WGPUBlendFactor_Force32; } } @@ -12751,6 +12785,7 @@ _SOKOL_PRIVATE void _sg_wgpu_init_caps(void) { // FIXME: in webgpu.h, wgpuDeviceGetLimits() has a boolean return value, but // the JS shim doesn't actually return anything + // (see: https://github.com/emscripten-core/emscripten/issues/20278) wgpuDeviceGetLimits(_sg.wgpu.dev, &_sg.wgpu.limits); const WGPULimits* l = &_sg.wgpu.limits.limits; @@ -13194,30 +13229,81 @@ _SOKOL_PRIVATE uint32_t _sg_wgpu_bindgroups_cache_get(uint64_t hash) { return _sg.wgpu.bindgroups_cache.items[index].id; } -_SOKOL_PRIVATE void _sg_wgpu_bindcache_clear(void) { +_SOKOL_PRIVATE void _sg_wgpu_bindings_cache_clear(void) { memset(&_sg.wgpu.bindings_cache, 0, sizeof(_sg.wgpu.bindings_cache)); } -_SOKOL_PRIVATE bool _sg_wgpu_bindcache_vb_dirty(int index, const _sg_buffer_t* vb, int offset) { - SOKOL_ASSERT(vb && (index >= 0) && (index < SG_MAX_VERTEX_BUFFERS)); - return (vb->slot.id != _sg.wgpu.bindings_cache.vbs[index].buffer.id) || (offset != _sg.wgpu.bindings_cache.vbs[index].offset); +_SOKOL_PRIVATE bool _sg_wgpu_bindings_cache_vb_dirty(int index, const _sg_buffer_t* vb, int offset) { + SOKOL_ASSERT((index >= 0) && (index < SG_MAX_VERTEX_BUFFERS)); + if (vb) { + return (_sg.wgpu.bindings_cache.vbs[index].buffer.id != vb->slot.id) + || (_sg.wgpu.bindings_cache.vbs[index].offset != offset); + } else { + return _sg.wgpu.bindings_cache.vbs[index].buffer.id != SG_INVALID_ID; + } } -_SOKOL_PRIVATE void _sg_wgpu_bindcache_vb_update(int index, const _sg_buffer_t* vb, int offset) { - SOKOL_ASSERT(vb && (index >= 0) && (index < SG_MAX_VERTEX_BUFFERS)); - _sg.wgpu.bindings_cache.vbs[index].buffer.id = vb->slot.id; - _sg.wgpu.bindings_cache.vbs[index].offset = offset; +_SOKOL_PRIVATE void _sg_wgpu_bindings_cache_vb_update(int index, const _sg_buffer_t* vb, int offset) { + SOKOL_ASSERT((index >= 0) && (index < SG_MAX_VERTEX_BUFFERS)); + if (vb) { + _sg.wgpu.bindings_cache.vbs[index].buffer.id = vb->slot.id; + _sg.wgpu.bindings_cache.vbs[index].offset = offset; + } else { + _sg.wgpu.bindings_cache.vbs[index].buffer.id = SG_INVALID_ID; + _sg.wgpu.bindings_cache.vbs[index].offset = 0; + } } -_SOKOL_PRIVATE bool _sg_wgpu_bindcache_ib_dirty(const _sg_buffer_t* ib, int ib_offset) { - SOKOL_ASSERT(ib); - return (ib->slot.id != _sg.wgpu.bindings_cache.ib.buffer.id) || (ib_offset != _sg.wgpu.bindings_cache.ib.offset); +_SOKOL_PRIVATE bool _sg_wgpu_bindings_cache_ib_dirty(const _sg_buffer_t* ib, int offset) { + if (ib) { + return (_sg.wgpu.bindings_cache.ib.buffer.id != ib->slot.id) + || (_sg.wgpu.bindings_cache.ib.offset != offset); + } else { + return _sg.wgpu.bindings_cache.ib.buffer.id != SG_INVALID_ID; + } } -_SOKOL_PRIVATE void _sg_wgpu_bindcache_ib_update(const _sg_buffer_t* ib, int ib_offset) { - SOKOL_ASSERT(ib); - _sg.wgpu.bindings_cache.ib.buffer.id = ib->slot.id; - _sg.wgpu.bindings_cache.ib.offset = ib_offset; +_SOKOL_PRIVATE void _sg_wgpu_bindings_cache_ib_update(const _sg_buffer_t* ib, int offset) { + if (ib) { + _sg.wgpu.bindings_cache.ib.buffer.id = ib->slot.id; + _sg.wgpu.bindings_cache.ib.offset = offset; + } else { + _sg.wgpu.bindings_cache.ib.buffer.id = SG_INVALID_ID; + _sg.wgpu.bindings_cache.ib.offset = 0; + } +} + +_SOKOL_PRIVATE bool _sg_wgpu_bindings_cache_bg_dirty(const _sg_wgpu_bindgroup_t* bg) { + if (bg) { + return _sg.wgpu.bindings_cache.bg.id != bg->slot.id; + } else { + return _sg.wgpu.bindings_cache.bg.id != SG_INVALID_ID; + } +} + +_SOKOL_PRIVATE void _sg_wgpu_bindings_cache_bg_update(const _sg_wgpu_bindgroup_t* bg) { + if (bg) { + _sg.wgpu.bindings_cache.bg.id = bg->slot.id; + } else { + _sg.wgpu.bindings_cache.bg.id = SG_INVALID_ID; + } +} + +_SOKOL_PRIVATE void _sg_wgpu_set_image_sampler_bindgroup(_sg_wgpu_bindgroup_t* bg) { + if (_sg_wgpu_bindings_cache_bg_dirty(bg)) { + _sg_wgpu_bindings_cache_bg_update(bg); + _sg_stats_add(wgpu.bindings.num_set_bindgroup, 1); + if (bg) { + SOKOL_ASSERT(bg->slot.state == SG_RESOURCESTATE_VALID); + SOKOL_ASSERT(bg->bindgroup); + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0); + } else { + // a nullptr bindgroup means setting the empty bindgroup + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); + } + } else { + _sg_stats_add(wgpu.bindings.num_skip_redundant_bindgroup, 1); + } } _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { @@ -13249,9 +13335,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { _sg_wgpu_bindgroups_cache_set(key.hash, bg->slot.id); } if (bg && bg->slot.state == SG_RESOURCESTATE_VALID) { - SOKOL_ASSERT(bg->bindgroup); - _sg_stats_add(wgpu.bindings.num_set_bindgroup, 1); - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0); + _sg_wgpu_set_image_sampler_bindgroup(bg); } else { return false; } @@ -13260,9 +13344,7 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { _sg_wgpu_bindgroup_t* bg = _sg_wgpu_create_bindgroup(bnd); if (bg) { if (bg->slot.state == SG_RESOURCESTATE_VALID) { - SOKOL_ASSERT(bg->bindgroup); - _sg_stats_add(wgpu.bindings.num_set_bindgroup, 1); - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, bg->bindgroup, 0, 0); + _sg_wgpu_set_image_sampler_bindgroup(bg); } _sg_wgpu_discard_bindgroup(bg); } else { @@ -13270,9 +13352,44 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindgroup(_sg_bindings_t* bnd) { } } } else { - _sg_stats_add(wgpu.bindings.num_set_empty_bindgroup, 1); - wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); + _sg_wgpu_set_image_sampler_bindgroup(0); + } + return true; +} +_SOKOL_PRIVATE bool _sg_wgpu_apply_index_buffer(_sg_bindings_t* bnd) { + if (_sg_wgpu_bindings_cache_ib_dirty(bnd->ib, bnd->ib_offset)) { + _sg_wgpu_bindings_cache_ib_update(bnd->ib, bnd->ib_offset); + if (bnd->ib) { + const WGPUIndexFormat format = _sg_wgpu_indexformat(bnd->pip->cmn.index_type); + const uint64_t buf_size = (uint64_t)bnd->ib->cmn.size; + const uint64_t offset = (uint64_t)bnd->ib_offset; + SOKOL_ASSERT(buf_size > offset); + const uint64_t max_bytes = buf_size - offset; + wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, bnd->ib->wgpu.buf, format, offset, max_bytes); + _sg_stats_add(wgpu.bindings.num_set_index_buffer, 1); + } + // FIXME: else-path should actually set a null index buffer (this was just recently implemented in WebGPU) + } else { + _sg_stats_add(wgpu.bindings.num_skip_redundant_index_buffer, 1); + } + return true; +} + +_SOKOL_PRIVATE bool _sg_wgpu_apply_vertex_buffers(_sg_bindings_t* bnd) { + for (int slot = 0; slot < bnd->num_vbs; slot++) { + if (_sg_wgpu_bindings_cache_vb_dirty(slot, bnd->vbs[slot], bnd->vb_offsets[slot])) { + _sg_wgpu_bindings_cache_vb_update(slot, bnd->vbs[slot], bnd->vb_offsets[slot]); + const uint64_t buf_size = (uint64_t)bnd->vbs[slot]->cmn.size; + const uint64_t offset = (uint64_t)bnd->vb_offsets[slot]; + SOKOL_ASSERT(buf_size > offset); + const uint64_t max_bytes = buf_size - offset; + wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, (uint32_t)slot, bnd->vbs[slot]->wgpu.buf, offset, max_bytes); + _sg_stats_add(wgpu.bindings.num_set_vertex_buffer, 1); + } else { + _sg_stats_add(wgpu.bindings.num_skip_redundant_vertex_buffer, 1); + } } + // FIXME: remaining vb slots should actually set a null vertex buffer (this was just recently implemented in WebGPU) return true; } @@ -13296,11 +13413,11 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg.wgpu.queue = wgpuDeviceGetQueue(_sg.wgpu.dev); SOKOL_ASSERT(_sg.wgpu.queue); - _sg_wgpu_bindcache_clear(); _sg_wgpu_init_caps(); _sg_wgpu_uniform_buffer_init(desc); _sg_wgpu_bindgroups_pool_init(desc); _sg_wgpu_bindgroups_cache_init(desc); + _sg_wgpu_bindings_cache_clear(); // create an empty bind group for shader stages without bound images WGPUBindGroupLayoutDescriptor bgl_desc; @@ -13335,7 +13452,7 @@ _SOKOL_PRIVATE void _sg_wgpu_discard_backend(void) { } _SOKOL_PRIVATE void _sg_wgpu_reset_state_cache(void) { - // FIXME + _sg_wgpu_bindings_cache_clear(); } _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_context(_sg_context_t* ctx) { @@ -13956,7 +14073,7 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* _sg.wgpu.cur_height = h; _sg.wgpu.cur_pipeline = 0; _sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID; - _sg_wgpu_bindcache_clear(); + _sg_wgpu_bindings_cache_clear(); WGPURenderPassDescriptor wgpu_pass_desc; WGPURenderPassColorAttachment wgpu_color_att[SG_MAX_COLOR_ATTACHMENTS]; @@ -14070,42 +14187,9 @@ _SOKOL_PRIVATE bool _sg_wgpu_apply_bindings(_sg_bindings_t* bnd) { SOKOL_ASSERT(bnd); SOKOL_ASSERT(bnd->pip->shader && (bnd->pip->cmn.shader_id.id == bnd->pip->shader->slot.id)); bool retval = true; - - // index buffer - if (bnd->ib) { - if (_sg_wgpu_bindcache_ib_dirty(bnd->ib, bnd->ib_offset)) { - _sg_wgpu_bindcache_ib_update(bnd->ib, bnd->ib_offset); - const WGPUIndexFormat format = _sg_wgpu_indexformat(bnd->pip->cmn.index_type); - const uint64_t buf_size = (uint64_t)bnd->ib->cmn.size; - const uint64_t offset = (uint64_t)bnd->ib_offset; - SOKOL_ASSERT(buf_size > offset); - const uint64_t max_bytes = buf_size - offset; - wgpuRenderPassEncoderSetIndexBuffer(_sg.wgpu.pass_enc, bnd->ib->wgpu.buf, format, offset, max_bytes); - _sg_stats_add(wgpu.bindings.num_set_index_buffer, 1); - } else { - _sg_stats_add(wgpu.bindings.num_skip_set_index_buffer, 1); - } - } - // FIXME: else-path should actually set a null index buffer (this was just recently implemented in WebGPU) - - // vertex buffers - for (int slot = 0; slot < bnd->num_vbs; slot++) { - if (_sg_wgpu_bindcache_vb_dirty(slot, bnd->vbs[slot], bnd->vb_offsets[slot])) { - _sg_wgpu_bindcache_vb_update(slot, bnd->vbs[slot], bnd->vb_offsets[slot]); - const uint64_t buf_size = (uint64_t)bnd->vbs[slot]->cmn.size; - const uint64_t offset = (uint64_t)bnd->vb_offsets[slot]; - SOKOL_ASSERT(buf_size > offset); - const uint64_t max_bytes = buf_size - offset; - wgpuRenderPassEncoderSetVertexBuffer(_sg.wgpu.pass_enc, (uint32_t)slot, bnd->vbs[slot]->wgpu.buf, offset, max_bytes); - _sg_stats_add(wgpu.bindings.num_set_vertex_buffer, 1); - } else { - _sg_stats_add(wgpu.bindings.num_skip_set_vertex_buffer, 1); - } - // FIXME: else-path should actually set a null vertex buffer (this was just recently implemented in WebGPU) - } - - _sg_wgpu_apply_bindgroup(bnd); - + retval &= _sg_wgpu_apply_index_buffer(bnd); + retval &= _sg_wgpu_apply_vertex_buffers(bnd); + retval &= _sg_wgpu_apply_bindgroup(bnd); return retval; } From d5e986c52b796f371f2a022e1601ee9774048e9c Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 9 Oct 2023 14:38:20 +0200 Subject: [PATCH 86/95] sokol_gfx_imgui.h: fixes for sokol_gfx.h stats member renames --- util/sokol_gfx_imgui.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/sokol_gfx_imgui.h b/util/sokol_gfx_imgui.h index ec9193847..53304bd69 100644 --- a/util/sokol_gfx_imgui.h +++ b/util/sokol_gfx_imgui.h @@ -4273,13 +4273,13 @@ _SOKOL_PRIVATE void _sg_imgui_draw_frame_stats_panel(sg_imgui_t* ctx) { _sg_imgui_frame_stats(wgpu.uniforms.num_set_bindgroup); _sg_imgui_frame_stats(wgpu.uniforms.size_write_buffer); _sg_imgui_frame_stats(wgpu.bindings.num_set_vertex_buffer); - _sg_imgui_frame_stats(wgpu.bindings.num_skip_set_vertex_buffer); + _sg_imgui_frame_stats(wgpu.bindings.num_skip_redundant_vertex_buffer); _sg_imgui_frame_stats(wgpu.bindings.num_set_index_buffer); - _sg_imgui_frame_stats(wgpu.bindings.num_skip_set_index_buffer); + _sg_imgui_frame_stats(wgpu.bindings.num_skip_redundant_index_buffer); _sg_imgui_frame_stats(wgpu.bindings.num_create_bindgroup); _sg_imgui_frame_stats(wgpu.bindings.num_discard_bindgroup); _sg_imgui_frame_stats(wgpu.bindings.num_set_bindgroup); - _sg_imgui_frame_stats(wgpu.bindings.num_set_empty_bindgroup); + _sg_imgui_frame_stats(wgpu.bindings.num_skip_redundant_bindgroup); _sg_imgui_frame_stats(wgpu.bindings.num_bindgroup_cache_hits); _sg_imgui_frame_stats(wgpu.bindings.num_bindgroup_cache_misses); _sg_imgui_frame_stats(wgpu.bindings.num_bindgroup_cache_collisions); From 4e0d7ce6b57f5a6debfac95021a3f35d00ab22d7 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 9 Oct 2023 14:43:45 +0200 Subject: [PATCH 87/95] sokol_gfx.h wgpu: fix wgpu sampler not being released when destroyed --- sokol_gfx.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 22ba72742..b7dbba619 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -13420,6 +13420,7 @@ _SOKOL_PRIVATE void _sg_wgpu_setup_backend(const sg_desc* desc) { _sg_wgpu_bindings_cache_clear(); // create an empty bind group for shader stages without bound images + // FIXME: once WebGPU supports setting null objects, this can be removed WGPUBindGroupLayoutDescriptor bgl_desc; _sg_clear(&bgl_desc, sizeof(bgl_desc)); WGPUBindGroupLayout empty_bgl = wgpuDeviceCreateBindGroupLayout(_sg.wgpu.dev, &bgl_desc); @@ -13689,7 +13690,7 @@ _SOKOL_PRIVATE sg_resource_state _sg_wgpu_create_sampler(_sg_sampler_t* smp, con _SOKOL_PRIVATE void _sg_wgpu_discard_sampler(_sg_sampler_t* smp) { SOKOL_ASSERT(smp); if (smp->wgpu.smp) { - wgpuSamplerReference(smp->wgpu.smp); + wgpuSamplerRelease(smp->wgpu.smp); smp->wgpu.smp = 0; } } From f2ca0cfa3127a14f1310dfaf69bbf3b1c2e70bb1 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 9 Oct 2023 15:53:37 +0200 Subject: [PATCH 88/95] sokol_gfx.h wgpu: fix empty image-sampler bindings behaviour --- sokol_gfx.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index b7dbba619..3a2e778a4 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -14074,7 +14074,6 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* _sg.wgpu.cur_height = h; _sg.wgpu.cur_pipeline = 0; _sg.wgpu.cur_pipeline_id.id = SG_INVALID_ID; - _sg_wgpu_bindings_cache_clear(); WGPURenderPassDescriptor wgpu_pass_desc; WGPURenderPassColorAttachment wgpu_color_att[SG_MAX_COLOR_ATTACHMENTS]; @@ -14108,6 +14107,11 @@ _SOKOL_PRIVATE void _sg_wgpu_begin_pass(_sg_pass_t* pass, const sg_pass_action* _sg.wgpu.pass_enc = wgpuCommandEncoderBeginRenderPass(_sg.wgpu.cmd_enc, &wgpu_pass_desc); SOKOL_ASSERT(_sg.wgpu.pass_enc); + // clear bindings cache and apply an empty image-sampler bindgroup + _sg_wgpu_bindings_cache_clear(); + wgpuRenderPassEncoderSetBindGroup(_sg.wgpu.pass_enc, _SG_WGPU_IMAGE_SAMPLER_BINDGROUP_INDEX, _sg.wgpu.empty_bind_group, 0, 0); + _sg_stats_add(wgpu.bindings.num_set_bindgroup, 1); + // initial uniform buffer binding (required even if no uniforms are set in the frame) _sg_wgpu_uniform_buffer_on_begin_pass(); } From 13787112361be66df4daeecb893a907894d498a7 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Mon, 16 Oct 2023 14:41:11 +0200 Subject: [PATCH 89/95] sokol_gfx.h wgpu: support SRGB8A8 and RGB9E5 pixel formats --- sokol_gfx.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 3a2e778a4..f08318b28 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -12603,7 +12603,8 @@ _SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) { case SG_PIXELFORMAT_RG16UI: return WGPUTextureFormat_RG16Uint; case SG_PIXELFORMAT_RG16SI: return WGPUTextureFormat_RG16Sint; case SG_PIXELFORMAT_RG16F: return WGPUTextureFormat_RG16Float; - case SG_PIXELFORMAT_RGBA8: return WGPUTextureFormat_RGBA8Unorm; + case SG_PIXELFORMAT_RGBA8: return WGPUTextureFormat_RGBA8UnormSrgb; + case SG_PIXELFORMAT_SRGB8A8: return WGPUTextureFormat_RGBA8Unorm; case SG_PIXELFORMAT_RGBA8SN: return WGPUTextureFormat_RGBA8Snorm; case SG_PIXELFORMAT_RGBA8UI: return WGPUTextureFormat_RGBA8Uint; case SG_PIXELFORMAT_RGBA8SI: return WGPUTextureFormat_RGBA8Sint; @@ -12636,6 +12637,7 @@ _SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) { case SG_PIXELFORMAT_ETC2_RGBA8: return WGPUTextureFormat_ETC2RGBA8Unorm; case SG_PIXELFORMAT_ETC2_RG11: return WGPUTextureFormat_EACR11Unorm; case SG_PIXELFORMAT_ETC2_RG11SN: return WGPUTextureFormat_EACR11Snorm; + case SG_PIXELFORMAT_RGB9E5: return WGPUTextureFormat_RGB9E5Ufloat; // NOT SUPPORTED case SG_PIXELFORMAT_R16: @@ -12644,8 +12646,6 @@ _SOKOL_PRIVATE WGPUTextureFormat _sg_wgpu_textureformat(sg_pixel_format p) { case SG_PIXELFORMAT_RG16SN: case SG_PIXELFORMAT_RGBA16: case SG_PIXELFORMAT_RGBA16SN: - case SG_PIXELFORMAT_SRGB8A8: - case SG_PIXELFORMAT_RGB9E5: case SG_PIXELFORMAT_PVRTC_RGB_2BPP: case SG_PIXELFORMAT_PVRTC_RGB_4BPP: case SG_PIXELFORMAT_PVRTC_RGBA_2BPP: From 9a4cd059770e31c2840c4e5376bd8d405fc1a713 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Thu, 19 Oct 2023 20:12:36 +0200 Subject: [PATCH 90/95] sokol_gfx.h wgpu: start adding WebGPU backend details to the documentation --- sokol_gfx.h | 94 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 13 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index f08318b28..a0c3d6be5 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -602,9 +602,9 @@ ================== sokol-gfx doesn't come with an integrated shader cross-compiler, instead backend-specific shader sources or binary blobs need to be provided when - creating a shader object, along with information about the shader interface - needed in the sokol-gfx validation layer and to properly bind shader resources - on the CPU-side to be consumable by the GPU-side. + creating a shader object, along with information about the shader resource + binding interface needed in the sokol-gfx validation layer and to properly + bind shader resources on the CPU-side to be consumable by the GPU-side. The easiest way to provide all this shader creation data is to use the sokol-shdc shader compiler tool to compile shaders from a common @@ -643,6 +643,7 @@ load 'd3dcompiler_47.dll' - for the Metal backends, shaders can be provided as source or binary blobs, the MSL version should be in 'metal-1.1' (other versions may work but are not tested) + - for the WebGPU backend, shader must be provided as WGSL source code - optionally the following shader-code related attributes can be provided: - an entry function name (only on D3D11 or Metal, but not OpenGL) - on D3D11 only, a compilation target (default is "vs_4_0" and "ps_4_0") @@ -651,6 +652,8 @@ vertex shader: - Metal: no information needed since vertex attributes are always bound by their attribute location defined in the shader via '[[attribute(N)]]' + - WebGPU: no information needed since vertex attributes are always + bound by their attribute location defined in the shader via `@location(N)` - GLSL: vertex attribute names can be optionally provided, in that case their location will be looked up by name, otherwise, the vertex attribute location can be defined with 'layout(location = N)', PLEASE NOTE that the name-lookup method @@ -671,23 +674,36 @@ and CROSS-BACKEND COMMON UNIFORM DATA LAYOUT below! - A description of each texture/image used in the shader: - - the expected image type (e.g. 2D, 3D, etc...) - - the 'image sample type' (e.g. float, depth, signed- or unsigned-int) + - the expected image type: + - SG_IMAGETYPE_2D + - SG_IMAGETYPE_CUBE + - SG_IMAGETYPE_3D + - SG_IMAGETYPE_ARRAY + - the expected 'image sample type': + - SG_IMAGESAMPLETYPE_FLOAT + - SG_IMAGESAMPLETYPE_DEPTH + - SG_IMAGESAMPLETYPE_SINT + - SG_IMAGESAMPLETYPE_UINT + - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT - a flag whether the texture is expected to be multisampled (currently it's not supported to fetch data from multisampled textures in shaders, but this is planned for a later time) - A description of each sampler used in the shader: - - just wether the sampler is a regular 'sampling sampler', - or a 'comparison sampler' (which is usually used for - shadow mapping) + - SG_SAMPLERTYPE_FILTERING, + - SG_SAMPLERTYPE_NONFILTERING, + - SG_SAMPLERTYPE_COMPARISON, - An array of 'image-sampler-pairs' used by the shader to sample textures, - for D3D11 and Metal this is only used for validation purposes to check - whether the texture and sampler are compatible with each other. For GLSL - an additional 'combined-image-sampler name' must be provided because - 'OpenGL style GLSL' cannot handle separate texture and sampler objects, - but still groups them into a tradtional GLSL 'sampler object'. + for D3D11, Metal and WebGPU this is used for validation purposes to check + whether the texture and sampler are compatible with each other (especially + WebGPU is very picky about combining the correct + texture-sample-type with the correct sampler-type). For GLSL an + additional 'combined-image-sampler name' must be provided because 'OpenGL + style GLSL' cannot handle separate texture and sampler objects, but still + groups them into a tradtional GLSL 'sampler object'. + + For example code of how to create backend-specific shader objects, please refer to the following samples: @@ -696,6 +712,47 @@ - for Metal: https://github.com/floooh/sokol-samples/tree/master/metal - for OpenGL: https://github.com/floooh/sokol-samples/tree/master/glfw - for GLES3: https://github.com/floooh/sokol-samples/tree/master/html5 + - for WebGPI: https://github.com/floooh/sokol-samples/tree/master/wgpu + + + ON SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT AND SG_SAMPLERTYPE_NONFILTERING + ======================================================================== + The WebGPU backend introduces the concept of 'unfilterable-float' textures, + which can only be combined with 'nonfiltering' samplers (this is a restriction + specific to WebGPU, but since the same sokol-gfx code should work across + all backend, the sokol-gfx validation layer also enforces this restriction + - the alternative would be undefined behaviour in some backend APIs on + some devices). + + The background is that some mobile devices (most notably iOS devices) can + not perform linear filtering when sampling textures with certain pixel + formats, most notable the 32F formats: + + - SG_PIXELFORMAT_R32F + - SG_PIXELFORMAT_RG32F + - SG_PIXELFORMAT_RGBA32F + + The information of whether a shader is going to be used with such an + unfilterable-float texture must already be provided in the sg_shader_desc + struct when creating the shader (see the above section "ON SHADER CREATION"). + + If you are using the sokol-shdc shader compiler, the information whether a + texture/sampler binding expects an 'unfilterable-float/nonfiltering' + texture/sampler combination cannot be inferred from the shader source + alone, you'll need to provide this hint via annotation-tags. For instance + here is an example from the ozz-skin-sapp.c sample shader which samples an + RGBA32F texture with skinning matrices in the vertex shader: + + ```glsl + @image_sample_type joint_tex unfilterable_float + uniform texture2D joint_tex; + @sampler_type smp nonfiltering + uniform sampler smp; + ``` + + This will result in SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT and + SG_SAMPLERTYPE_NONFILTERING being written to the code-generated + sg_shader_desc struct. UNIFORM DATA LAYOUT: @@ -1206,6 +1263,17 @@ result in a pipeline object in FAILED state. Same when trying to create a pass object with invalid image objects. + + + WEBGPU CAVEATS + ============== + For a general overview and design notes of the WebGPU backend see: + + https://floooh.github.io/2023/10/16/sokol-webgpu.html + + TODO! + + LICENSE ======= zlib/libpng license From ed51699cd17ad638ba82d9084727a5404acac7df Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 21 Oct 2023 16:26:05 +0200 Subject: [PATCH 91/95] sokol_gfx.h: add a WEBGPU CAVEATS documentation section --- sokol_gfx.h | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index a0c3d6be5..71787431d 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -1264,14 +1264,99 @@ a pass object with invalid image objects. - WEBGPU CAVEATS ============== For a general overview and design notes of the WebGPU backend see: https://floooh.github.io/2023/10/16/sokol-webgpu.html - TODO! + In general, don't expect an automatic speedup when switching from the WebGL2 + backend to the WebGPU backend. Some WebGPU functions currently actually + have a higher CPU overhead than similar WebGL2 functions, leading to the + paradoxical situation that WebGPU code is slower than similar WebGL2 + code. + + - when writing WGSL shader code by hand, a specific bind-slot convention + must be used: + + All uniform block structs must use `@group(0)`, with up to + 4 uniform blocks per shader stage. + - Vertex shader uniform block bindings must start at `@group(0) @binding(0)` + - Fragment shader uniform blocks bindings must start at `@group(0) @binding(4)` + + All textures and samplers must use `@group(1)` and start at specific + offsets depending on resource type and shader stage. + - Vertex shader textures must start at `@group(1) @binding(0)` + - Vertex shader samplers must start at `@group(1) @binding(16)` + - Fragment shader textures must start at `@group(1) @binding(32)` + - Fragment shader samplers must start at `@group(1) @binding(48)` + + Note that the actual number of allowed per-stage texture- and sampler-bindings + in sokol-gfx is currently lower than the above ranges (currently only up to + 12 textures and 8 samplers per shader stage are allowed). + + If you use sokol-shdc to generate WGSL shader code, you don't need to worry + about the above binding convention since sokol-shdc assigns bind slots + automatically. + + - The sokol-gfx WebGPU backend uses the sg_desc.uniform_buffer_size item + to allocate a single per-frame uniform buffer which must be big enough + to hold all data written by sg_apply_uniforms() during a single frame, + including a worst-case 256-byte alignment (e.g. each sg_apply_uniform + call will cost 256 bytes of uniform buffer size). The default size + is 4 MB, which is enough for 16384 sg_apply_uniform() calls per + frame (assuming the uniform data 'payload' is less than 256 bytes + per call). These rules are the same as for the Metal backend, so if + you are already using the Metal backend you'll be fine. + + - sg_apply_bindings(): the sokol-gfx WebGPU backend implements a bindgroup + cache to prevent excessive creation and destruction of BindGroup objects + when calling sg_apply_bindings(). The number of slots in the bindgroups + cache is defined in sg_desc.wgpu_bindgroups_cache_size when calling + sg_setup. The cache size must be a power-of-2 numbers, with the default being + 1024. The bindgroups cache behaviour can be observed by calling the new + function sg_query_frame_stats(), where the following struct items are + of interest: + + .wgpu.num_bindgroup_cache_hits + .wgpu.num_bindgroup_cache_misses + .wgpu.num_bindgroup_cache_collisions + .wgpu.num_bindgroup_cache_vs_hash_key_mismatch + + The value to pay attention to is `.wgpu.num_bindgroup_cache_collisions`, + if this number if consistently higher than a few percent of the + .wgpu.num_set_bindgroup value, it might be a good idea to bump the + bindgroups cache size to the next power-of-2. + + - sg_apply_viewport(): WebGPU currently has a unique restriction that viewport + rectangles must be contained entirely within the framebuffer. As a shitty + workaround sokol_gfx.h will clip incoming viewport rectangles against + the framebuffer, but this will distort the clipspace-to-screenspace mapping. + There's no proper way to handle this inside sokol_gfx.h, this must be fixed + in a future WebGPU update. + + - The sokol shader compiler generally adds `diagnostic(off, derivative_uniformity);` + into the WGSL output. Currently only the Chrome WebGPU implementation seems + to accept this. + + - The vertex format SG_VERTEXFORMAT_UINT10_N2 is currently not supported because + WebGPU lacks a matching vertex format (this is currently being worked on though, + as soon as the vertex format shows up in webgpu.h, sokol_gfx.h will add support. + + - Likewise, the following sokol-gfx vertex formats are not supported in WebGPU: + R16, R16SN, RG16, RG16SN, RGBA16, RGBA16SN and all PVRTC compressed format. + Unlike unsupported vertex formats, unsupported pixel formats can be queried + in cross-backend code via sg_query_pixel_format() though. + + - The Emscripten WebGPU shim currently doesn't support the Closure minification + post-link-step (e.g. currently the emcc argument '--closure 1' or '--closure 2' + will generate broken Javascript code. + + - sokol-gfx requires the WebGPU device feature `depth32float-stencil8` to be enabled + (this should be supported widely supported) + + - sokol-gfx expects that the WebGPU device feature `float32-filterable` to *not* be + enabled (this would exclude all iOS devices) LICENSE From eaa6075e1a25a4ee50f853035b79246e7352302b Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 21 Oct 2023 16:33:05 +0200 Subject: [PATCH 92/95] sokol_gfx.h: add details to sg_image_sample_type and sg_sampler_type doc header --- sokol_gfx.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sokol_gfx.h b/sokol_gfx.h index 71787431d..7208fbd6b 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -1802,6 +1802,17 @@ typedef enum sg_image_type { layer in sg_apply_bindings() to check if the provided image object is compatible with what the shader expects, and also required by the WebGPU backend. + + NOTE that the following texture pixel formats require the use + of SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT, combined with a sampler + of type SG_SAMPLERTYPE_NONFILTERING: + + - SG_PIXELFORMAT_R32F + - SG_PIXELFORMAT_RG32F + - SG_PIXELFORMAT_RGBA32F + + (when using sokol-shdc, also check out the tags `@image_sample_type` + and `@sampler_type`) */ typedef enum sg_image_sample_type { _SG_IMAGESAMPLETYPE_DEFAULT, // value 0 reserved for default-init @@ -1819,6 +1830,16 @@ typedef enum sg_image_sample_type { The basic type of a texture sampler (sampling vs comparison) as defined in a shader. Must be provided in sg_shader_sampler_desc. + + sg_image_sample_type and sg_sampler_type for a texture/sampler + pair must be compatible with each other, specifically only + the following pairs are allowed: + + - SG_IMAGESAMPLETYPE_FLOAT / (SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING) + - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT / SG_SAMPLERTYPE_NONFILTERING + - SG_IMAGESAMPLETYPE_SINT / SG_SAMPLERTYPE_NONFILTERING + - SG_IMAGESAMPLETYPE_UINT / SG_SAMPLERTYPE_NONFILTERING + - SG_IMAGESAMPLETYPE_DEPTH / SG_SAMPLERTYPE_COMPARISON */ typedef enum sg_sampler_type { _SG_SAMPLERTYPE_DEFAULT, From e05c84807d0991b15ad48a8717c6552fe091ddb3 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 21 Oct 2023 16:36:38 +0200 Subject: [PATCH 93/95] sokol_gfx.h: more documentation updates --- sokol_gfx.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sokol_gfx.h b/sokol_gfx.h index 7208fbd6b..1ceda6c19 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -703,7 +703,13 @@ style GLSL' cannot handle separate texture and sampler objects, but still groups them into a tradtional GLSL 'sampler object'. + Compatibility rules for image-sample-type vs sampler-type are as follows: + - SG_IMAGESAMPLETYPE_FLOAT => (SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING) + - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT => SG_SAMPLERTYPE_NONFILTERING + - SG_IMAGESAMPLETYPE_SINT => SG_SAMPLERTYPE_NONFILTERING + - SG_IMAGESAMPLETYPE_UINT => SG_SAMPLERTYPE_NONFILTERING + - SG_IMAGESAMPLETYPE_DEPTH => SG_SAMPLERTYPE_COMPARISON For example code of how to create backend-specific shader objects, please refer to the following samples: @@ -1835,11 +1841,11 @@ typedef enum sg_image_sample_type { pair must be compatible with each other, specifically only the following pairs are allowed: - - SG_IMAGESAMPLETYPE_FLOAT / (SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING) - - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT / SG_SAMPLERTYPE_NONFILTERING - - SG_IMAGESAMPLETYPE_SINT / SG_SAMPLERTYPE_NONFILTERING - - SG_IMAGESAMPLETYPE_UINT / SG_SAMPLERTYPE_NONFILTERING - - SG_IMAGESAMPLETYPE_DEPTH / SG_SAMPLERTYPE_COMPARISON + - SG_IMAGESAMPLETYPE_FLOAT => (SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING) + - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT => SG_SAMPLERTYPE_NONFILTERING + - SG_IMAGESAMPLETYPE_SINT => SG_SAMPLERTYPE_NONFILTERING + - SG_IMAGESAMPLETYPE_UINT => SG_SAMPLERTYPE_NONFILTERING + - SG_IMAGESAMPLETYPE_DEPTH => SG_SAMPLERTYPE_COMPARISON */ typedef enum sg_sampler_type { _SG_SAMPLERTYPE_DEFAULT, From 0f710472671c9c85093922cf69010947b4139d73 Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 21 Oct 2023 17:23:56 +0200 Subject: [PATCH 94/95] update changelog --- CHANGELOG.md | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5af7653f..ee613c59c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,102 @@ ## Updates +#### 21-Oct-2023 + +The major topic of this update is the 'finalized' WebGPU support in sokol_gfx.h and sokol_app.h. + +- WebGPU samples are hosted here: + + https://floooh.github.io/sokol-webgpu/ + +- WebGL2 samples remain hosted here: + + https://floooh.github.io/sokol-html5/ + +- Please read the following blog post as introduction: + + https://floooh.github.io/2023/10/16/sokol-webgpu.html + +- ...and the changelog and updated documentation in the sokol-shdc repository: + + https://github.com/floooh/sokol-tools + +- You'll also need to update the sokol-shdc binaries: + + https://github.com/floooh/sokol-tools-bin + +- Please also read the following new or updated sections in the embedded sokol_gfx.h header documentation: + + - `ON SHADER CREATION` + - `ON SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT AND SG_SAMPLERTYPE_NONFILTERING` + - `WEBGPU CAVEATS` + + Please do this especially when using any of the following texture pixel formats, as you will most likely encounter new validation layer errors: + + - `SG_PIXELFORMAT_R32F` + - `SG_PIXELFORMAT_RG32F` + - `SG_PIXELFORMAT_RGBA32F` + +- There is a tiny breaking change in the sokol_gfx.h API (only requires action when not using sokol-shdc): + + - the following `sg_sampler_type` enum items have been renamed to better harmonize with WebGPU: + - SG_SAMPLERTYPE_SAMPLE => SG_SAMPLERTYPE_FILTERING + - SG_SAMPLERTYPE_COMPARE => SG_SAMPLERTYPE_COMPARISON + + - the enum `sg_image_sample_type` gained a new item: + - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT + + - the enum `sg_sampler_type` gained a new item: + - SG_SAMPLERTYPE_NONFILTERING + +- The sokol_gfx.h struct `sg_desc` has two new items: + - `.wgpu_bindgroups_cache_size` - must be power-of-2, default: 1024 + - `.wgpu_disable_bindgroups_cache` - default: false + +- sokol_gfx.h gained the following new public API functions to query per-frame information: + - `sg_frame_stats sg_query_frame_stats()` + - `void sg_enable_frame_stats(void)` + - `void sg_disable_frame_stats(void)` + - `bool sg_frame_stats_enabled(void)` + + Frame statistics gathering is enabled after startup, but can be temporarily + disabled and enabled again via `sg_disable_frame_stats()` and `sg_enable_frame_stats`. + +- The sokol_gfx.h validation layer has new validation checks in `sg_make_shader()` + regarding image/sampler pair compatibility (WebGPU is particularly strict about + this stuff). + +- In sokol_app.h, the old wip WebGPU device and swapchain setup code is now implemented + in pure C code (previously this was a mix of Javascript and C). + +- Also note that sokol_app.h currently only supports WebGPU setup in the Emscripten backend. + If you want to use sokol_gfx.h with the WebGPU backend in a native scenario, you'll have + to use a different window system glue library (like GLFW). The sokol-samples directory + has a handful of examples for using sokol_gfx.h + Dawn + GLFW. + +- The following headers have been made compatible with the sokol_gfx.h WebGPU backend + (mainly by embedding WGSL shader code): + - sokol_debugtext.h + - sokol_fontstash.h + - sokol_gl.h + - sokol_spine.h + - sokol_imgui.h (also required some more changes for embedding `unfilterable-float` + textures, since these now require separate shader and pipeline objects) + - sokol_nuklear.h (works in WebGPU, but doesn't contain the work from sokol_imgui.h + to support `unfilterable-float` user textures) + +- sokol_gfx_imgui.h gained a new function `sg_imgui_draw_menu()` which renders a + menu panel to show/hide all debug windows. Previously this had to be done + outside the header. + +- sokol_gfx_imgui.h gained a new 'frame stats' window, which allows to peak into + sokol_gfx.h frame-rendering internals. This basically visualizes the struct + `sg_frame_stats` returned by the new sokol_gfx.h function `sg_query_frame_stats()`. + +- The sokol-samples repository gained 3 new samples: + - cubemap-jpeg-sapp.c (load a cubemap from seperate JPEG files) + - cubemaprt-sapp.c (render into cubemap faces - this demo actually existed a while but wasn't "official" so far) + - drawcallperf-sapp.c (a sample to explore the performance overhead of sg_apply_bindings, sg_apply_uniforms and sg_draw) + #### 03-Oct-2023 - sokol_app.h win/gl: PR https://github.com/floooh/sokol/pull/886 has been merged, this makes From 61c40b7a351d18bf0909ec94f9abe4640d8e017c Mon Sep 17 00:00:00 2001 From: Andre Weissflog Date: Sat, 21 Oct 2023 17:27:04 +0200 Subject: [PATCH 95/95] update readme and changelog --- CHANGELOG.md | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee613c59c..f67abcce1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,7 @@ The major topic of this update is the 'finalized' WebGPU support in sokol_gfx.h - There is a tiny breaking change in the sokol_gfx.h API (only requires action when not using sokol-shdc): - - the following `sg_sampler_type` enum items have been renamed to better harmonize with WebGPU: + - the following `sg_sampler_type` enum items have been renamed to better match their WebGPU counterparts: - SG_SAMPLERTYPE_SAMPLE => SG_SAMPLERTYPE_FILTERING - SG_SAMPLERTYPE_COMPARE => SG_SAMPLERTYPE_COMPARISON @@ -68,7 +68,7 @@ The major topic of this update is the 'finalized' WebGPU support in sokol_gfx.h - In sokol_app.h, the old wip WebGPU device and swapchain setup code is now implemented in pure C code (previously this was a mix of Javascript and C). -- Also note that sokol_app.h currently only supports WebGPU setup in the Emscripten backend. +- Also note that sokol_app.h currently only supports WebGPU in the Emscripten backend. If you want to use sokol_gfx.h with the WebGPU backend in a native scenario, you'll have to use a different window system glue library (like GLFW). The sokol-samples directory has a handful of examples for using sokol_gfx.h + Dawn + GLFW. diff --git a/README.md b/README.md index 8349a6d80..36e257732 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Simple [STB-style](https://github.com/nothings/stb/blob/master/docs/stb_howto.txt) cross-platform libraries for C and C++, written in C. -[**See what's new**](https://github.com/floooh/sokol/blob/master/CHANGELOG.md) (**25-Sep-2023** POTENTIALLY BREAKING: allocator callbacks have been renamed) +[**See what's new**](https://github.com/floooh/sokol/blob/master/CHANGELOG.md) (**21-Oct-2023** WebGPU!) [![Build](/../../actions/workflows/main.yml/badge.svg)](/../../actions/workflows/main.yml) [![Bindings](/../../actions/workflows/gen_bindings.yml/badge.svg)](/../../actions/workflows/gen_bindings.yml) [![build](https://github.com/floooh/sokol-zig/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-zig/actions/workflows/main.yml) [![build](https://github.com/floooh/sokol-nim/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-nim/actions/workflows/main.yml) [![Odin](https://github.com/floooh/sokol-odin/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-odin/actions/workflows/main.yml)[![Rust](https://github.com/floooh/sokol-rust/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-rust/actions/workflows/main.yml)