ImGui :: #import "ImGui"; // Shaders IMGUI_VERTEX_SHADER :: #string END cbuffer vertexBuffer : register(b0) { float4x4 ProjectionMatrix; }; struct VS_INPUT { float2 pos : POSITION; float4 col : COLOR; float2 uv : TEXCOORD0; }; struct PS_INPUT { float4 pos : SV_POSITION; float4 col : COLOR; float2 uv : TEXCOORD0; }; PS_INPUT main_vs(float2 pos : POSITION, float4 col : COLOR, float2 uv : TEXCOORD0) { PS_INPUT output; output.pos = mul(float4(pos.xy, 0.f, 1.f), ProjectionMatrix); output.col = col; output.uv = uv; return output; } END IMGUI_PIXEL_SHADER :: #string END struct PS_INPUT { float4 pos : SV_POSITION; float4 col : COLOR0; float2 uv : TEXCOORD0; }; sampler sampler0; Texture2D texture0; float4 main_ps(PS_INPUT input) : SV_Target { float4 out_col = input.col * texture0.Sample(sampler0, input.uv); return out_col; } END // Impl procedures imgui_impldx11_new_frame :: () { bd := imgui_impldx11_get_backend_data(); assert(bd != null && "Did you call ImGui_ImplDX11_Init()?"); if !bd.font_sampler { imgui_impldx11_create_device_objects(); } } imgui_impldx11_render_draw_data :: (draw_data: *ImGui.ImDrawData) { // Avoid rendering when minimized if draw_data.DisplaySize.x <= 0.0 || draw_data.DisplaySize.y <= 0.0 return; bd := imgui_impldx11_get_backend_data(); ctx := bd.d3d_context; // Create and grow vertex/index buffers if needed if !bd.vb || bd.vertex_buffer_size < xx draw_data.TotalVtxCount { if bd.vb { IUnknown_Release(bd.vb); bd.vb = null; } bd.vertex_buffer_size = cast(u32)draw_data.TotalVtxCount + 5000; desc: D3D11_BUFFER_DESC; memset(*desc, 0, size_of(D3D11_BUFFER_DESC)); desc.Usage = .D3D11_USAGE_DYNAMIC; desc.ByteWidth = bd.vertex_buffer_size * size_of(ImGui.ImDrawVert); desc.BindFlags = .D3D11_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = .D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; if ID3D11Device_CreateBuffer(bd.d3d_device, *desc, null, *bd.vb) < 0 return; } if !bd.ib || bd.index_buffer_size < xx draw_data.TotalIdxCount { if bd.ib != null { IUnknown_Release(bd.ib); bd.ib = null; } bd.index_buffer_size = cast(u32)draw_data.TotalIdxCount + 10000; desc: D3D11_BUFFER_DESC; memset(*desc, 0, size_of(D3D11_BUFFER_DESC)); desc.Usage = .D3D11_USAGE_DYNAMIC; desc.ByteWidth = bd.index_buffer_size * size_of(ImGui.ImDrawIdx); desc.BindFlags = .D3D11_BIND_INDEX_BUFFER; desc.CPUAccessFlags = .D3D11_CPU_ACCESS_WRITE; if ID3D11Device_CreateBuffer(bd.d3d_device, *desc, null, *bd.ib) < 0 return; } // Upload vertex/index data into a single contiguous GPU buffer vtx_resource: D3D11_MAPPED_SUBRESOURCE; idx_resource: D3D11_MAPPED_SUBRESOURCE; if ID3D11DeviceContext_Map(ctx, bd.vb, 0, .D3D11_MAP_WRITE_DISCARD, 0, *vtx_resource) != S_OK return; if ID3D11DeviceContext_Map(ctx, bd.ib, 0, .D3D11_MAP_WRITE_DISCARD, 0, *idx_resource) != S_OK return; vtx_dst := cast(*ImGui.ImDrawVert)vtx_resource.pData; idx_dst := cast(*ImGui.ImDrawIdx)idx_resource.pData; for n: 0..draw_data.CmdListsCount - 1 { cmd_list := draw_data.CmdLists[n]; memcpy(vtx_dst, cmd_list.VtxBuffer.Data, cmd_list.VtxBuffer.Size * size_of(ImGui.ImDrawVert)); memcpy(idx_dst, cmd_list.IdxBuffer.Data, cmd_list.IdxBuffer.Size * size_of(ImGui.ImDrawIdx)); vtx_dst += cmd_list.VtxBuffer.Size; idx_dst += cmd_list.IdxBuffer.Size; } ID3D11DeviceContext_Unmap(ctx, bd.vb, 0); ID3D11DeviceContext_Unmap(ctx, bd.ib, 0); // 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). DisplayPos is (0,0) for single viewport apps. { mapped_resource: D3D11_MAPPED_SUBRESOURCE; if ID3D11DeviceContext_Map(ctx, bd.vertex_constant_buffer, 0, .D3D11_MAP_WRITE_DISCARD, 0, *mapped_resource) != S_OK return; constant_buffer := cast(*Matrix4)mapped_resource.pData; L := draw_data.DisplayPos.x; R := draw_data.DisplayPos.x + draw_data.DisplaySize.x; T := draw_data.DisplayPos.y; B := draw_data.DisplayPos.y + draw_data.DisplaySize.y; m: Matrix4; m._11 = 2.0 / (R-L); m._12 = 0.0; m._13 = 0.0; m._14 = (R+L)/(L-R); m._21 = 0.0; m._22 = 2.0 / (T-B); m._23 = 0.0; m._24 = (T+B)/(B-T); m._31 = 0.0; m._32 = 0.0; m._33 = 0.5; m._34 = 0.5; m._41 = 0.0; m._42 = 0.0; m._43 = 0.0; m._44 = 1.0; memcpy(constant_buffer, *m, size_of(Matrix4)); ID3D11DeviceContext_Unmap(ctx, bd.vertex_constant_buffer, 0); } // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) BACKUP_DX11_STATE :: struct { scissor_rects_count: u32; viewports_count: u32; scissor_rects: [D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE] D3D11_RECT; viewports: [D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE] D3D11_VIEWPORT; rs: *ID3D11RasterizerState; blend_state: *ID3D11BlendState; blend_factor: [4] float; sample_mask: u32; stencil_ref: u32; depth_stencil_state: *ID3D11DepthStencilState; ps_shader_resource: *ID3D11ShaderResourceView; ps_sampler: *ID3D11SamplerState; ps: *ID3D11PixelShader; vs: *ID3D11VertexShader; gs: *ID3D11GeometryShader; ps_instances_count: u32; vs_instances_count: u32; gs_instances_count: u32; ps_instances: [256]*ID3D11ClassInstance; vs_instances: [256]*ID3D11ClassInstance; gs_instances: [256]*ID3D11ClassInstance; primitive_topology: D3D11_PRIMITIVE_TOPOLOGY; index_buffer: *ID3D11Buffer; vertex_buffer: *ID3D11Buffer; vs_constant_buffer: *ID3D11Buffer; index_buffer_offset: u32; vertex_buffer_stride: u32; vertex_buffer_offset: u32; index_buffer_format: DXGI_FORMAT; input_layout: *ID3D11InputLayout; }; old: BACKUP_DX11_STATE; old.scissor_rects_count = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; old.viewports_count = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; ID3D11DeviceContext_RSGetScissorRects(ctx, *old.scissor_rects_count, old.scissor_rects.data); ID3D11DeviceContext_RSGetViewports(ctx, *old.viewports_count, old.viewports.data); ID3D11DeviceContext_RSGetState(ctx, *old.rs); ID3D11DeviceContext_OMGetBlendState(ctx, *old.blend_state, *old.blend_factor, *old.sample_mask); ID3D11DeviceContext_OMGetDepthStencilState(ctx, *old.depth_stencil_state, *old.stencil_ref); ID3D11DeviceContext_PSGetShaderResources(ctx, 0, 1, *old.ps_shader_resource); ID3D11DeviceContext_PSGetSamplers(ctx, 0, 1, *old.ps_sampler); old.ps_instances_count = 256; old.vs_instances_count = 256; old.gs_instances_count = 256; ID3D11DeviceContext_PSGetShader(ctx, *old.ps, old.ps_instances.data, *old.ps_instances_count); ID3D11DeviceContext_VSGetShader(ctx, *old.vs, old.vs_instances.data, *old.vs_instances_count); ID3D11DeviceContext_VSGetConstantBuffers(ctx, 0, 1, *old.vs_constant_buffer); ID3D11DeviceContext_GSGetShader(ctx, *old.gs, old.gs_instances.data, *old.gs_instances_count); ID3D11DeviceContext_IAGetPrimitiveTopology(ctx, *old.primitive_topology); ID3D11DeviceContext_IAGetIndexBuffer(ctx, *old.index_buffer, *old.index_buffer_format, *old.index_buffer_offset); ID3D11DeviceContext_IAGetVertexBuffers(ctx, 0, 1, *old.vertex_buffer, *old.vertex_buffer_stride, *old.vertex_buffer_offset); ID3D11DeviceContext_IAGetInputLayout(ctx, *old.input_layout); // Setup desired DX state imgui_impldx11_setup_render_state(draw_data, ctx); // Render command lists // (Because we merged all buffers into a single one, we maintain our own offset into them) global_idx_offset : u32 = 0; global_vtx_offset : s32 = 0; clip_off := draw_data.DisplayPos; for n: 0..draw_data.CmdListsCount-1 { cmd_list := draw_data.CmdLists[n]; for cmd_i: 0..cmd_list.CmdBuffer.Size-1 { pcmd := *cmd_list.CmdBuffer.Data[cmd_i]; if pcmd.UserCallback != null { // @Incomplete // 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 == ImGui.ImDrawCallback_ResetRenderState { // imgui_impdx11_setup_render_state(draw_data, ctx); //} else { pcmd.UserCallback(cmd_list, pcmd); //} } else { // Project scissor/clipping rectangles into framebuffer space clip_min : ImGui.ImVec2; clip_min.x = pcmd.ClipRect.x - clip_off.x; clip_min.y = pcmd.ClipRect.y - clip_off.y; clip_max : ImGui.ImVec2; clip_max.x = pcmd.ClipRect.z - clip_off.x; clip_max.y = pcmd.ClipRect.w - clip_off.y; if clip_max.x <= clip_min.x || clip_max.y <= clip_min.y continue; // Apply scissor/clipping rectangle r : D3D11_RECT; r.left = xx clip_min.x; r.top = xx clip_min.y; r.right = xx clip_max.x; r.bottom = xx clip_max.y; ID3D11DeviceContext_RSSetScissorRects(ctx, 1, *r); // Bind texture, Draw texture_srv := cast(*ID3D11ShaderResourceView)pcmd.TextureId; ID3D11DeviceContext_PSSetShaderResources(ctx, 0, 1, *texture_srv); ID3D11DeviceContext_DrawIndexed(ctx, pcmd.ElemCount, pcmd.IdxOffset + global_idx_offset, xx pcmd.VtxOffset + global_vtx_offset); } } global_idx_offset += xx cmd_list.IdxBuffer.Size; global_vtx_offset += xx cmd_list.VtxBuffer.Size; } // Restore modified DX state ID3D11DeviceContext_RSSetScissorRects(ctx, old.scissor_rects_count, old.scissor_rects.data); ID3D11DeviceContext_RSSetViewports(ctx, old.viewports_count, old.viewports.data); ID3D11DeviceContext_RSSetState(ctx, old.rs); if (old.rs != null) IUnknown_Release(old.rs); ID3D11DeviceContext_OMSetBlendState(ctx, old.blend_state, *old.blend_factor, old.sample_mask); if old.blend_state != null IUnknown_Release(old.blend_state); ID3D11DeviceContext_OMSetDepthStencilState(ctx, old.depth_stencil_state, old.stencil_ref); if old.depth_stencil_state != null IUnknown_Release(old.depth_stencil_state); ID3D11DeviceContext_PSSetShaderResources(ctx, 0, 1, *old.ps_shader_resource); if old.ps_shader_resource != null IUnknown_Release(old.ps_shader_resource); ID3D11DeviceContext_PSSetSamplers(ctx, 0, 1, *old.ps_sampler); if old.ps_sampler != null IUnknown_Release(old.ps_sampler); ID3D11DeviceContext_PSSetShader(ctx, old.ps, old.ps_instances.data, old.ps_instances_count); if old.ps IUnknown_Release(old.ps); { i := 0; while i < old.ps_instances_count { defer i += 1; if old.ps_instances[i] != null IUnknown_Release(old.ps_instances[i]); } } ID3D11DeviceContext_VSSetShader(ctx, old.vs, old.vs_instances.data, old.vs_instances_count); if old.vs != null IUnknown_Release(old.vs); ID3D11DeviceContext_VSSetConstantBuffers(ctx, 0, 1, *old.vs_constant_buffer); if old.vs_constant_buffer != null IUnknown_Release(old.vs_constant_buffer); ID3D11DeviceContext_GSSetShader(ctx, old.gs, old.gs_instances.data, old.gs_instances_count); if old.gs != null IUnknown_Release(old.gs); { i := 0; while i < old.vs_instances_count { defer i += 1; if old.vs_instances[i] != null IUnknown_Release(old.vs_instances[i]); } } ID3D11DeviceContext_IASetPrimitiveTopology(ctx, old.primitive_topology); ID3D11DeviceContext_IASetIndexBuffer(ctx, old.index_buffer, old.index_buffer_format, old.index_buffer_offset); if old.index_buffer != null IUnknown_Release(old.index_buffer); ID3D11DeviceContext_IASetVertexBuffers(ctx, 0, 1, *old.vertex_buffer, *old.vertex_buffer_stride, *old.vertex_buffer_offset); if old.vertex_buffer != null IUnknown_Release(old.vertex_buffer); ID3D11DeviceContext_IASetInputLayout(ctx, old.input_layout); if old.input_layout != null IUnknown_Release(old.input_layout); } imgui_impldx11_setup_render_state :: (draw_data: *ImGui.ImDrawData, ctx: *ID3D11DeviceContext) { bd := imgui_impldx11_get_backend_data(); vp: D3D11_VIEWPORT; memset(*vp, 0, size_of(D3D11_VIEWPORT)); vp.Width = draw_data.DisplaySize.x; vp.Height = draw_data.DisplaySize.y; vp.MinDepth = 0.0; vp.MaxDepth = 1.0; vp.TopLeftX = 0; vp.TopLeftY = 0; ID3D11DeviceContext_RSSetViewports(ctx, 1, *vp); // Setup shader and vertex buffers stride: u32 = xx size_of(ImGui.ImDrawVert); offset: u32 = 0; ID3D11DeviceContext_IASetInputLayout(ctx, bd.input_layout); ID3D11DeviceContext_IASetVertexBuffers(ctx, 0, 1, *bd.vb, *stride, *offset); format : DXGI_FORMAT; if size_of(ImGui.ImDrawIdx) == 2 { format = .DXGI_FORMAT_R16_UINT; } else { format = .DXGI_FORMAT_R32_UINT; } ID3D11DeviceContext_IASetIndexBuffer(ctx, bd.ib, format, 0); ID3D11DeviceContext_IASetPrimitiveTopology(ctx, .D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ID3D11DeviceContext_VSSetShader(ctx, bd.vertex_shader, null, 0); ID3D11DeviceContext_VSSetConstantBuffers(ctx, 0, 1, *bd.vertex_constant_buffer); ID3D11DeviceContext_PSSetShader(ctx, bd.pixel_shader, null, 0); ID3D11DeviceContext_PSSetSamplers(ctx, 0, 1, *bd.font_sampler); ID3D11DeviceContext_GSSetShader(ctx, null, null, 0); ID3D11DeviceContext_HSSetShader(ctx, null, null, 0); // In theory we should backup and restore this as well.. very infrequently used.. ID3D11DeviceContext_DSSetShader(ctx, null, null, 0); // In theory we should backup and restore this as well.. very infrequently used.. ID3D11DeviceContext_CSSetShader(ctx, null, null, 0); // In theory we should backup and restore this as well.. very infrequently used.. // Setup blend state factor : [4] float; ID3D11DeviceContext_OMSetBlendState(ctx, bd.blend_state, *factor, 0xffffffff); ID3D11DeviceContext_OMSetDepthStencilState(ctx, bd.depth_stencil_state, 0); ID3D11DeviceContext_RSSetState(ctx, bd.rasterizer_state); } imgui_impldx11_invalidate_device_objects :: () { bd := imgui_impldx11_get_backend_data(); if bd.d3d_device == null return; if bd.font_sampler { IUnknown_Release(bd.font_sampler); bd.font_sampler = null; } if bd.font_texture_view { IUnknown_Release(bd.font_texture_view); bd.font_texture_view = null; ImGui.GetIO().Fonts.TexID = null; } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well. if bd.ib { IUnknown_Release(bd.ib); bd.ib = null; } if bd.vb { IUnknown_Release(bd.vb); bd.vb = null; } if bd.blend_state { IUnknown_Release(bd.blend_state); bd.blend_state = null; } if bd.depth_stencil_state { IUnknown_Release(bd.depth_stencil_state); bd.depth_stencil_state = null; } if bd.rasterizer_state { IUnknown_Release(bd.rasterizer_state); bd.rasterizer_state = null; } if bd.pixel_shader { IUnknown_Release(bd.pixel_shader); bd.pixel_shader = null; } if bd.vertex_constant_buffer { IUnknown_Release(bd.vertex_constant_buffer); bd.vertex_constant_buffer = null; } if bd.input_layout { IUnknown_Release(bd.input_layout); bd.input_layout = null; } if bd.vertex_shader { IUnknown_Release(bd.vertex_shader); bd.vertex_shader = null; } } imgui_impldx11_create_device_objects :: () -> bool { bd := imgui_impldx11_get_backend_data(); if bd.font_sampler { imgui_impldx11_invalidate_device_objects(); } // Create the vertex shader vertex_shader_blob, blob, result := compile_shader("imgui_vertex_shader", IMGUI_VERTEX_SHADER, "main_vs", "vs_4_0", string.[]); if FAILED(result) { return false; } if ID3D11Device_CreateVertexShader(bd.d3d_device, vertex_shader_blob.data, cast(u64)vertex_shader_blob.count, null, *bd.vertex_shader) != S_OK { free(vertex_shader_blob); return false; } { // Create the input layout layout : [3] Vertex_Data_Info; layout[0] = .{0,.POSITION2D, 0}; layout[1] = .{0,.TEXCOORD0, 0}; layout[2] = .{0,.COLOR_WITH_ALPHA8, 0}; backend_shader : Backend_Shader; backend_shader.bytecode = vertex_shader_blob; backend_shader.vertex_shader = bd.vertex_shader; bd.input_layout = create_backend_input_layout(engine.renderer.backend, layout, backend_shader); free(vertex_shader_blob); } // Create the constant buffer { desc: D3D11_BUFFER_DESC; desc.ByteWidth = size_of(Matrix4); desc.Usage = .D3D11_USAGE_DYNAMIC; desc.BindFlags = .CONSTANT_BUFFER; desc.CPUAccessFlags = .WRITE; desc.MiscFlags = 0; hr := ID3D11Device_CreateBuffer(bd.d3d_device, *desc, null, *bd.vertex_constant_buffer); if FAILED(hr) { return false; } } // Create the pixel shader { pixel_shader_blob, blob, result := compile_shader("imgui_pixel_shader", IMGUI_PIXEL_SHADER, "main_ps", "ps_4_0", string.[]); if FAILED(result) { return false; } if (ID3D11Device_CreatePixelShader(bd.d3d_device, pixel_shader_blob.data, cast(u64)pixel_shader_blob.count, null, *bd.pixel_shader) != S_OK) { free(pixel_shader_blob); return false; } free(pixel_shader_blob); } // Create the blending setup { desc: D3D11_BLEND_DESC; desc.AlphaToCoverageEnable = .FALSE; desc.RenderTarget[0].BlendEnable = .TRUE; desc.RenderTarget[0].SrcBlend = .D3D11_BLEND_SRC_ALPHA; desc.RenderTarget[0].DestBlend = .D3D11_BLEND_INV_SRC_ALPHA; desc.RenderTarget[0].BlendOp = .D3D11_BLEND_OP_ADD; desc.RenderTarget[0].SrcBlendAlpha = .D3D11_BLEND_ONE; desc.RenderTarget[0].DestBlendAlpha = .D3D11_BLEND_INV_SRC_ALPHA; desc.RenderTarget[0].BlendOpAlpha = .D3D11_BLEND_OP_ADD; desc.RenderTarget[0].RenderTargetWriteMask = xx D3D11_COLOR_WRITE_ENABLE.ALL; ID3D11Device_CreateBlendState(bd.d3d_device, *desc, *bd.blend_state); } // Create the rasterizer state { desc: D3D11_RASTERIZER_DESC; desc.FillMode = .D3D11_FILL_SOLID; desc.CullMode = .D3D11_CULL_NONE; desc.ScissorEnable = .TRUE; desc.DepthClipEnable = .TRUE; //desc.FrontCounterClockwise = .TRUE; ID3D11Device_CreateRasterizerState(bd.d3d_device, *desc, *bd.rasterizer_state); } // Create depth-stencil State { desc: D3D11_DEPTH_STENCIL_DESC; desc.DepthEnable = .FALSE; desc.DepthWriteMask = .D3D11_DEPTH_WRITE_MASK_ALL; desc.DepthFunc = .D3D11_COMPARISON_ALWAYS; desc.StencilEnable = .FALSE; desc.FrontFace.StencilFailOp = .D3D11_STENCIL_OP_KEEP; desc.FrontFace.StencilDepthFailOp = .D3D11_STENCIL_OP_KEEP; desc.FrontFace.StencilPassOp = .D3D11_STENCIL_OP_KEEP; desc.FrontFace.StencilFunc = .D3D11_COMPARISON_ALWAYS; desc.BackFace = desc.FrontFace; ID3D11Device_CreateDepthStencilState(bd.d3d_device, *desc, *bd.depth_stencil_state); } imgui_impld11_create_fonts_texture(); return true; } imgui_impld11_create_fonts_texture :: () { // Build texture atlas io := ImGui.GetIO(); bd := imgui_impldx11_get_backend_data(); pixels: *u8; width: s32; height: s32; ImGui.ImFontAtlas.GetTexDataAsRGBA32(io.Fonts, *pixels, *width, *height); // Upload texture to graphics system { desc: D3D11_TEXTURE2D_DESC; desc.Width = xx width; desc.Height = xx height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = .DXGI_FORMAT_R8G8B8A8_UNORM; desc.SampleDesc.Count = 1; desc.Usage = .D3D11_USAGE_DEFAULT; desc.BindFlags = .D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; texture: *ID3D11Texture2D; sub_resource: D3D11_SUBRESOURCE_DATA; sub_resource.pSysMem = pixels; sub_resource.SysMemPitch = desc.Width * 4; sub_resource.SysMemSlicePitch = 0; ID3D11Device_CreateTexture2D(bd.d3d_device, *desc, *sub_resource, *texture); assert(texture != null); // Create texture view srv_desc: D3D11_SHADER_RESOURCE_VIEW_DESC; srv_desc.Format = .DXGI_FORMAT_R8G8B8A8_UNORM; srv_desc.ViewDimension = .D3D11_SRV_DIMENSION_TEXTURE2D; srv_desc.Texture2D.MipLevels = xx desc.MipLevels; srv_desc.Texture2D.MostDetailedMip = 0; ID3D11Device_CreateShaderResourceView(bd.d3d_device, texture, *srv_desc, *bd.font_texture_view); IUnknown_Release(texture); } // Store our identifier io.Fonts.TexID = cast(ImGui.ImTextureID)bd.font_texture_view; // Create texture sampler // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) { desc: D3D11_SAMPLER_DESC; desc.Filter = .D3D11_FILTER_MIN_MAG_MIP_LINEAR; desc.AddressU = .D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = .D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = .D3D11_TEXTURE_ADDRESS_WRAP; desc.MipLODBias = 0.0; desc.ComparisonFunc = .D3D11_COMPARISON_ALWAYS; desc.MinLOD = 0.0; desc.MaxLOD = 0.0; ID3D11Device_CreateSamplerState(bd.d3d_device, *desc, *bd.font_sampler); } } ImGui_ImplDX11_Data :: struct { d3d_device: *ID3D11Device; d3d_context: *ID3D11DeviceContext; factor: *IDXGIFactory1; vb: *ID3D11Buffer; ib: *ID3D11Buffer; vertex_shader: *ID3D11VertexShader; input_layout: *ID3D11InputLayout; vertex_constant_buffer: *ID3D11Buffer; pixel_shader: *ID3D11PixelShader; font_sampler: *ID3D11SamplerState; font_texture_view: *ID3D11ShaderResourceView; rasterizer_state: *ID3D11RasterizerState; blend_state: *ID3D11BlendState; depth_stencil_state: *ID3D11DepthStencilState; vertex_buffer_size: u32 = 5000; index_buffer_size: u32 = 10000; }; // ImGui imgui_impldx11_init :: (device: *ID3D11Device, device_context: *ID3D11DeviceContext) -> bool { io := ImGui.GetIO(); assert(io.BackendRendererUserData == null && "Already initialized a renderer backend!"); // Setup backend capabilities flags bd := New(ImGui_ImplDX11_Data); io.BackendRendererUserData = xx bd; io.BackendRendererName = copy_string("imgui_impl_dx11").data; io.BackendFlags_ |= .ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. bd.d3d_device = device; bd.d3d_context = device_context; return true; } imgui_impldx11_get_backend_data :: () -> *ImGui_ImplDX11_Data { ctx := ImGui.GetCurrentContext(); if ctx != null { return cast(*ImGui_ImplDX11_Data)ImGui.GetIO().BackendRendererUserData; } return null; } imgui_impldx11_shutdown :: () { bd := imgui_impldx11_get_backend_data(); assert(bd != null && "No renderer backend to shutdown, or already shutdown?"); io := ImGui.GetIO(); imgui_impldx11_invalidate_device_objects(); io.BackendRendererName = null; io.BackendRendererUserData = null; free(bd); // @Incomplete }