@ -12,6 +12,7 @@
// CHANGELOG
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// (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-02-18: Change blending equation to preserve alpha in output buffer.
// 2021-01-28: Initial version.
// 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)))
# 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
// Dear ImGui prototypes from imgui_internal.h
extern ImGuiID ImHashData ( const void * data_p , size_t data_size , ImU32 seed = 0 ) ;
extern ImGuiID ImHashData ( const void * data_p , size_t data_size , ImU32 seed = 0 ) ;
// WebGPU data
// WebGPU data
static WGPUDevice g_wgpuDevice = NULL ;
static WGPUDevice g_wgpuDevice = NULL ;
static WGPUQueue g_defaultQueue = NULL ;
static WGPUTextureFormat g_renderTargetFormat = WGPUTextureFormat_Undefined ;
static WGPUTextureFormat g_renderTargetFormat = WGPUTextureFormat_Undefined ;
static WGPURenderPipeline g_pipelineState = NULL ;
static WGPURenderPipeline g_pipelineState = NULL ;
@ -37,9 +43,9 @@ struct RenderResources
WGPUSampler Sampler ; // Sampler for the font texture
WGPUSampler Sampler ; // Sampler for the font texture
WGPUBuffer Uniforms ; // Shader uniforms
WGPUBuffer Uniforms ; // Shader uniforms
WGPUBindGroup CommonBindGroup ; // Resources bind-group to bind the common resources to pipeline
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)
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
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 ;
static RenderResources g_resources ;
@ -241,8 +247,8 @@ static void SafeRelease(RenderResources& res)
SafeRelease ( res . Sampler ) ;
SafeRelease ( res . Sampler ) ;
SafeRelease ( res . Uniforms ) ;
SafeRelease ( res . Uniforms ) ;
SafeRelease ( res . CommonBindGroup ) ;
SafeRelease ( res . CommonBindGroup ) ;
SafeRelease ( res . ImageBindGroupLayout ) ;
SafeRelease ( res . ImageBindGroup ) ;
SafeRelease ( res . ImageBindGroup ) ;
SafeRelease ( res . ImageBindGroupLayout ) ;
} ;
} ;
static void SafeRelease ( FrameResources & res )
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 } ,
{ 0.0f , 0.0f , 0.5f , 0.0f } ,
{ ( R + L ) / ( L - R ) , ( T + B ) / ( B - T ) , 0.5f , 1.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
// Setup viewport
wgpuRenderPassEncoderSetViewport ( ctx , 0 , 0 , draw_data - > DisplaySize . x , draw_data - > DisplaySize . y , 0 , 1 ) ;
wgpuRenderPassEncoderSetViewport ( ctx , 0 , 0 , draw_data - > DisplaySize . x , draw_data - > DisplaySize . y , 0 , 1 ) ;
// Bind shader and vertex buffers
// Bind shader and vertex buffers
unsigned int stride = sizeof ( ImDrawVert ) ;
wgpuRenderPassEncoderSetVertexBuffer ( ctx , 0 , fr - > VertexBuffer , 0 , 0 ) ;
unsigned int offset = 0 ;
wgpuRenderPassEncoderSetIndexBuffer ( ctx , fr - > IndexBuffer , sizeof ( ImDrawIdx ) = = 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32 , 0 , 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 ) ) ;
wgpuRenderPassEncoderSetPipeline ( ctx , g_pipelineState ) ;
wgpuRenderPassEncoderSetPipeline ( ctx , g_pipelineState ) ;
wgpuRenderPassEncoderSetBindGroup ( ctx , 0 , g_resources . CommonBindGroup , 0 , NULL ) ;
wgpuRenderPassEncoderSetBindGroup ( ctx , 0 , g_resources . CommonBindGroup , 0 , NULL ) ;
// Setup blend factor
// Setup blend factor
WGPUColor blend_color = { 0.f , 0.f , 0.f , 0.f } ;
WGPUColor blend_color = { 0.f , 0.f , 0.f , 0.f } ;
wgpuRenderPassEncoderSetBlendCo lor ( ctx , & blend_color ) ;
wgpuRenderPassEncoderSetBlendCo nstant ( ctx , & blend_color ) ;
}
}
// Render function
// Render function
@ -331,7 +335,11 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
// Create and grow vertex/index buffers if needed
// Create and grow vertex/index buffers if needed
if ( fr - > VertexBuffer = = NULL | | fr - > VertexBufferSize < draw_data - > TotalVtxCount )
if ( fr - > VertexBuffer = = NULL | | fr - > VertexBufferSize < draw_data - > TotalVtxCount )
{
{
SafeRelease ( fr - > VertexBuffer ) ;
if ( fr - > VertexBuffer )
{
wgpuBufferDestroy ( fr - > VertexBuffer ) ;
wgpuBufferRelease ( fr - > VertexBuffer ) ;
}
SafeRelease ( fr - > VertexBufferHost ) ;
SafeRelease ( fr - > VertexBufferHost ) ;
fr - > VertexBufferSize = draw_data - > TotalVtxCount + 5000 ;
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 )
if ( fr - > IndexBuffer = = NULL | | fr - > IndexBufferSize < draw_data - > TotalIdxCount )
{
{
SafeRelease ( fr - > IndexBuffer ) ;
if ( fr - > IndexBuffer )
{
wgpuBufferDestroy ( fr - > IndexBuffer ) ;
wgpuBufferRelease ( fr - > IndexBuffer ) ;
}
SafeRelease ( fr - > IndexBufferHost ) ;
SafeRelease ( fr - > IndexBufferHost ) ;
fr - > IndexBufferSize = draw_data - > TotalIdxCount + 10000 ;
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 vb_write_size = ( ( char * ) vtx_dst - ( char * ) fr - > VertexBufferHost + 3 ) & ~ 3 ;
int64_t ib_write_size = ( ( char * ) idx_dst - ( char * ) fr - > IndexBufferHost + 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 ( g_defaultQueue , fr - > VertexBuffer , 0 , fr - > VertexBufferHost , vb_write_size ) ;
wgpuQueueWriteBuffer ( wgpuDeviceGetDefaultQueue( g_wgpuDevice ) , fr - > IndexBuffer , 0 , fr - > IndexBufferHost , ib_write_size ) ;
wgpuQueueWriteBuffer ( g_defaultQueue , fr - > IndexBuffer , 0 , fr - > IndexBufferHost , ib_write_size ) ;
// Setup desired render state
// Setup desired render state
ImGui_ImplWGPU_SetupRenderState ( draw_data , pass_encoder , fr ) ;
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 ( )
static void ImGui_ImplWGPU_CreateFontsTexture ( )
{
{
// Build texture atlas
// Build texture atlas
@ -466,7 +466,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture()
tex_desc . dimension = WGPUTextureDimension_2D ;
tex_desc . dimension = WGPUTextureDimension_2D ;
tex_desc . size . width = width ;
tex_desc . size . width = width ;
tex_desc . size . height = height ;
tex_desc . size . height = height ;
tex_desc . size . depth = 1 ;
tex_desc . size . depth OrArrayLayers = 1 ;
tex_desc . sampleCount = 1 ;
tex_desc . sampleCount = 1 ;
tex_desc . format = WGPUTextureFormat_RGBA8Unorm ;
tex_desc . format = WGPUTextureFormat_RGBA8Unorm ;
tex_desc . mipLevelCount = 1 ;
tex_desc . mipLevelCount = 1 ;
@ -486,34 +486,17 @@ static void ImGui_ImplWGPU_CreateFontsTexture()
// Upload texture data
// Upload texture data
{
{
WGPUBuffer staging_buffer = ImGui_ImplWGPU_CreateBufferFromData ( g_wgpuDevice , pixels , ( uint32_t ) ( width * size_pp * height ) , WGPUBufferUsage_CopySrc ) ;
WGPUImageCopyTexture dst_view = { } ;
dst_view . texture = g_resources . FontTexture ;
WGPUBufferCopyView bufferCopyView = { } ;
dst_view . mipLevel = 0 ;
bufferCopyView . buffer = staging_buffer ;
dst_view . origin = { 0 , 0 , 0 } ;
bufferCopyView . layout . offset = 0 ;
dst_view . aspect = WGPUTextureAspect_All ;
bufferCopyView . layout . bytesPerRow = width * size_pp ;
WGPUTextureDataLayout layout = { } ;
bufferCopyView . layout . rowsPerImage = height ;
layout . offset = 0 ;
layout . bytesPerRow = width * size_pp ;
WGPUTextureCopyView textureCopyView = { } ;
layout . rowsPerImage = height ;
textureCopyView . texture = g_resources . FontTexture ;
WGPUExtent3D size = { static_cast < uint32_t > ( width ) , static_cast < uint32_t > ( height ) , 1 } ;
textureCopyView . mipLevel = 0 ;
wgpuQueueWriteTexture ( g_defaultQueue , & dst_view , pixels , ( uint32_t ) ( width * size_pp * height ) , & layout , & size ) ;
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 , & copySize ) ;
WGPUCommandBufferDescriptor cmd_buf_desc = { } ;
WGPUCommandBuffer copy = wgpuCommandEncoderFinish ( encoder , & cmd_buf_desc ) ;
WGPUQueue queue = wgpuDeviceGetDefaultQueue ( g_wgpuDevice ) ;
wgpuQueueSubmit ( queue , 1 , & copy ) ;
wgpuCommandEncoderRelease ( encoder ) ;
wgpuBufferRelease ( staging_buffer ) ;
}
}
// Create the associated sampler
// Create the associated sampler
@ -525,9 +508,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture()
sampler_desc . addressModeU = WGPUAddressMode_Repeat ;
sampler_desc . addressModeU = WGPUAddressMode_Repeat ;
sampler_desc . addressModeV = WGPUAddressMode_Repeat ;
sampler_desc . addressModeV = WGPUAddressMode_Repeat ;
sampler_desc . addressModeW = WGPUAddressMode_Repeat ;
sampler_desc . addressModeW = WGPUAddressMode_Repeat ;
# if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
sampler_desc . maxAnisotropy = 1 ;
sampler_desc . maxAnisotropy = 1 ;
# endif
g_resources . Sampler = wgpuDeviceCreateSampler ( g_wgpuDevice , & sampler_desc ) ;
g_resources . Sampler = wgpuDeviceCreateSampler ( g_wgpuDevice , & sampler_desc ) ;
}
}
@ -557,139 +538,82 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
ImGui_ImplWGPU_InvalidateDeviceObjects ( ) ;
ImGui_ImplWGPU_InvalidateDeviceObjects ( ) ;
// Create render pipeline
// Create render pipeline
WGPURenderPipelineDescriptor graphics_pipeline_desc = { } ;
WGPURenderPipelineDescriptor2 graphics_pipeline_desc = { } ;
graphics_pipeline_desc . primitiveTopology = WGPUPrimitiveTopology_TriangleList ;
graphics_pipeline_desc . primitive . topology = WGPUPrimitiveTopology_TriangleList ;
graphics_pipeline_desc . sampleCount = 1 ;
graphics_pipeline_desc . primitive . stripIndexFormat = WGPUIndexFormat_Undefined ;
graphics_pipeline_desc . sampleMask = UINT_MAX ;
graphics_pipeline_desc . primitive . frontFace = WGPUFrontFace_CW ;
graphics_pipeline_desc . primitive . cullMode = WGPUCullMode_None ;
WGPUBindGroupLayoutEntry common_bg_layout_entries [ 2 ] = { } ;
graphics_pipeline_desc . multisample . count = 1 ;
common_bg_layout_entries [ 0 ] . binding = 0 ;
graphics_pipeline_desc . multisample . mask = UINT_MAX ;
common_bg_layout_entries [ 0 ] . visibility = WGPUShaderStage_Vertex ;
graphics_pipeline_desc . multisample . alphaToCoverageEnabled = false ;
# if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
graphics_pipeline_desc . layout = nullptr ; // Use automatic layout generation
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 ) ;
// Create the vertex shader
// Create the vertex shader
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule ( __glsl_shader_vert_spv , sizeof ( __glsl_shader_vert_spv ) / sizeof ( uint32_t ) ) ;
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
// Vertex input configuration
WGPUVertexAttribute Descriptor attribute _binding _desc[ ] =
WGPUVertexAttribute attribute_desc [ ] =
{
{
{ WGPUVertexFormat_Float 2, ( uint64_t ) IM_OFFSETOF ( ImDrawVert , pos ) , 0 } ,
{ WGPUVertexFormat_Float32x2 , ( uint64_t ) IM_OFFSETOF ( ImDrawVert , pos ) , 0 } ,
{ WGPUVertexFormat_Float 2, ( uint64_t ) IM_OFFSETOF ( ImDrawVert , uv ) , 1 } ,
{ WGPUVertexFormat_Float32x2 , ( uint64_t ) IM_OFFSETOF ( ImDrawVert , uv ) , 1 } ,
{ WGPUVertexFormat_U Char4Norm, ( uint64_t ) IM_OFFSETOF ( ImDrawVert , col ) , 2 } ,
{ WGPUVertexFormat_Unorm8x4 , ( uint64_t ) IM_OFFSETOF ( ImDrawVert , col ) , 2 } ,
} ;
} ;
WGPUVertexBufferLayout Descriptor buffer_binding_desc ;
WGPUVertexBufferLayout buffer_layouts [ 1 ] ;
buffer_ binding_desc . arrayStride = sizeof ( ImDrawVert ) ;
buffer_layouts [ 0 ] . arrayStride = sizeof ( ImDrawVert ) ;
buffer_ binding_desc . stepMode = WGPUInputStepMode_Vertex ;
buffer_layouts [ 0 ] . stepMode = WGPUInputStepMode_Vertex ;
buffer_ binding_desc . attributeCount = 3 ;
buffer_layouts [ 0 ] . attributeCount = 3 ;
buffer_ binding_desc . attributes = attribute _binding _desc;
buffer_layouts [ 0 ] . attributes = attribute_desc ;
WGPUVertexStateDescriptor vertex_state_desc = { } ;
graphics_pipeline_desc . vertex . bufferCount = 1 ;
vertex_state_desc . indexFormat = WGPUIndexFormat_Undefined ;
graphics_pipeline_desc . vertex . buffers = buffer_layouts ;
vertex_state_desc . vertexBufferCount = 1 ;
vertex_state_desc . vertexBuffers = & buffer_binding_desc ;
graphics_pipeline_desc . vertexState = & vertex_state_desc ;
// Create the pixel shader
// Create the pixel shader
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModule ( __glsl_shader_frag_spv , sizeof ( __glsl_shader_frag_spv ) / sizeof ( uint32_t ) ) ;
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
// Create the blending setup
WGPUColorStateDescriptor color_state = { } ;
WGPUBlendState blend_state = { } ;
{
blend_state . alpha . operation = WGPUBlendOperation_Add ;
color_state . format = g_renderTargetFormat ;
blend_state . alpha . srcFactor = WGPUBlendFactor_One ;
color_state . alphaBlend . operation = WGPUBlendOperation_Add ;
blend_state . alpha . dstFactor = WGPUBlendFactor_OneMinusSrcAlpha ;
color_state . alphaBlend . srcFactor = WGPUBlendFactor_One ;
blend_state . color . operation = WGPUBlendOperation_Add ;
color_state . alphaBlend . dstFactor = WGPUBlendFactor_OneMinusSrcAlpha ;
blend_state . color . srcFactor = WGPUBlendFactor_SrcAlpha ;
color_state . colorBlend . operation = WGPUBlendOperation_Add ;
blend_state . color . dstFactor = WGPUBlendFactor_OneMinusSrcAlpha ;
color_state . colorBlend . srcFactor = WGPUBlendFactor_SrcAlpha ;
color_state . colorBlend . dstFactor = WGPUBlendFactor_OneMinusSrcAlpha ;
WGPUColorTargetState color_state = { } ;
color_state . writeMask = WGPUColorWriteMask_All ;
color_state . format = g_renderTargetFormat ;
color_state . blend = & blend_state ;
graphics_pipeline_desc . colorStateCount = 1 ;
color_state . writeMask = WGPUColorWriteMask_All ;
graphics_pipeline_desc . colorStates = & color_state ;
graphics_pipeline_desc . alphaToCoverageEnabled = false ;
WGPUFragmentState fragment_state = { } ;
}
fragment_state . module = pixel_shader_desc . module ;
fragment_state . entryPoint = pixel_shader_desc . entryPoint ;
// Create the rasterizer state
fragment_state . targetCount = 1 ;
WGPURasterizationStateDescriptor raster_desc = { } ;
fragment_state . targets = & color_state ;
{
raster_desc . cullMode = WGPUCullMode_None ;
graphics_pipeline_desc . fragment = & fragment_state ;
raster_desc . frontFace = WGPUFrontFace_CW ;
raster_desc . depthBias = 0 ;
raster_desc . depthBiasClamp = 0 ;
raster_desc . depthBiasSlopeScale = 0 ;
graphics_pipeline_desc . rasterizationState = & raster_desc ;
}
// Create depth-stencil State
// Create depth-stencil State
WGPUDepthStencilStateDescriptor depth_desc = { } ;
WGPUDepthStencilState depth_stencil_state = { } ;
{
depth_stencil_state . depthBias = 0 ;
// Configure disabled state
depth_stencil_state . depthBiasClamp = 0 ;
depth_desc . format = WGPUTextureFormat_Undefined ;
depth_stencil_state . depthBiasSlopeScale = 0 ;
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 ;
// No depth buffer corresponds to no configuration
graphics_pipeline_desc . depthStencilState = NULL ;
}
g_pipelineState = wgpuDeviceCreateRenderPipeline ( g_wgpuDevice , & graphics_pipeline_desc ) ;
// Configure disabled depth-stencil state
graphics_pipeline_desc . depthStencil = nullptr ;
g_pipelineState = wgpuDeviceCreateRenderPipeline2 ( g_wgpuDevice , & graphics_pipeline_desc ) ;
ImGui_ImplWGPU_CreateFontsTexture ( ) ;
ImGui_ImplWGPU_CreateFontsTexture ( ) ;
ImGui_ImplWGPU_CreateUniformBuffer ( ) ;
ImGui_ImplWGPU_CreateUniformBuffer ( ) ;
// Create resource bind group
// 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 [ ] =
WGPUBindGroupEntry common_bg_entries [ ] =
{
{
{ 0 , g_resources . Uniforms , 0 , sizeof ( Uniforms ) , 0 , 0 } ,
{ 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 . entryCount = sizeof ( common_bg_entries ) / sizeof ( WGPUBindGroupEntry ) ;
common_bg_descriptor . entries = common_bg_entries ;
common_bg_descriptor . entries = common_bg_entries ;
g_resources . CommonBindGroup = wgpuDeviceCreateBindGroup ( g_wgpuDevice , & common_bg_descriptor ) ;
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 ) ;
WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup ( bg_layouts [ 1 ] , g_resources . FontTextureView ) ;
g_resources . ImageBindGroup = image_bind_group ;
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 ) ;
g_resources . ImageBindGroups . SetVoidPtr ( ImHashData ( & g_resources . FontTextureView , sizeof ( ImTextureID ) ) , image_bind_group ) ;
SafeRelease ( vertex_shader_desc . module ) ;
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.
io . BackendFlags | = ImGuiBackendFlags_RendererHasVtxOffset ; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
g_wgpuDevice = device ;
g_wgpuDevice = device ;
g_defaultQueue = wgpuDeviceGetQueue ( g_wgpuDevice ) ;
g_renderTargetFormat = rt_format ;
g_renderTargetFormat = rt_format ;
g_pFrameResources = new FrameResources [ num_frames_in_flight ] ;
g_pFrameResources = new FrameResources [ num_frames_in_flight ] ;
g_numFramesInFlight = 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 . Sampler = NULL ;
g_resources . Uniforms = NULL ;
g_resources . Uniforms = NULL ;
g_resources . CommonBindGroup = NULL ;
g_resources . CommonBindGroup = NULL ;
g_resources . ImageBindGroupLayout = NULL ;
g_resources . ImageBindGroups . Data . reserve ( 100 ) ;
g_resources . ImageBindGroups . Data . reserve ( 100 ) ;
g_resources . ImageBindGroup = NULL ;
g_resources . ImageBindGroup = NULL ;
g_resources . ImageBindGroupLayout = NULL ;
// Create buffers with a default size (they will later be grown as needed)
// Create buffers with a default size (they will later be grown as needed)
for ( int i = 0 ; i < num_frames_in_flight ; i + + )
for ( int i = 0 ; i < num_frames_in_flight ; i + + )
@ -771,6 +696,7 @@ void ImGui_ImplWGPU_Shutdown()
ImGui_ImplWGPU_InvalidateDeviceObjects ( ) ;
ImGui_ImplWGPU_InvalidateDeviceObjects ( ) ;
delete [ ] g_pFrameResources ;
delete [ ] g_pFrameResources ;
g_pFrameResources = NULL ;
g_pFrameResources = NULL ;
wgpuQueueRelease ( g_defaultQueue ) ;
g_wgpuDevice = NULL ;
g_wgpuDevice = NULL ;
g_numFramesInFlight = 0 ;
g_numFramesInFlight = 0 ;
g_frameIndex = UINT_MAX ;
g_frameIndex = UINT_MAX ;