2021-01-28 18:37:34 +08:00
// dear imgui: Renderer for WebGPU
// This needs to be used along with a Platform Binding (e.g. GLFW)
2021-01-28 19:11:26 +08:00
// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
2021-01-28 18:37:34 +08:00
// Implemented features:
// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
2023-02-07 19:24:42 +08:00
// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
2024-10-08 04:12:09 +08:00
// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
2021-01-28 18:37:34 +08:00
2021-08-24 20:48:04 +08:00
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
2021-05-27 19:59:35 +08:00
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
2023-09-11 19:47:08 +08:00
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp
2021-01-28 18:37:34 +08:00
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
2024-10-21 20:19:31 +08:00
// 2024-10-14: Update Dawn support for change of string usages. (#8082, #8083)
2024-10-08 03:00:07 +08:00
// 2024-10-07: Expose selected render state in ImGui_ImplWGPU_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
2024-10-08 04:02:55 +08:00
// 2024-10-07: Changed default texture sampler to Clamp instead of Repeat/Wrap.
2024-09-16 22:07:02 +08:00
// 2024-09-16: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU define to handle ever-changing native implementations. (#7977)
2024-01-22 21:54:45 +08:00
// 2024-01-22: Added configurable PipelineMultisampleState struct. (#7240)
2024-01-22 21:46:41 +08:00
// 2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes.
2024-01-20 21:14:53 +08:00
// 2024-01-22: Fixed pipeline layout leak. (#7245)
2024-01-17 20:26:02 +08:00
// 2024-01-17: Explicitly fill all of WGPUDepthStencilState since standard removed defaults.
2023-07-13 17:48:16 +08:00
// 2023-07-13: Use WGPUShaderModuleWGSLDescriptor's code instead of source. use WGPUMipmapFilterMode_Linear instead of WGPUFilterMode_Linear. (#6602)
2023-02-24 07:14:31 +08:00
// 2023-04-11: Align buffer sizes. Use WGSL shaders instead of precompiled SPIR-V.
2023-04-11 21:25:21 +08:00
// 2023-04-11: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
2023-01-26 04:45:03 +08:00
// 2023-01-25: Revert automatic pipeline layout generation (see https://github.com/gpuweb/gpuweb/issues/2470)
2022-11-24 04:58:02 +08:00
// 2022-11-24: Fixed validation error with default depth buffer settings.
2022-11-08 04:35:05 +08:00
// 2022-11-10: Fixed rendering when a depth buffer is enabled. Added 'WGPUTextureFormat depth_format' parameter to ImGui_ImplWGPU_Init().
2022-10-11 18:22:29 +08:00
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
2021-11-29 19:18:25 +08:00
// 2021-11-29: Passing explicit buffer sizes to wgpuRenderPassEncoderSetVertexBuffer()/wgpuRenderPassEncoderSetIndexBuffer().
2022-11-08 04:35:05 +08:00
// 2021-08-24: Fixed for latest specs.
2021-05-22 18:37:33 +08:00
// 2021-05-24: Add support for draw_data->FramebufferScale.
2021-02-07 19:36:54 +08:00
// 2021-05-19: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
2021-05-17 00:55:58 +08:00
// 2021-05-16: Update to latest WebGPU specs (compatible with Emscripten 2.0.20 and Chrome Canary 92).
2021-02-18 02:29:07 +08:00
// 2021-02-18: Change blending equation to preserve alpha in output buffer.
2021-01-28 19:11:26 +08:00
// 2021-01-28: Initial version.
2021-01-28 18:37:34 +08:00
2024-09-16 22:07:02 +08:00
// When targeting native platforms (i.e. NOT emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN
// or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
# ifndef __EMSCRIPTEN__
# if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
# error exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
# endif
# else
# if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
# error neither IMGUI_IMPL_WEBGPU_BACKEND_DAWN nor IMGUI_IMPL_WEBGPU_BACKEND_WGPU may be defined if targeting emscripten!
# endif
# endif
2021-01-28 18:37:34 +08:00
# include "imgui.h"
2023-07-13 17:27:52 +08:00
# ifndef IMGUI_DISABLE
2021-01-28 18:37:34 +08:00
# include "imgui_impl_wgpu.h"
# include <limits.h>
# include <webgpu/webgpu.h>
2021-01-28 19:11:26 +08:00
// Dear ImGui prototypes from imgui_internal.h
extern ImGuiID ImHashData ( const void * data_p , size_t data_size , ImU32 seed = 0 ) ;
2023-02-21 06:39:50 +08:00
# define MEMALIGN(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align (copied from IM_ALIGN() macro).
2021-01-28 18:37:34 +08:00
// WebGPU data
struct RenderResources
{
2023-04-11 21:25:21 +08:00
WGPUTexture FontTexture = nullptr ; // Font texture
WGPUTextureView FontTextureView = nullptr ; // Texture view for font texture
WGPUSampler Sampler = nullptr ; // Sampler for the font texture
WGPUBuffer Uniforms = nullptr ; // Shader uniforms
WGPUBindGroup CommonBindGroup = nullptr ; // Resources bind-group to bind the common resources to pipeline
ImGuiStorage ImageBindGroups ; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map)
WGPUBindGroup ImageBindGroup = nullptr ; // Default font-resource of Dear ImGui
WGPUBindGroupLayout ImageBindGroupLayout = nullptr ; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM
2021-01-28 18:37:34 +08:00
} ;
struct FrameResources
{
WGPUBuffer IndexBuffer ;
WGPUBuffer VertexBuffer ;
ImDrawIdx * IndexBufferHost ;
ImDrawVert * VertexBufferHost ;
int IndexBufferSize ;
int VertexBufferSize ;
} ;
struct Uniforms
{
float MVP [ 4 ] [ 4 ] ;
2023-02-24 07:14:31 +08:00
float Gamma ;
2021-01-28 18:37:34 +08:00
} ;
2023-04-11 21:25:21 +08:00
struct ImGui_ImplWGPU_Data
{
2024-01-22 21:46:41 +08:00
ImGui_ImplWGPU_InitInfo initInfo ;
WGPUDevice wgpuDevice = nullptr ;
WGPUQueue defaultQueue = nullptr ;
WGPUTextureFormat renderTargetFormat = WGPUTextureFormat_Undefined ;
WGPUTextureFormat depthStencilFormat = WGPUTextureFormat_Undefined ;
WGPURenderPipeline pipelineState = nullptr ;
RenderResources renderResources ;
FrameResources * pFrameResources = nullptr ;
unsigned int numFramesInFlight = 0 ;
unsigned int frameIndex = UINT_MAX ;
2023-04-11 21:25:21 +08:00
} ;
// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
static ImGui_ImplWGPU_Data * ImGui_ImplWGPU_GetBackendData ( )
{
return ImGui : : GetCurrentContext ( ) ? ( ImGui_ImplWGPU_Data * ) ImGui : : GetIO ( ) . BackendRendererUserData : nullptr ;
}
2021-01-28 18:37:34 +08:00
//-----------------------------------------------------------------------------
// SHADERS
//-----------------------------------------------------------------------------
2023-02-24 07:14:31 +08:00
static const char __shader_vert_wgsl [ ] = R " (
struct VertexInput {
@ location ( 0 ) position : vec2 < f32 > ,
@ location ( 1 ) uv : vec2 < f32 > ,
@ location ( 2 ) color : vec4 < f32 > ,
} ;
2021-01-28 18:37:34 +08:00
2023-02-24 07:14:31 +08:00
struct VertexOutput {
@ builtin ( position ) position : vec4 < f32 > ,
@ location ( 0 ) color : vec4 < f32 > ,
@ location ( 1 ) uv : vec2 < f32 > ,
} ;
2021-01-28 18:37:34 +08:00
2023-02-24 07:14:31 +08:00
struct Uniforms {
mvp : mat4x4 < f32 > ,
gamma : f32 ,
2021-01-28 18:37:34 +08:00
} ;
2023-02-24 07:14:31 +08:00
@ group ( 0 ) @ binding ( 0 ) var < uniform > uniforms : Uniforms ;
@ vertex
fn main ( in : VertexInput ) - > VertexOutput {
var out : VertexOutput ;
out . position = uniforms . mvp * vec4 < f32 > ( in . position , 0.0 , 1.0 ) ;
out . color = in . color ;
out . uv = in . uv ;
return out ;
2021-01-28 18:37:34 +08:00
}
2023-02-24 07:14:31 +08:00
) " ;
static const char __shader_frag_wgsl [ ] = R " (
struct VertexOutput {
@ builtin ( position ) position : vec4 < f32 > ,
@ location ( 0 ) color : vec4 < f32 > ,
@ location ( 1 ) uv : vec2 < f32 > ,
} ;
struct Uniforms {
mvp : mat4x4 < f32 > ,
gamma : f32 ,
2021-01-28 18:37:34 +08:00
} ;
2023-02-24 07:14:31 +08:00
@ group ( 0 ) @ binding ( 0 ) var < uniform > uniforms : Uniforms ;
@ group ( 0 ) @ binding ( 1 ) var s : sampler ;
@ group ( 1 ) @ binding ( 0 ) var t : texture_2d < f32 > ;
@ fragment
fn main ( in : VertexOutput ) - > @ location ( 0 ) vec4 < f32 > {
let color = in . color * textureSample ( t , s , in . uv ) ;
let corrected_color = pow ( color . rgb , vec3 < f32 > ( uniforms . gamma ) ) ;
return vec4 < f32 > ( corrected_color , color . a ) ;
}
) " ;
2021-01-28 18:37:34 +08:00
static void SafeRelease ( ImDrawIdx * & res )
{
if ( res )
delete [ ] res ;
2022-10-11 18:22:29 +08:00
res = nullptr ;
2021-01-28 18:37:34 +08:00
}
static void SafeRelease ( ImDrawVert * & res )
{
if ( res )
delete [ ] res ;
2022-10-11 18:22:29 +08:00
res = nullptr ;
2021-01-28 18:37:34 +08:00
}
static void SafeRelease ( WGPUBindGroupLayout & res )
{
if ( res )
wgpuBindGroupLayoutRelease ( res ) ;
2022-10-11 18:22:29 +08:00
res = nullptr ;
2021-01-28 18:37:34 +08:00
}
static void SafeRelease ( WGPUBindGroup & res )
{
if ( res )
wgpuBindGroupRelease ( res ) ;
2022-10-11 18:22:29 +08:00
res = nullptr ;
2021-01-28 18:37:34 +08:00
}
static void SafeRelease ( WGPUBuffer & res )
{
if ( res )
wgpuBufferRelease ( res ) ;
2022-10-11 18:22:29 +08:00
res = nullptr ;
2021-01-28 18:37:34 +08:00
}
2024-01-20 21:14:53 +08:00
static void SafeRelease ( WGPUPipelineLayout & res )
{
if ( res )
wgpuPipelineLayoutRelease ( res ) ;
res = nullptr ;
}
2021-01-28 18:37:34 +08:00
static void SafeRelease ( WGPURenderPipeline & res )
{
if ( res )
wgpuRenderPipelineRelease ( res ) ;
2022-10-11 18:22:29 +08:00
res = nullptr ;
2021-01-28 18:37:34 +08:00
}
static void SafeRelease ( WGPUSampler & res )
{
if ( res )
wgpuSamplerRelease ( res ) ;
2022-10-11 18:22:29 +08:00
res = nullptr ;
2021-01-28 18:37:34 +08:00
}
static void SafeRelease ( WGPUShaderModule & res )
{
if ( res )
wgpuShaderModuleRelease ( res ) ;
2022-10-11 18:22:29 +08:00
res = nullptr ;
2021-01-28 18:37:34 +08:00
}
static void SafeRelease ( WGPUTextureView & res )
{
if ( res )
wgpuTextureViewRelease ( res ) ;
2022-10-11 18:22:29 +08:00
res = nullptr ;
2021-01-28 18:37:34 +08:00
}
static void SafeRelease ( WGPUTexture & res )
{
if ( res )
wgpuTextureRelease ( res ) ;
2022-10-11 18:22:29 +08:00
res = nullptr ;
2021-01-28 18:37:34 +08:00
}
static void SafeRelease ( RenderResources & res )
{
SafeRelease ( res . FontTexture ) ;
SafeRelease ( res . FontTextureView ) ;
SafeRelease ( res . Sampler ) ;
SafeRelease ( res . Uniforms ) ;
SafeRelease ( res . CommonBindGroup ) ;
SafeRelease ( res . ImageBindGroup ) ;
2021-05-17 00:55:58 +08:00
SafeRelease ( res . ImageBindGroupLayout ) ;
2021-01-28 18:37:34 +08:00
} ;
static void SafeRelease ( FrameResources & res )
{
SafeRelease ( res . IndexBuffer ) ;
SafeRelease ( res . VertexBuffer ) ;
SafeRelease ( res . IndexBufferHost ) ;
SafeRelease ( res . VertexBufferHost ) ;
}
2023-02-24 07:14:31 +08:00
static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule ( const char * wgsl_source )
2021-01-28 18:37:34 +08:00
{
2023-04-11 21:25:21 +08:00
ImGui_ImplWGPU_Data * bd = ImGui_ImplWGPU_GetBackendData ( ) ;
2024-09-16 22:07:02 +08:00
# ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
2024-09-22 12:05:28 +08:00
WGPUShaderSourceWGSL wgsl_desc = { } ;
2024-09-16 22:07:02 +08:00
wgsl_desc . chain . sType = WGPUSType_ShaderSourceWGSL ;
2024-09-22 12:05:28 +08:00
wgsl_desc . code = { wgsl_source , WGPU_STRLEN } ;
2024-09-16 22:07:02 +08:00
# else
2024-09-22 12:05:28 +08:00
WGPUShaderModuleWGSLDescriptor wgsl_desc = { } ;
2023-02-24 07:14:31 +08:00
wgsl_desc . chain . sType = WGPUSType_ShaderModuleWGSLDescriptor ;
2024-09-22 12:05:28 +08:00
wgsl_desc . code = wgsl_source ;
2024-09-16 22:07:02 +08:00
# endif
2021-01-28 18:37:34 +08:00
2021-10-07 20:58:09 +08:00
WGPUShaderModuleDescriptor desc = { } ;
2023-02-24 07:14:31 +08:00
desc . nextInChain = reinterpret_cast < WGPUChainedStruct * > ( & wgsl_desc ) ;
2021-01-28 18:37:34 +08:00
WGPUProgrammableStageDescriptor stage_desc = { } ;
2023-04-11 21:25:21 +08:00
stage_desc . module = wgpuDeviceCreateShaderModule ( bd - > wgpuDevice , & desc ) ;
2024-10-21 20:19:31 +08:00
# ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
stage_desc . entryPoint = { " main " , WGPU_STRLEN } ;
# else
2021-01-28 18:37:34 +08:00
stage_desc . entryPoint = " main " ;
2024-10-21 20:19:31 +08:00
# endif
2021-01-28 18:37:34 +08:00
return stage_desc ;
}
static WGPUBindGroup ImGui_ImplWGPU_CreateImageBindGroup ( WGPUBindGroupLayout layout , WGPUTextureView texture )
{
2023-04-11 21:25:21 +08:00
ImGui_ImplWGPU_Data * bd = ImGui_ImplWGPU_GetBackendData ( ) ;
2021-09-06 05:40:01 +08:00
WGPUBindGroupEntry image_bg_entries [ ] = { { nullptr , 0 , 0 , 0 , 0 , 0 , texture } } ;
2021-01-28 18:37:34 +08:00
WGPUBindGroupDescriptor image_bg_descriptor = { } ;
image_bg_descriptor . layout = layout ;
image_bg_descriptor . entryCount = sizeof ( image_bg_entries ) / sizeof ( WGPUBindGroupEntry ) ;
image_bg_descriptor . entries = image_bg_entries ;
2023-04-11 21:25:21 +08:00
return wgpuDeviceCreateBindGroup ( bd - > wgpuDevice , & image_bg_descriptor ) ;
2021-01-28 18:37:34 +08:00
}
static void ImGui_ImplWGPU_SetupRenderState ( ImDrawData * draw_data , WGPURenderPassEncoder ctx , FrameResources * fr )
{
2023-04-11 21:25:21 +08:00
ImGui_ImplWGPU_Data * bd = ImGui_ImplWGPU_GetBackendData ( ) ;
2021-01-28 18:37:34 +08:00
// Setup orthographic projection matrix into our constant buffer
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
{
float L = draw_data - > DisplayPos . x ;
float R = draw_data - > DisplayPos . x + draw_data - > DisplaySize . x ;
float T = draw_data - > DisplayPos . y ;
float B = draw_data - > DisplayPos . y + draw_data - > DisplaySize . y ;
float mvp [ 4 ] [ 4 ] =
{
{ 2.0f / ( R - L ) , 0.0f , 0.0f , 0.0f } ,
{ 0.0f , 2.0f / ( T - B ) , 0.0f , 0.0f } ,
{ 0.0f , 0.0f , 0.5f , 0.0f } ,
{ ( R + L ) / ( L - R ) , ( T + B ) / ( B - T ) , 0.5f , 1.0f } ,
} ;
2023-02-24 07:14:31 +08:00
wgpuQueueWriteBuffer ( bd - > defaultQueue , bd - > renderResources . Uniforms , offsetof ( Uniforms , MVP ) , mvp , sizeof ( Uniforms : : MVP ) ) ;
float gamma ;
switch ( bd - > renderTargetFormat )
{
case WGPUTextureFormat_ASTC10x10UnormSrgb :
case WGPUTextureFormat_ASTC10x5UnormSrgb :
case WGPUTextureFormat_ASTC10x6UnormSrgb :
case WGPUTextureFormat_ASTC10x8UnormSrgb :
case WGPUTextureFormat_ASTC12x10UnormSrgb :
case WGPUTextureFormat_ASTC12x12UnormSrgb :
case WGPUTextureFormat_ASTC4x4UnormSrgb :
case WGPUTextureFormat_ASTC5x5UnormSrgb :
case WGPUTextureFormat_ASTC6x5UnormSrgb :
case WGPUTextureFormat_ASTC6x6UnormSrgb :
case WGPUTextureFormat_ASTC8x5UnormSrgb :
case WGPUTextureFormat_ASTC8x6UnormSrgb :
case WGPUTextureFormat_ASTC8x8UnormSrgb :
case WGPUTextureFormat_BC1RGBAUnormSrgb :
case WGPUTextureFormat_BC2RGBAUnormSrgb :
case WGPUTextureFormat_BC3RGBAUnormSrgb :
case WGPUTextureFormat_BC7RGBAUnormSrgb :
case WGPUTextureFormat_BGRA8UnormSrgb :
case WGPUTextureFormat_ETC2RGB8A1UnormSrgb :
case WGPUTextureFormat_ETC2RGB8UnormSrgb :
case WGPUTextureFormat_ETC2RGBA8UnormSrgb :
case WGPUTextureFormat_RGBA8UnormSrgb :
gamma = 2.2f ;
break ;
default :
gamma = 1.0f ;
}
wgpuQueueWriteBuffer ( bd - > defaultQueue , bd - > renderResources . Uniforms , offsetof ( Uniforms , Gamma ) , & gamma , sizeof ( Uniforms : : Gamma ) ) ;
2021-01-28 18:37:34 +08:00
}
// Setup viewport
2021-05-22 18:37:33 +08:00
wgpuRenderPassEncoderSetViewport ( ctx , 0 , 0 , draw_data - > FramebufferScale . x * draw_data - > DisplaySize . x , draw_data - > FramebufferScale . y * draw_data - > DisplaySize . y , 0 , 1 ) ;
2021-01-28 18:37:34 +08:00
// Bind shader and vertex buffers
2022-01-12 05:56:35 +08:00
wgpuRenderPassEncoderSetVertexBuffer ( ctx , 0 , fr - > VertexBuffer , 0 , fr - > VertexBufferSize * sizeof ( ImDrawVert ) ) ;
wgpuRenderPassEncoderSetIndexBuffer ( ctx , fr - > IndexBuffer , sizeof ( ImDrawIdx ) = = 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32 , 0 , fr - > IndexBufferSize * sizeof ( ImDrawIdx ) ) ;
2023-04-11 21:25:21 +08:00
wgpuRenderPassEncoderSetPipeline ( ctx , bd - > pipelineState ) ;
wgpuRenderPassEncoderSetBindGroup ( ctx , 0 , bd - > renderResources . CommonBindGroup , 0 , nullptr ) ;
2021-01-28 18:37:34 +08:00
// Setup blend factor
WGPUColor blend_color = { 0.f , 0.f , 0.f , 0.f } ;
2021-05-17 00:55:58 +08:00
wgpuRenderPassEncoderSetBlendConstant ( ctx , & blend_color ) ;
2021-01-28 18:37:34 +08:00
}
// Render function
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
void ImGui_ImplWGPU_RenderDrawData ( ImDrawData * draw_data , WGPURenderPassEncoder pass_encoder )
{
// Avoid rendering when minimized
2024-01-03 18:25:19 +08:00
int fb_width = ( int ) ( draw_data - > DisplaySize . x * draw_data - > FramebufferScale . x ) ;
int fb_height = ( int ) ( draw_data - > DisplaySize . y * draw_data - > FramebufferScale . y ) ;
if ( fb_width < = 0 | | fb_height < = 0 | | draw_data - > CmdListsCount = = 0 )
2021-01-28 18:37:34 +08:00
return ;
2021-01-28 19:11:26 +08:00
// FIXME: Assuming that this only gets called once per frame!
2021-01-28 18:37:34 +08:00
// If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator.
2023-04-11 21:25:21 +08:00
ImGui_ImplWGPU_Data * bd = ImGui_ImplWGPU_GetBackendData ( ) ;
bd - > frameIndex = bd - > frameIndex + 1 ;
FrameResources * fr = & bd - > pFrameResources [ bd - > frameIndex % bd - > numFramesInFlight ] ;
2021-01-28 18:37:34 +08:00
// Create and grow vertex/index buffers if needed
2022-10-11 18:22:29 +08:00
if ( fr - > VertexBuffer = = nullptr | | fr - > VertexBufferSize < draw_data - > TotalVtxCount )
2021-01-28 18:37:34 +08:00
{
2021-05-17 00:55:58 +08:00
if ( fr - > VertexBuffer )
{
wgpuBufferDestroy ( fr - > VertexBuffer ) ;
wgpuBufferRelease ( fr - > VertexBuffer ) ;
}
2021-01-28 18:37:34 +08:00
SafeRelease ( fr - > VertexBufferHost ) ;
fr - > VertexBufferSize = draw_data - > TotalVtxCount + 5000 ;
2021-01-28 19:11:26 +08:00
WGPUBufferDescriptor vb_desc =
{
2022-10-11 18:22:29 +08:00
nullptr ,
2021-01-28 19:11:26 +08:00
" Dear ImGui Vertex buffer " ,
2024-10-21 20:19:31 +08:00
# ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
WGPU_STRLEN ,
# endif
2021-01-28 18:37:34 +08:00
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex ,
2023-02-21 06:39:50 +08:00
MEMALIGN ( fr - > VertexBufferSize * sizeof ( ImDrawVert ) , 4 ) ,
2021-01-28 18:37:34 +08:00
false
} ;
2023-04-11 21:25:21 +08:00
fr - > VertexBuffer = wgpuDeviceCreateBuffer ( bd - > wgpuDevice , & vb_desc ) ;
2021-01-28 18:37:34 +08:00
if ( ! fr - > VertexBuffer )
return ;
fr - > VertexBufferHost = new ImDrawVert [ fr - > VertexBufferSize ] ;
}
2022-10-11 18:22:29 +08:00
if ( fr - > IndexBuffer = = nullptr | | fr - > IndexBufferSize < draw_data - > TotalIdxCount )
2021-01-28 18:37:34 +08:00
{
2021-05-17 00:55:58 +08:00
if ( fr - > IndexBuffer )
{
wgpuBufferDestroy ( fr - > IndexBuffer ) ;
wgpuBufferRelease ( fr - > IndexBuffer ) ;
}
2021-01-28 18:37:34 +08:00
SafeRelease ( fr - > IndexBufferHost ) ;
fr - > IndexBufferSize = draw_data - > TotalIdxCount + 10000 ;
2021-01-28 19:11:26 +08:00
WGPUBufferDescriptor ib_desc =
{
2022-10-11 18:22:29 +08:00
nullptr ,
2021-01-28 19:11:26 +08:00
" Dear ImGui Index buffer " ,
2024-10-21 20:19:31 +08:00
# ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
WGPU_STRLEN ,
# endif
2021-01-28 18:37:34 +08:00
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index ,
2023-02-21 06:39:50 +08:00
MEMALIGN ( fr - > IndexBufferSize * sizeof ( ImDrawIdx ) , 4 ) ,
2021-01-28 18:37:34 +08:00
false
} ;
2023-04-11 21:25:21 +08:00
fr - > IndexBuffer = wgpuDeviceCreateBuffer ( bd - > wgpuDevice , & ib_desc ) ;
2021-01-28 18:37:34 +08:00
if ( ! fr - > IndexBuffer )
return ;
fr - > IndexBufferHost = new ImDrawIdx [ fr - > IndexBufferSize ] ;
}
// Upload vertex/index data into a single contiguous GPU buffer
ImDrawVert * vtx_dst = ( ImDrawVert * ) fr - > VertexBufferHost ;
ImDrawIdx * idx_dst = ( ImDrawIdx * ) fr - > IndexBufferHost ;
for ( int n = 0 ; n < draw_data - > CmdListsCount ; n + + )
{
2024-10-07 23:52:57 +08:00
const ImDrawList * draw_list = draw_data - > CmdLists [ n ] ;
memcpy ( vtx_dst , draw_list - > VtxBuffer . Data , draw_list - > VtxBuffer . Size * sizeof ( ImDrawVert ) ) ;
memcpy ( idx_dst , draw_list - > IdxBuffer . Data , draw_list - > IdxBuffer . Size * sizeof ( ImDrawIdx ) ) ;
vtx_dst + = draw_list - > VtxBuffer . Size ;
idx_dst + = draw_list - > IdxBuffer . Size ;
2021-01-28 18:37:34 +08:00
}
2023-02-21 06:39:50 +08:00
int64_t vb_write_size = MEMALIGN ( ( char * ) vtx_dst - ( char * ) fr - > VertexBufferHost , 4 ) ;
int64_t ib_write_size = MEMALIGN ( ( char * ) idx_dst - ( char * ) fr - > IndexBufferHost , 4 ) ;
2023-04-11 21:25:21 +08:00
wgpuQueueWriteBuffer ( bd - > defaultQueue , fr - > VertexBuffer , 0 , fr - > VertexBufferHost , vb_write_size ) ;
wgpuQueueWriteBuffer ( bd - > defaultQueue , fr - > IndexBuffer , 0 , fr - > IndexBufferHost , ib_write_size ) ;
2021-01-28 18:37:34 +08:00
// Setup desired render state
ImGui_ImplWGPU_SetupRenderState ( draw_data , pass_encoder , fr ) ;
2024-10-08 03:00:07 +08:00
// Setup render state structure (for callbacks and custom texture bindings)
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
ImGui_ImplWGPU_RenderState render_state ;
render_state . Device = bd - > wgpuDevice ;
render_state . RenderPassEncoder = pass_encoder ;
platform_io . Renderer_RenderState = & render_state ;
2021-01-28 18:37:34 +08:00
// Render command lists
// (Because we merged all buffers into a single one, we maintain our own offset into them)
int global_vtx_offset = 0 ;
int global_idx_offset = 0 ;
2021-05-22 18:37:33 +08:00
ImVec2 clip_scale = draw_data - > FramebufferScale ;
2021-01-28 18:37:34 +08:00
ImVec2 clip_off = draw_data - > DisplayPos ;
for ( int n = 0 ; n < draw_data - > CmdListsCount ; n + + )
{
2024-10-07 23:52:57 +08:00
const ImDrawList * draw_list = draw_data - > CmdLists [ n ] ;
for ( int cmd_i = 0 ; cmd_i < draw_list - > CmdBuffer . Size ; cmd_i + + )
2021-01-28 18:37:34 +08:00
{
2024-10-07 23:52:57 +08:00
const ImDrawCmd * pcmd = & draw_list - > CmdBuffer [ cmd_i ] ;
2022-10-11 18:22:29 +08:00
if ( pcmd - > UserCallback ! = nullptr )
2021-01-28 18:37:34 +08:00
{
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if ( pcmd - > UserCallback = = ImDrawCallback_ResetRenderState )
ImGui_ImplWGPU_SetupRenderState ( draw_data , pass_encoder , fr ) ;
else
2024-10-07 23:52:57 +08:00
pcmd - > UserCallback ( draw_list , pcmd ) ;
2021-01-28 18:37:34 +08:00
}
else
{
// Bind custom texture
2021-05-20 00:50:31 +08:00
ImTextureID tex_id = pcmd - > GetTexID ( ) ;
ImGuiID tex_id_hash = ImHashData ( & tex_id , sizeof ( tex_id ) ) ;
2023-04-11 21:25:21 +08:00
auto bind_group = bd - > renderResources . ImageBindGroups . GetVoidPtr ( tex_id_hash ) ;
2021-01-28 19:11:26 +08:00
if ( bind_group )
{
2022-10-11 18:22:29 +08:00
wgpuRenderPassEncoderSetBindGroup ( pass_encoder , 1 , ( WGPUBindGroup ) bind_group , 0 , nullptr ) ;
2021-01-28 18:37:34 +08:00
}
2021-01-28 19:11:26 +08:00
else
{
2023-04-11 21:25:21 +08:00
WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup ( bd - > renderResources . ImageBindGroupLayout , ( WGPUTextureView ) tex_id ) ;
bd - > renderResources . ImageBindGroups . SetVoidPtr ( tex_id_hash , image_bind_group ) ;
2022-10-11 18:22:29 +08:00
wgpuRenderPassEncoderSetBindGroup ( pass_encoder , 1 , image_bind_group , 0 , nullptr ) ;
2021-01-28 18:37:34 +08:00
}
2021-08-24 23:03:52 +08:00
// Project scissor/clipping rectangles into framebuffer space
ImVec2 clip_min ( ( pcmd - > ClipRect . x - clip_off . x ) * clip_scale . x , ( pcmd - > ClipRect . y - clip_off . y ) * clip_scale . y ) ;
ImVec2 clip_max ( ( pcmd - > ClipRect . z - clip_off . x ) * clip_scale . x , ( pcmd - > ClipRect . w - clip_off . y ) * clip_scale . y ) ;
2024-01-03 18:25:19 +08:00
// Clamp to viewport as wgpuRenderPassEncoderSetScissorRect() won't accept values that are off bounds
if ( clip_min . x < 0.0f ) { clip_min . x = 0.0f ; }
if ( clip_min . y < 0.0f ) { clip_min . y = 0.0f ; }
if ( clip_max . x > fb_width ) { clip_max . x = ( float ) fb_width ; }
if ( clip_max . y > fb_height ) { clip_max . y = ( float ) fb_height ; }
2021-12-01 04:48:29 +08:00
if ( clip_max . x < = clip_min . x | | clip_max . y < = clip_min . y )
2021-08-24 23:03:52 +08:00
continue ;
// Apply scissor/clipping rectangle, Draw
wgpuRenderPassEncoderSetScissorRect ( pass_encoder , ( uint32_t ) clip_min . x , ( uint32_t ) clip_min . y , ( uint32_t ) ( clip_max . x - clip_min . x ) , ( uint32_t ) ( clip_max . y - clip_min . y ) ) ;
2021-01-28 18:37:34 +08:00
wgpuRenderPassEncoderDrawIndexed ( pass_encoder , pcmd - > ElemCount , 1 , pcmd - > IdxOffset + global_idx_offset , pcmd - > VtxOffset + global_vtx_offset , 0 ) ;
}
}
2024-10-07 23:52:57 +08:00
global_idx_offset + = draw_list - > IdxBuffer . Size ;
global_vtx_offset + = draw_list - > VtxBuffer . Size ;
2021-01-28 18:37:34 +08:00
}
2024-10-08 03:00:07 +08:00
platform_io . Renderer_RenderState = NULL ;
2021-01-28 18:37:34 +08:00
}
static void ImGui_ImplWGPU_CreateFontsTexture ( )
{
// Build texture atlas
2023-04-11 21:25:21 +08:00
ImGui_ImplWGPU_Data * bd = ImGui_ImplWGPU_GetBackendData ( ) ;
2021-01-28 18:37:34 +08:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
unsigned char * pixels ;
int width , height , size_pp ;
io . Fonts - > GetTexDataAsRGBA32 ( & pixels , & width , & height , & size_pp ) ;
// Upload texture to graphics system
{
WGPUTextureDescriptor tex_desc = { } ;
2024-10-21 20:19:31 +08:00
# ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
tex_desc . label = { " Dear ImGui Font Texture " , WGPU_STRLEN } ;
# else
2021-01-28 19:11:26 +08:00
tex_desc . label = " Dear ImGui Font Texture " ;
2024-10-21 20:19:31 +08:00
# endif
2021-01-28 18:37:34 +08:00
tex_desc . dimension = WGPUTextureDimension_2D ;
tex_desc . size . width = width ;
tex_desc . size . height = height ;
2021-05-17 00:55:58 +08:00
tex_desc . size . depthOrArrayLayers = 1 ;
2021-01-28 18:37:34 +08:00
tex_desc . sampleCount = 1 ;
tex_desc . format = WGPUTextureFormat_RGBA8Unorm ;
tex_desc . mipLevelCount = 1 ;
2021-09-06 05:40:01 +08:00
tex_desc . usage = WGPUTextureUsage_CopyDst | WGPUTextureUsage_TextureBinding ;
2023-04-11 21:25:21 +08:00
bd - > renderResources . FontTexture = wgpuDeviceCreateTexture ( bd - > wgpuDevice , & tex_desc ) ;
2021-01-28 18:37:34 +08:00
WGPUTextureViewDescriptor tex_view_desc = { } ;
tex_view_desc . format = WGPUTextureFormat_RGBA8Unorm ;
tex_view_desc . dimension = WGPUTextureViewDimension_2D ;
tex_view_desc . baseMipLevel = 0 ;
tex_view_desc . mipLevelCount = 1 ;
tex_view_desc . baseArrayLayer = 0 ;
tex_view_desc . arrayLayerCount = 1 ;
tex_view_desc . aspect = WGPUTextureAspect_All ;
2023-04-11 21:25:21 +08:00
bd - > renderResources . FontTextureView = wgpuTextureCreateView ( bd - > renderResources . FontTexture , & tex_view_desc ) ;
2021-01-28 18:37:34 +08:00
}
// Upload texture data
{
2021-05-17 00:55:58 +08:00
WGPUImageCopyTexture dst_view = { } ;
2023-04-11 21:25:21 +08:00
dst_view . texture = bd - > renderResources . FontTexture ;
2021-05-17 00:55:58 +08:00
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 ;
2021-05-22 18:37:33 +08:00
WGPUExtent3D size = { ( uint32_t ) width , ( uint32_t ) height , 1 } ;
2023-04-11 21:25:21 +08:00
wgpuQueueWriteTexture ( bd - > defaultQueue , & dst_view , pixels , ( uint32_t ) ( width * size_pp * height ) , & layout , & size ) ;
2021-01-28 18:37:34 +08:00
}
// Create the associated sampler
2022-04-07 20:28:08 +08:00
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
2021-01-28 18:37:34 +08:00
{
WGPUSamplerDescriptor sampler_desc = { } ;
sampler_desc . minFilter = WGPUFilterMode_Linear ;
sampler_desc . magFilter = WGPUFilterMode_Linear ;
2023-07-13 17:48:16 +08:00
sampler_desc . mipmapFilter = WGPUMipmapFilterMode_Linear ;
2024-10-08 04:02:55 +08:00
sampler_desc . addressModeU = WGPUAddressMode_ClampToEdge ;
sampler_desc . addressModeV = WGPUAddressMode_ClampToEdge ;
sampler_desc . addressModeW = WGPUAddressMode_ClampToEdge ;
2021-01-31 03:25:20 +08:00
sampler_desc . maxAnisotropy = 1 ;
2023-04-11 21:25:21 +08:00
bd - > renderResources . Sampler = wgpuDeviceCreateSampler ( bd - > wgpuDevice , & sampler_desc ) ;
2021-01-28 18:37:34 +08:00
}
// Store our identifier
2023-04-11 21:25:21 +08:00
static_assert ( sizeof ( ImTextureID ) > = sizeof ( bd - > renderResources . FontTexture ) , " Can't pack descriptor handle into TexID, 32-bit not supported yet. " ) ;
io . Fonts - > SetTexID ( ( ImTextureID ) bd - > renderResources . FontTextureView ) ;
2021-01-28 18:37:34 +08:00
}
static void ImGui_ImplWGPU_CreateUniformBuffer ( )
{
2023-04-11 21:25:21 +08:00
ImGui_ImplWGPU_Data * bd = ImGui_ImplWGPU_GetBackendData ( ) ;
2021-01-28 19:11:26 +08:00
WGPUBufferDescriptor ub_desc =
{
2022-10-11 18:22:29 +08:00
nullptr ,
2021-01-28 19:11:26 +08:00
" Dear ImGui Uniform buffer " ,
2024-10-21 20:19:31 +08:00
# ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
WGPU_STRLEN ,
# endif
2021-01-28 18:37:34 +08:00
WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform ,
2023-02-24 07:14:31 +08:00
MEMALIGN ( sizeof ( Uniforms ) , 16 ) ,
2021-01-28 18:37:34 +08:00
false
} ;
2023-04-11 21:25:21 +08:00
bd - > renderResources . Uniforms = wgpuDeviceCreateBuffer ( bd - > wgpuDevice , & ub_desc ) ;
2021-01-28 18:37:34 +08:00
}
bool ImGui_ImplWGPU_CreateDeviceObjects ( )
{
2023-04-11 21:25:21 +08:00
ImGui_ImplWGPU_Data * bd = ImGui_ImplWGPU_GetBackendData ( ) ;
if ( ! bd - > wgpuDevice )
2021-01-28 18:37:34 +08:00
return false ;
2023-04-11 21:25:21 +08:00
if ( bd - > pipelineState )
2021-01-28 18:37:34 +08:00
ImGui_ImplWGPU_InvalidateDeviceObjects ( ) ;
// Create render pipeline
2021-08-24 20:48:04 +08:00
WGPURenderPipelineDescriptor graphics_pipeline_desc = { } ;
2021-05-17 00:55:58 +08:00
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 ;
2024-01-22 21:54:45 +08:00
graphics_pipeline_desc . multisample = bd - > initInfo . PipelineMultisampleState ;
2023-01-26 04:45:03 +08:00
// Bind group layouts
WGPUBindGroupLayoutEntry common_bg_layout_entries [ 2 ] = { } ;
common_bg_layout_entries [ 0 ] . binding = 0 ;
2023-02-24 07:14:31 +08:00
common_bg_layout_entries [ 0 ] . visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment ;
2023-01-26 04:45:03 +08:00
common_bg_layout_entries [ 0 ] . buffer . type = WGPUBufferBindingType_Uniform ;
common_bg_layout_entries [ 1 ] . binding = 1 ;
common_bg_layout_entries [ 1 ] . visibility = WGPUShaderStage_Fragment ;
common_bg_layout_entries [ 1 ] . sampler . type = WGPUSamplerBindingType_Filtering ;
WGPUBindGroupLayoutEntry image_bg_layout_entries [ 1 ] = { } ;
image_bg_layout_entries [ 0 ] . binding = 0 ;
image_bg_layout_entries [ 0 ] . visibility = WGPUShaderStage_Fragment ;
image_bg_layout_entries [ 0 ] . texture . sampleType = WGPUTextureSampleType_Float ;
image_bg_layout_entries [ 0 ] . texture . viewDimension = WGPUTextureViewDimension_2D ;
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 ] ;
2023-04-11 21:25:21 +08:00
bg_layouts [ 0 ] = wgpuDeviceCreateBindGroupLayout ( bd - > wgpuDevice , & common_bg_layout_desc ) ;
bg_layouts [ 1 ] = wgpuDeviceCreateBindGroupLayout ( bd - > wgpuDevice , & image_bg_layout_desc ) ;
2023-01-26 04:45:03 +08:00
WGPUPipelineLayoutDescriptor layout_desc = { } ;
layout_desc . bindGroupLayoutCount = 2 ;
layout_desc . bindGroupLayouts = bg_layouts ;
2023-04-11 21:25:21 +08:00
graphics_pipeline_desc . layout = wgpuDeviceCreatePipelineLayout ( bd - > wgpuDevice , & layout_desc ) ;
2021-01-28 18:37:34 +08:00
// Create the vertex shader
2023-02-24 07:14:31 +08:00
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule ( __shader_vert_wgsl ) ;
2021-05-17 00:55:58 +08:00
graphics_pipeline_desc . vertex . module = vertex_shader_desc . module ;
graphics_pipeline_desc . vertex . entryPoint = vertex_shader_desc . entryPoint ;
2021-01-28 18:37:34 +08:00
// Vertex input configuration
2021-05-17 00:55:58 +08:00
WGPUVertexAttribute attribute_desc [ ] =
2021-01-28 19:11:26 +08:00
{
2023-11-09 23:44:39 +08:00
{ WGPUVertexFormat_Float32x2 , ( uint64_t ) offsetof ( ImDrawVert , pos ) , 0 } ,
{ WGPUVertexFormat_Float32x2 , ( uint64_t ) offsetof ( ImDrawVert , uv ) , 1 } ,
{ WGPUVertexFormat_Unorm8x4 , ( uint64_t ) offsetof ( ImDrawVert , col ) , 2 } ,
2021-01-28 18:37:34 +08:00
} ;
2021-05-17 00:55:58 +08:00
WGPUVertexBufferLayout buffer_layouts [ 1 ] ;
buffer_layouts [ 0 ] . arrayStride = sizeof ( ImDrawVert ) ;
2021-09-06 05:40:01 +08:00
buffer_layouts [ 0 ] . stepMode = WGPUVertexStepMode_Vertex ;
2021-05-17 00:55:58 +08:00
buffer_layouts [ 0 ] . attributeCount = 3 ;
buffer_layouts [ 0 ] . attributes = attribute_desc ;
2021-01-28 18:37:34 +08:00
2021-05-17 00:55:58 +08:00
graphics_pipeline_desc . vertex . bufferCount = 1 ;
graphics_pipeline_desc . vertex . buffers = buffer_layouts ;
2021-01-28 18:37:34 +08:00
// Create the pixel shader
2023-02-24 07:14:31 +08:00
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModule ( __shader_frag_wgsl ) ;
2021-01-28 18:37:34 +08:00
// Create the blending setup
2021-05-17 00:55:58 +08:00
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 ;
WGPUColorTargetState color_state = { } ;
2023-04-11 21:25:21 +08:00
color_state . format = bd - > renderTargetFormat ;
2021-05-17 00:55:58 +08:00
color_state . blend = & blend_state ;
color_state . writeMask = WGPUColorWriteMask_All ;
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 ;
2021-01-28 18:37:34 +08:00
// Create depth-stencil State
2021-05-17 00:55:58 +08:00
WGPUDepthStencilState depth_stencil_state = { } ;
2023-04-11 21:25:21 +08:00
depth_stencil_state . format = bd - > depthStencilFormat ;
2024-09-16 22:07:02 +08:00
# ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
depth_stencil_state . depthWriteEnabled = WGPUOptionalBool_False ;
# else
2022-11-08 04:35:05 +08:00
depth_stencil_state . depthWriteEnabled = false ;
2024-09-16 22:07:02 +08:00
# endif
2022-11-24 04:58:02 +08:00
depth_stencil_state . depthCompare = WGPUCompareFunction_Always ;
depth_stencil_state . stencilFront . compare = WGPUCompareFunction_Always ;
2024-01-17 20:26:02 +08:00
depth_stencil_state . stencilFront . failOp = WGPUStencilOperation_Keep ;
depth_stencil_state . stencilFront . depthFailOp = WGPUStencilOperation_Keep ;
depth_stencil_state . stencilFront . passOp = WGPUStencilOperation_Keep ;
2022-11-24 04:58:02 +08:00
depth_stencil_state . stencilBack . compare = WGPUCompareFunction_Always ;
2024-01-17 20:26:02 +08:00
depth_stencil_state . stencilBack . failOp = WGPUStencilOperation_Keep ;
depth_stencil_state . stencilBack . depthFailOp = WGPUStencilOperation_Keep ;
depth_stencil_state . stencilBack . passOp = WGPUStencilOperation_Keep ;
2021-01-28 18:37:34 +08:00
2021-05-17 00:55:58 +08:00
// Configure disabled depth-stencil state
2023-04-11 21:25:21 +08:00
graphics_pipeline_desc . depthStencil = ( bd - > depthStencilFormat = = WGPUTextureFormat_Undefined ) ? nullptr : & depth_stencil_state ;
2021-05-17 00:55:58 +08:00
2023-04-11 21:25:21 +08:00
bd - > pipelineState = wgpuDeviceCreateRenderPipeline ( bd - > wgpuDevice , & graphics_pipeline_desc ) ;
2021-01-28 18:37:34 +08:00
ImGui_ImplWGPU_CreateFontsTexture ( ) ;
ImGui_ImplWGPU_CreateUniformBuffer ( ) ;
// Create resource bind group
2021-01-28 19:11:26 +08:00
WGPUBindGroupEntry common_bg_entries [ ] =
{
2023-02-24 07:14:31 +08:00
{ nullptr , 0 , bd - > renderResources . Uniforms , 0 , MEMALIGN ( sizeof ( Uniforms ) , 16 ) , 0 , 0 } ,
2023-04-11 21:25:21 +08:00
{ nullptr , 1 , 0 , 0 , 0 , bd - > renderResources . Sampler , 0 } ,
2021-01-28 18:37:34 +08:00
} ;
WGPUBindGroupDescriptor common_bg_descriptor = { } ;
common_bg_descriptor . layout = bg_layouts [ 0 ] ;
common_bg_descriptor . entryCount = sizeof ( common_bg_entries ) / sizeof ( WGPUBindGroupEntry ) ;
common_bg_descriptor . entries = common_bg_entries ;
2023-04-11 21:25:21 +08:00
bd - > renderResources . CommonBindGroup = wgpuDeviceCreateBindGroup ( bd - > wgpuDevice , & common_bg_descriptor ) ;
2021-01-28 18:37:34 +08:00
2023-04-11 21:25:21 +08:00
WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup ( bg_layouts [ 1 ] , bd - > renderResources . FontTextureView ) ;
bd - > renderResources . ImageBindGroup = image_bind_group ;
bd - > renderResources . ImageBindGroupLayout = bg_layouts [ 1 ] ;
bd - > renderResources . ImageBindGroups . SetVoidPtr ( ImHashData ( & bd - > renderResources . FontTextureView , sizeof ( ImTextureID ) ) , image_bind_group ) ;
2021-01-28 18:37:34 +08:00
SafeRelease ( vertex_shader_desc . module ) ;
SafeRelease ( pixel_shader_desc . module ) ;
2024-01-20 21:14:53 +08:00
SafeRelease ( graphics_pipeline_desc . layout ) ;
2021-01-28 18:37:34 +08:00
SafeRelease ( bg_layouts [ 0 ] ) ;
return true ;
}
void ImGui_ImplWGPU_InvalidateDeviceObjects ( )
{
2023-04-11 21:25:21 +08:00
ImGui_ImplWGPU_Data * bd = ImGui_ImplWGPU_GetBackendData ( ) ;
if ( ! bd - > wgpuDevice )
2021-01-28 18:37:34 +08:00
return ;
2023-04-11 21:25:21 +08:00
SafeRelease ( bd - > pipelineState ) ;
SafeRelease ( bd - > renderResources ) ;
2021-01-28 18:37:34 +08:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
2023-02-07 19:24:42 +08:00
io . Fonts - > SetTexID ( 0 ) ; // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
2021-01-28 18:37:34 +08:00
2023-04-11 21:25:21 +08:00
for ( unsigned int i = 0 ; i < bd - > numFramesInFlight ; i + + )
SafeRelease ( bd - > pFrameResources [ i ] ) ;
2021-01-28 18:37:34 +08:00
}
2024-01-22 21:46:41 +08:00
bool ImGui_ImplWGPU_Init ( ImGui_ImplWGPU_InitInfo * init_info )
2021-01-28 18:37:34 +08:00
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
2024-05-13 21:07:13 +08:00
IMGUI_CHECKVERSION ( ) ;
2023-04-11 21:25:21 +08:00
IM_ASSERT ( io . BackendRendererUserData = = nullptr & & " Already initialized a renderer backend! " ) ;
// Setup backend capabilities flags
ImGui_ImplWGPU_Data * bd = IM_NEW ( ImGui_ImplWGPU_Data ) ( ) ;
io . BackendRendererUserData = ( void * ) bd ;
2024-09-16 22:07:02 +08:00
# if defined(__EMSCRIPTEN__)
io . BackendRendererName = " imgui_impl_webgpu_emscripten " ;
# elif defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
io . BackendRendererName = " imgui_impl_webgpu_dawn " ;
# elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
io . BackendRendererName = " imgui_impl_webgpu_wgpu " ;
# else
2021-01-28 18:37:34 +08:00
io . BackendRendererName = " imgui_impl_webgpu " ;
2024-09-16 22:07:02 +08:00
# endif
2021-01-28 18:37:34 +08:00
io . BackendFlags | = ImGuiBackendFlags_RendererHasVtxOffset ; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
2024-01-22 21:46:41 +08:00
bd - > initInfo = * init_info ;
bd - > wgpuDevice = init_info - > Device ;
2023-04-11 21:25:21 +08:00
bd - > defaultQueue = wgpuDeviceGetQueue ( bd - > wgpuDevice ) ;
2024-01-22 21:46:41 +08:00
bd - > renderTargetFormat = init_info - > RenderTargetFormat ;
bd - > depthStencilFormat = init_info - > DepthStencilFormat ;
bd - > numFramesInFlight = init_info - > NumFramesInFlight ;
2023-04-11 21:25:21 +08:00
bd - > frameIndex = UINT_MAX ;
bd - > renderResources . FontTexture = nullptr ;
bd - > renderResources . FontTextureView = nullptr ;
bd - > renderResources . Sampler = nullptr ;
bd - > renderResources . Uniforms = nullptr ;
bd - > renderResources . CommonBindGroup = nullptr ;
bd - > renderResources . ImageBindGroups . Data . reserve ( 100 ) ;
bd - > renderResources . ImageBindGroup = nullptr ;
bd - > renderResources . ImageBindGroupLayout = nullptr ;
2021-01-28 18:37:34 +08:00
// Create buffers with a default size (they will later be grown as needed)
2024-01-22 21:46:41 +08:00
bd - > pFrameResources = new FrameResources [ bd - > numFramesInFlight ] ;
2024-04-16 19:51:03 +08:00
for ( unsigned int i = 0 ; i < bd - > numFramesInFlight ; i + + )
2021-01-28 18:37:34 +08:00
{
2023-04-11 21:25:21 +08:00
FrameResources * fr = & bd - > pFrameResources [ i ] ;
2022-10-11 18:22:29 +08:00
fr - > IndexBuffer = nullptr ;
fr - > VertexBuffer = nullptr ;
fr - > IndexBufferHost = nullptr ;
fr - > VertexBufferHost = nullptr ;
2021-01-28 18:37:34 +08:00
fr - > IndexBufferSize = 10000 ;
fr - > VertexBufferSize = 5000 ;
}
return true ;
}
void ImGui_ImplWGPU_Shutdown ( )
{
2023-04-11 21:25:21 +08:00
ImGui_ImplWGPU_Data * bd = ImGui_ImplWGPU_GetBackendData ( ) ;
IM_ASSERT ( bd ! = nullptr & & " No renderer backend to shutdown, or already shutdown? " ) ;
ImGuiIO & io = ImGui : : GetIO ( ) ;
2021-01-28 18:37:34 +08:00
ImGui_ImplWGPU_InvalidateDeviceObjects ( ) ;
2023-04-11 21:25:21 +08:00
delete [ ] bd - > pFrameResources ;
bd - > pFrameResources = nullptr ;
wgpuQueueRelease ( bd - > defaultQueue ) ;
bd - > wgpuDevice = nullptr ;
bd - > numFramesInFlight = 0 ;
bd - > frameIndex = UINT_MAX ;
io . BackendRendererName = nullptr ;
io . BackendRendererUserData = nullptr ;
2023-04-17 20:47:15 +08:00
io . BackendFlags & = ~ ImGuiBackendFlags_RendererHasVtxOffset ;
2023-04-11 21:25:21 +08:00
IM_DELETE ( bd ) ;
2021-01-28 18:37:34 +08:00
}
void ImGui_ImplWGPU_NewFrame ( )
{
2023-04-11 21:25:21 +08:00
ImGui_ImplWGPU_Data * bd = ImGui_ImplWGPU_GetBackendData ( ) ;
if ( ! bd - > pipelineState )
2021-01-28 18:37:34 +08:00
ImGui_ImplWGPU_CreateDeviceObjects ( ) ;
}
2023-07-13 17:27:52 +08:00
//-----------------------------------------------------------------------------
# endif // #ifndef IMGUI_DISABLE