From 83bdfef8e08286a8863242597e6c9f1e5b207a53 Mon Sep 17 00:00:00 2001 From: Basil Fierz Date: Sun, 16 May 2021 18:55:58 +0200 Subject: [PATCH] Backends: WGPU: update to latest specs. (#4116, #3632) Merged 13 commits. --- backends/imgui_impl_wgpu.cpp | 256 ++++++++-------------- docs/CHANGELOG.txt | 1 + examples/example_emscripten_wgpu/main.cpp | 8 +- 3 files changed, 96 insertions(+), 169 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 348818780..7724aa2b0 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2021-05-16: Update to latest WebGPU specs (compatible with Emscripten 2.0.20 and Chrome Canary 92). // 2021-02-18: Change blending equation to preserve alpha in output buffer. // 2021-01-28: Initial version. @@ -22,11 +23,16 @@ #define HAS_EMSCRIPTEN_VERSION(major, minor, tiny) (__EMSCRIPTEN_major__ > (major) || (__EMSCRIPTEN_major__ == (major) && __EMSCRIPTEN_minor__ > (minor)) || (__EMSCRIPTEN_major__ == (major) && __EMSCRIPTEN_minor__ == (minor) && __EMSCRIPTEN_tiny__ >= (tiny))) +#if defined(__EMSCRIPTEN__) && !HAS_EMSCRIPTEN_VERSION(2, 0, 20) +#error "Requires at least emscripten 2.0.20" +#endif + // Dear ImGui prototypes from imgui_internal.h extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed = 0); // WebGPU data static WGPUDevice g_wgpuDevice = NULL; +static WGPUQueue g_defaultQueue = NULL; static WGPUTextureFormat g_renderTargetFormat = WGPUTextureFormat_Undefined; static WGPURenderPipeline g_pipelineState = NULL; @@ -37,9 +43,9 @@ struct RenderResources WGPUSampler Sampler; // Sampler for the font texture WGPUBuffer Uniforms; // Shader uniforms WGPUBindGroup CommonBindGroup; // Resources bind-group to bind the common resources to pipeline - WGPUBindGroupLayout ImageBindGroupLayout; // Bind group layout for image textures ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map) WGPUBindGroup ImageBindGroup; // Default font-resource of Dear ImGui + WGPUBindGroupLayout ImageBindGroupLayout; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM }; static RenderResources g_resources; @@ -241,8 +247,8 @@ static void SafeRelease(RenderResources& res) SafeRelease(res.Sampler); SafeRelease(res.Uniforms); SafeRelease(res.CommonBindGroup); - SafeRelease(res.ImageBindGroupLayout); SafeRelease(res.ImageBindGroup); + SafeRelease(res.ImageBindGroupLayout); }; static void SafeRelease(FrameResources& res) @@ -296,23 +302,21 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - wgpuQueueWriteBuffer(wgpuDeviceGetDefaultQueue(g_wgpuDevice), g_resources.Uniforms, 0, mvp, sizeof(mvp)); + wgpuQueueWriteBuffer(g_defaultQueue, g_resources.Uniforms, 0, mvp, sizeof(mvp)); } // Setup viewport wgpuRenderPassEncoderSetViewport(ctx, 0, 0, draw_data->DisplaySize.x, draw_data->DisplaySize.y, 0, 1); // Bind shader and vertex buffers - unsigned int stride = sizeof(ImDrawVert); - unsigned int offset = 0; - wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, offset, fr->VertexBufferSize * stride); - wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, fr->IndexBufferSize * sizeof(ImDrawIdx)); + wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, 0); + wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, 0); wgpuRenderPassEncoderSetPipeline(ctx, g_pipelineState); wgpuRenderPassEncoderSetBindGroup(ctx, 0, g_resources.CommonBindGroup, 0, NULL); // Setup blend factor WGPUColor blend_color = { 0.f, 0.f, 0.f, 0.f }; - wgpuRenderPassEncoderSetBlendColor(ctx, &blend_color); + wgpuRenderPassEncoderSetBlendConstant(ctx, &blend_color); } // Render function @@ -331,7 +335,11 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder // Create and grow vertex/index buffers if needed if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount) { - SafeRelease(fr->VertexBuffer); + if (fr->VertexBuffer) + { + wgpuBufferDestroy(fr->VertexBuffer); + wgpuBufferRelease(fr->VertexBuffer); + } SafeRelease(fr->VertexBufferHost); fr->VertexBufferSize = draw_data->TotalVtxCount + 5000; @@ -351,7 +359,11 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder } if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount) { - SafeRelease(fr->IndexBuffer); + if (fr->IndexBuffer) + { + wgpuBufferDestroy(fr->IndexBuffer); + wgpuBufferRelease(fr->IndexBuffer); + } SafeRelease(fr->IndexBufferHost); fr->IndexBufferSize = draw_data->TotalIdxCount + 10000; @@ -383,8 +395,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder } int64_t vb_write_size = ((char*)vtx_dst - (char*)fr->VertexBufferHost + 3) & ~3; int64_t ib_write_size = ((char*)idx_dst - (char*)fr->IndexBufferHost + 3) & ~3; - wgpuQueueWriteBuffer(wgpuDeviceGetDefaultQueue(g_wgpuDevice), fr->VertexBuffer, 0, fr->VertexBufferHost, vb_write_size); - wgpuQueueWriteBuffer(wgpuDeviceGetDefaultQueue(g_wgpuDevice), fr->IndexBuffer, 0, fr->IndexBufferHost, ib_write_size); + wgpuQueueWriteBuffer(g_defaultQueue, fr->VertexBuffer, 0, fr->VertexBufferHost, vb_write_size); + wgpuQueueWriteBuffer(g_defaultQueue, fr->IndexBuffer, 0, fr->IndexBufferHost, ib_write_size); // Setup desired render state ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr); @@ -439,18 +451,6 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder } } -static WGPUBuffer ImGui_ImplWGPU_CreateBufferFromData(const WGPUDevice& device, const void* data, uint64_t size, WGPUBufferUsage usage) -{ - WGPUBufferDescriptor descriptor = {}; - descriptor.size = size; - descriptor.usage = usage | WGPUBufferUsage_CopyDst; - WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor); - - WGPUQueue queue = wgpuDeviceGetDefaultQueue(g_wgpuDevice); - wgpuQueueWriteBuffer(queue, buffer, 0, data, size); - return buffer; -} - static void ImGui_ImplWGPU_CreateFontsTexture() { // Build texture atlas @@ -466,7 +466,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture() tex_desc.dimension = WGPUTextureDimension_2D; tex_desc.size.width = width; tex_desc.size.height = height; - tex_desc.size.depth = 1; + tex_desc.size.depthOrArrayLayers = 1; tex_desc.sampleCount = 1; tex_desc.format = WGPUTextureFormat_RGBA8Unorm; tex_desc.mipLevelCount = 1; @@ -486,34 +486,17 @@ static void ImGui_ImplWGPU_CreateFontsTexture() // Upload texture data { - WGPUBuffer staging_buffer = ImGui_ImplWGPU_CreateBufferFromData(g_wgpuDevice, pixels, (uint32_t)(width * size_pp * height), WGPUBufferUsage_CopySrc); - - WGPUBufferCopyView bufferCopyView = {}; - bufferCopyView.buffer = staging_buffer; - bufferCopyView.layout.offset = 0; - bufferCopyView.layout.bytesPerRow = width * size_pp; - bufferCopyView.layout.rowsPerImage = height; - - WGPUTextureCopyView textureCopyView = {}; - textureCopyView.texture = g_resources.FontTexture; - textureCopyView.mipLevel = 0; - textureCopyView.origin = { 0, 0, 0 }; -#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14) - textureCopyView.aspect = WGPUTextureAspect_All; -#endif - - WGPUExtent3D copySize = { (uint32_t)width, (uint32_t)height, 1 }; - - WGPUCommandEncoderDescriptor enc_desc = {}; - WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(g_wgpuDevice, &enc_desc); - wgpuCommandEncoderCopyBufferToTexture(encoder, &bufferCopyView, &textureCopyView, ©Size); - WGPUCommandBufferDescriptor cmd_buf_desc = {}; - WGPUCommandBuffer copy = wgpuCommandEncoderFinish(encoder, &cmd_buf_desc); - WGPUQueue queue = wgpuDeviceGetDefaultQueue(g_wgpuDevice); - wgpuQueueSubmit(queue, 1, ©); - - wgpuCommandEncoderRelease(encoder); - wgpuBufferRelease(staging_buffer); + WGPUImageCopyTexture dst_view = {}; + dst_view.texture = g_resources.FontTexture; + dst_view.mipLevel = 0; + dst_view.origin = { 0, 0, 0 }; + dst_view.aspect = WGPUTextureAspect_All; + WGPUTextureDataLayout layout = {}; + layout.offset = 0; + layout.bytesPerRow = width * size_pp; + layout.rowsPerImage = height; + WGPUExtent3D size = { static_cast(width), static_cast(height), 1 }; + wgpuQueueWriteTexture(g_defaultQueue, &dst_view, pixels, (uint32_t)(width * size_pp * height), &layout, &size); } // Create the associated sampler @@ -525,9 +508,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture() sampler_desc.addressModeU = WGPUAddressMode_Repeat; sampler_desc.addressModeV = WGPUAddressMode_Repeat; sampler_desc.addressModeW = WGPUAddressMode_Repeat; -#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14) sampler_desc.maxAnisotropy = 1; -#endif g_resources.Sampler = wgpuDeviceCreateSampler(g_wgpuDevice, &sampler_desc); } @@ -557,139 +538,82 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() ImGui_ImplWGPU_InvalidateDeviceObjects(); // Create render pipeline - WGPURenderPipelineDescriptor graphics_pipeline_desc = {}; - graphics_pipeline_desc.primitiveTopology = WGPUPrimitiveTopology_TriangleList; - graphics_pipeline_desc.sampleCount = 1; - graphics_pipeline_desc.sampleMask = UINT_MAX; - - WGPUBindGroupLayoutEntry common_bg_layout_entries[2] = {}; - common_bg_layout_entries[0].binding = 0; - common_bg_layout_entries[0].visibility = WGPUShaderStage_Vertex; -#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14) - common_bg_layout_entries[0].buffer.type = WGPUBufferBindingType_Uniform; -#else - common_bg_layout_entries[0].type = WGPUBindingType_UniformBuffer; -#endif - common_bg_layout_entries[1].binding = 1; - common_bg_layout_entries[1].visibility = WGPUShaderStage_Fragment; -#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14) - common_bg_layout_entries[1].sampler.type = WGPUSamplerBindingType_Filtering; -#else - common_bg_layout_entries[1].type = WGPUBindingType_Sampler; -#endif - - WGPUBindGroupLayoutEntry image_bg_layout_entries[1] = {}; - image_bg_layout_entries[0].binding = 0; - image_bg_layout_entries[0].visibility = WGPUShaderStage_Fragment; -#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14) - image_bg_layout_entries[0].texture.sampleType = WGPUTextureSampleType_Float; - image_bg_layout_entries[0].texture.viewDimension = WGPUTextureViewDimension_2D; -#else - image_bg_layout_entries[0].type = WGPUBindingType_SampledTexture; -#endif - - WGPUBindGroupLayoutDescriptor common_bg_layout_desc = {}; - common_bg_layout_desc.entryCount = 2; - common_bg_layout_desc.entries = common_bg_layout_entries; - - WGPUBindGroupLayoutDescriptor image_bg_layout_desc = {}; - image_bg_layout_desc.entryCount = 1; - image_bg_layout_desc.entries = image_bg_layout_entries; - - WGPUBindGroupLayout bg_layouts[2]; - bg_layouts[0] = wgpuDeviceCreateBindGroupLayout(g_wgpuDevice, &common_bg_layout_desc); - bg_layouts[1] = wgpuDeviceCreateBindGroupLayout(g_wgpuDevice, &image_bg_layout_desc); - - WGPUPipelineLayoutDescriptor layout_desc = {}; - layout_desc.bindGroupLayoutCount = 2; - layout_desc.bindGroupLayouts = bg_layouts; - graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(g_wgpuDevice, &layout_desc); + WGPURenderPipelineDescriptor2 graphics_pipeline_desc = {}; + graphics_pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList; + graphics_pipeline_desc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined; + graphics_pipeline_desc.primitive.frontFace = WGPUFrontFace_CW; + graphics_pipeline_desc.primitive.cullMode = WGPUCullMode_None; + graphics_pipeline_desc.multisample.count = 1; + graphics_pipeline_desc.multisample.mask = UINT_MAX; + graphics_pipeline_desc.multisample.alphaToCoverageEnabled = false; + graphics_pipeline_desc.layout = nullptr; // Use automatic layout generation // Create the vertex shader WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__glsl_shader_vert_spv, sizeof(__glsl_shader_vert_spv) / sizeof(uint32_t)); - graphics_pipeline_desc.vertexStage = vertex_shader_desc; + graphics_pipeline_desc.vertex.module = vertex_shader_desc.module; + graphics_pipeline_desc.vertex.entryPoint = vertex_shader_desc.entryPoint; // Vertex input configuration - WGPUVertexAttributeDescriptor attribute_binding_desc[] = + WGPUVertexAttribute attribute_desc[] = { - { WGPUVertexFormat_Float2, (uint64_t)IM_OFFSETOF(ImDrawVert, pos), 0 }, - { WGPUVertexFormat_Float2, (uint64_t)IM_OFFSETOF(ImDrawVert, uv), 1 }, - { WGPUVertexFormat_UChar4Norm, (uint64_t)IM_OFFSETOF(ImDrawVert, col), 2 }, + { WGPUVertexFormat_Float32x2, (uint64_t)IM_OFFSETOF(ImDrawVert, pos), 0 }, + { WGPUVertexFormat_Float32x2, (uint64_t)IM_OFFSETOF(ImDrawVert, uv), 1 }, + { WGPUVertexFormat_Unorm8x4, (uint64_t)IM_OFFSETOF(ImDrawVert, col), 2 }, }; - WGPUVertexBufferLayoutDescriptor buffer_binding_desc; - buffer_binding_desc.arrayStride = sizeof(ImDrawVert); - buffer_binding_desc.stepMode = WGPUInputStepMode_Vertex; - buffer_binding_desc.attributeCount = 3; - buffer_binding_desc.attributes = attribute_binding_desc; + WGPUVertexBufferLayout buffer_layouts[1]; + buffer_layouts[0].arrayStride = sizeof(ImDrawVert); + buffer_layouts[0].stepMode = WGPUInputStepMode_Vertex; + buffer_layouts[0].attributeCount = 3; + buffer_layouts[0].attributes = attribute_desc; - WGPUVertexStateDescriptor vertex_state_desc = {}; - vertex_state_desc.indexFormat = WGPUIndexFormat_Undefined; - vertex_state_desc.vertexBufferCount = 1; - vertex_state_desc.vertexBuffers = &buffer_binding_desc; - - graphics_pipeline_desc.vertexState = &vertex_state_desc; + graphics_pipeline_desc.vertex.bufferCount = 1; + graphics_pipeline_desc.vertex.buffers = buffer_layouts; // Create the pixel shader WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__glsl_shader_frag_spv, sizeof(__glsl_shader_frag_spv) / sizeof(uint32_t)); - graphics_pipeline_desc.fragmentStage = &pixel_shader_desc; // Create the blending setup - WGPUColorStateDescriptor color_state = {}; - { - color_state.format = g_renderTargetFormat; - color_state.alphaBlend.operation = WGPUBlendOperation_Add; - color_state.alphaBlend.srcFactor = WGPUBlendFactor_One; - color_state.alphaBlend.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; - color_state.colorBlend.operation = WGPUBlendOperation_Add; - color_state.colorBlend.srcFactor = WGPUBlendFactor_SrcAlpha; - color_state.colorBlend.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; - color_state.writeMask = WGPUColorWriteMask_All; + WGPUBlendState blend_state = {}; + blend_state.alpha.operation = WGPUBlendOperation_Add; + blend_state.alpha.srcFactor = WGPUBlendFactor_One; + blend_state.alpha.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; + blend_state.color.operation = WGPUBlendOperation_Add; + blend_state.color.srcFactor = WGPUBlendFactor_SrcAlpha; + blend_state.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha; - graphics_pipeline_desc.colorStateCount = 1; - graphics_pipeline_desc.colorStates = &color_state; - graphics_pipeline_desc.alphaToCoverageEnabled = false; - } + WGPUColorTargetState color_state = {}; + color_state.format = g_renderTargetFormat; + color_state.blend = &blend_state; + color_state.writeMask = WGPUColorWriteMask_All; - // Create the rasterizer state - WGPURasterizationStateDescriptor raster_desc = {}; - { - raster_desc.cullMode = WGPUCullMode_None; - raster_desc.frontFace = WGPUFrontFace_CW; - raster_desc.depthBias = 0; - raster_desc.depthBiasClamp = 0; - raster_desc.depthBiasSlopeScale = 0; - graphics_pipeline_desc.rasterizationState = &raster_desc; - } + WGPUFragmentState fragment_state = {}; + fragment_state.module = pixel_shader_desc.module; + fragment_state.entryPoint = pixel_shader_desc.entryPoint; + fragment_state.targetCount = 1; + fragment_state.targets = &color_state; + + graphics_pipeline_desc.fragment = &fragment_state; // Create depth-stencil State - WGPUDepthStencilStateDescriptor depth_desc = {}; - { - // Configure disabled state - depth_desc.format = WGPUTextureFormat_Undefined; - depth_desc.depthWriteEnabled = true; - depth_desc.depthCompare = WGPUCompareFunction_Always; - depth_desc.stencilReadMask = 0; - depth_desc.stencilWriteMask = 0; - depth_desc.stencilBack.compare = WGPUCompareFunction_Always; - depth_desc.stencilBack.failOp = WGPUStencilOperation_Keep; - depth_desc.stencilBack.depthFailOp = WGPUStencilOperation_Keep; - depth_desc.stencilBack.passOp = WGPUStencilOperation_Keep; - depth_desc.stencilFront.compare = WGPUCompareFunction_Always; - depth_desc.stencilFront.failOp = WGPUStencilOperation_Keep; - depth_desc.stencilFront.depthFailOp = WGPUStencilOperation_Keep; - depth_desc.stencilFront.passOp = WGPUStencilOperation_Keep; + WGPUDepthStencilState depth_stencil_state = {}; + depth_stencil_state.depthBias = 0; + depth_stencil_state.depthBiasClamp = 0; + depth_stencil_state.depthBiasSlopeScale = 0; - // No depth buffer corresponds to no configuration - graphics_pipeline_desc.depthStencilState = NULL; - } + // Configure disabled depth-stencil state + graphics_pipeline_desc.depthStencil = nullptr; - g_pipelineState = wgpuDeviceCreateRenderPipeline(g_wgpuDevice, &graphics_pipeline_desc); + g_pipelineState = wgpuDeviceCreateRenderPipeline2(g_wgpuDevice, &graphics_pipeline_desc); ImGui_ImplWGPU_CreateFontsTexture(); ImGui_ImplWGPU_CreateUniformBuffer(); // Create resource bind group + WGPUBindGroupLayout bg_layouts[2]; + bg_layouts[0] = wgpuRenderPipelineGetBindGroupLayout(g_pipelineState, 0); + bg_layouts[1] = wgpuRenderPipelineGetBindGroupLayout(g_pipelineState, 1); + WGPUBindGroupEntry common_bg_entries[] = { { 0, g_resources.Uniforms, 0, sizeof(Uniforms), 0, 0 }, @@ -701,10 +625,10 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() common_bg_descriptor.entryCount = sizeof(common_bg_entries) / sizeof(WGPUBindGroupEntry); common_bg_descriptor.entries = common_bg_entries; g_resources.CommonBindGroup = wgpuDeviceCreateBindGroup(g_wgpuDevice, &common_bg_descriptor); - g_resources.ImageBindGroupLayout = bg_layouts[1]; WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bg_layouts[1], g_resources.FontTextureView); g_resources.ImageBindGroup = image_bind_group; + g_resources.ImageBindGroupLayout = bg_layouts[1]; g_resources.ImageBindGroups.SetVoidPtr(ImHashData(&g_resources.FontTextureView, sizeof(ImTextureID)), image_bind_group); SafeRelease(vertex_shader_desc.module); @@ -737,6 +661,7 @@ bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextur io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. g_wgpuDevice = device; + g_defaultQueue = wgpuDeviceGetQueue(g_wgpuDevice); g_renderTargetFormat = rt_format; g_pFrameResources = new FrameResources[num_frames_in_flight]; g_numFramesInFlight = num_frames_in_flight; @@ -747,9 +672,9 @@ bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextur g_resources.Sampler = NULL; g_resources.Uniforms = NULL; g_resources.CommonBindGroup = NULL; - g_resources.ImageBindGroupLayout = NULL; g_resources.ImageBindGroups.Data.reserve(100); g_resources.ImageBindGroup = NULL; + g_resources.ImageBindGroupLayout = NULL; // Create buffers with a default size (they will later be grown as needed) for (int i = 0; i < num_frames_in_flight; i++) @@ -771,6 +696,7 @@ void ImGui_ImplWGPU_Shutdown() ImGui_ImplWGPU_InvalidateDeviceObjects(); delete[] g_pFrameResources; g_pFrameResources = NULL; + wgpuQueueRelease(g_defaultQueue); g_wgpuDevice = NULL; g_numFramesInFlight = 0; g_frameIndex = UINT_MAX; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 327ff2a0c..ee1f79a33 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -83,6 +83,7 @@ Other Changes: entering the rendering function. (#4045) [@Nemirtingas] - Backends: Vulkan: Fix mapped memory Vulkan validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize. (#3957) [@AgentX1994] +- Backends: WebGPU: Update to latest specs (Chrome Canary 92 and Emscripten 2.0.20). (#4116, #3632) [@bfierz, @Kangz] - Backends: OpenGL3: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5. (#3998, #2366, #2186) [@s7jones] - Examples: OpenGL: Add OpenGL ES 2.0 support to modern GL examples. (#2837, #3951) [@lethal-guitar, @hinxx] - Examples: Vulkan: Rebuild swapchain on VK_SUBOPTIMAL_KHR. (#3881) diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index a9da9320d..d11d906c8 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -147,7 +147,7 @@ static void main_loop(void* window) wgpu_swap_chain_height = height; WGPUSwapChainDescriptor swap_chain_desc = {}; - swap_chain_desc.usage = WGPUTextureUsage_OutputAttachment; + swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment; swap_chain_desc.format = WGPUTextureFormat_RGBA8Unorm; swap_chain_desc.width = width; swap_chain_desc.height = height; @@ -202,11 +202,11 @@ static void main_loop(void* window) // Rendering ImGui::Render(); - WGPURenderPassColorAttachmentDescriptor color_attachments = {}; + WGPURenderPassColorAttachment color_attachments = {}; color_attachments.loadOp = WGPULoadOp_Clear; color_attachments.storeOp = WGPUStoreOp_Store; color_attachments.clearColor = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w }; - color_attachments.attachment = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain); + color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain); WGPURenderPassDescriptor render_pass_desc = {}; render_pass_desc.colorAttachmentCount = 1; render_pass_desc.colorAttachments = &color_attachments; @@ -221,7 +221,7 @@ static void main_loop(void* window) WGPUCommandBufferDescriptor cmd_buffer_desc = {}; WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc); - WGPUQueue queue = wgpuDeviceGetDefaultQueue(wgpu_device); + WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device); wgpuQueueSubmit(queue, 1, &cmd_buffer); }