diff --git a/3rdparty/imgui/CMakeLists.txt b/3rdparty/imgui/CMakeLists.txt
index 49dc43dacd..00099b2e9e 100644
--- a/3rdparty/imgui/CMakeLists.txt
+++ b/3rdparty/imgui/CMakeLists.txt
@@ -14,19 +14,7 @@ add_library(imgui
target_include_directories(imgui PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/imgui" "${CMAKE_CURRENT_SOURCE_DIR}/include")
-if(USE_OPENGL)
- target_sources(imgui PRIVATE
- include/imgui_impl_opengl3.h
- src/imgui_impl_opengl3.cpp
- )
- target_link_libraries(imgui glad)
-endif()
+# Needed for macOS compile.
+set_property(TARGET imgui PROPERTY CXX_STANDARD 17)
+set_property(TARGET imgui PROPERTY CXX_STANDARD_REQUIRED ON)
-if(WIN32)
- target_sources(imgui PRIVATE
- include/imgui_impl_dx11.h
- include/imgui_impl_dx12.h
- src/imgui_impl_dx11.cpp
- src/imgui_impl_dx12.cpp
- )
-endif()
diff --git a/3rdparty/imgui/imgui b/3rdparty/imgui/imgui
index 89a28209e8..60bea052a9 160000
--- a/3rdparty/imgui/imgui
+++ b/3rdparty/imgui/imgui
@@ -1 +1 @@
-Subproject commit 89a28209e89f69a5eda560d2ef9c13915c95616a
+Subproject commit 60bea052a92cbb4a93b221002fdf04f0da3698e1
diff --git a/3rdparty/imgui/imgui.vcxproj b/3rdparty/imgui/imgui.vcxproj
index 3bcccf53b8..0b7aa56aed 100644
--- a/3rdparty/imgui/imgui.vcxproj
+++ b/3rdparty/imgui/imgui.vcxproj
@@ -47,9 +47,6 @@
-
-
-
@@ -57,9 +54,6 @@
-
-
-
diff --git a/3rdparty/imgui/imgui.vcxproj.filters b/3rdparty/imgui/imgui.vcxproj.filters
index 758a5f768c..76a5974718 100644
--- a/3rdparty/imgui/imgui.vcxproj.filters
+++ b/3rdparty/imgui/imgui.vcxproj.filters
@@ -7,9 +7,6 @@
-
-
-
@@ -17,8 +14,5 @@
-
-
-
\ No newline at end of file
diff --git a/3rdparty/imgui/include/imgui_impl_dx11.h b/3rdparty/imgui/include/imgui_impl_dx11.h
deleted file mode 100644
index 757edde7dc..0000000000
--- a/3rdparty/imgui/include/imgui_impl_dx11.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// dear imgui: Renderer for DirectX11
-// This needs to be used along with a Platform Binding (e.g. Win32)
-
-// Implemented features:
-// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
-// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
-
-// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
-// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
-// https://github.com/ocornut/imgui
-
-#pragma once
-
-struct ID3D11Device;
-struct ID3D11DeviceContext;
-
-IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
-IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
-IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
-
-// Use if you want to reset your rendering device without losing ImGui state.
-IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
-IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
-IMGUI_IMPL_API void ImGui_ImplDX11_CreateFontsTexture();
diff --git a/3rdparty/imgui/include/imgui_impl_dx12.h b/3rdparty/imgui/include/imgui_impl_dx12.h
deleted file mode 100644
index 899c822924..0000000000
--- a/3rdparty/imgui/include/imgui_impl_dx12.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// dear imgui: Renderer Backend for DirectX12
-// This needs to be used along with a Platform Backend (e.g. Win32)
-
-// Implemented features:
-// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
-// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
-
-// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
-// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
-// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file.
-
-// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
-// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
-// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
-// Read online: https://github.com/ocornut/imgui/tree/master/docs
-
-#pragma once
-#include "imgui.h" // IMGUI_IMPL_API
-#include // DXGI_FORMAT
-
-struct ID3D12Device;
-struct ID3D12DescriptorHeap;
-struct ID3D12GraphicsCommandList;
-struct D3D12_CPU_DESCRIPTOR_HANDLE;
-struct D3D12_GPU_DESCRIPTOR_HANDLE;
-
-// cmd_list is the command list that the implementation will use to render imgui draw lists.
-// Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate
-// render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle.
-// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture.
-IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
- D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle);
-IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown();
-IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame();
-IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list);
-
-// Use if you want to reset your rendering device without losing Dear ImGui state.
-IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects();
-IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects();
diff --git a/3rdparty/imgui/include/imgui_impl_opengl3.h b/3rdparty/imgui/include/imgui_impl_opengl3.h
deleted file mode 100644
index f4a0c33b39..0000000000
--- a/3rdparty/imgui/include/imgui_impl_opengl3.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline
-// - Desktop GL: 2.x 3.x 4.x
-// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
-// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
-
-// Implemented features:
-// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
-// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
-// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices.
-
-// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
-// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
-// https://github.com/ocornut/imgui
-
-// About Desktop OpenGL function loaders:
-// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
-// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
-// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
-
-// About GLSL version:
-// The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string.
-// On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es"
-// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
-
-#pragma once
-
-// Backend API
-IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL);
-IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown();
-IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
-
-// (Optional) Called by Init/NewFrame/Shutdown
-IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture();
-IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture();
-IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
-IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
diff --git a/3rdparty/imgui/src/imgui_impl_dx11.cpp b/3rdparty/imgui/src/imgui_impl_dx11.cpp
deleted file mode 100644
index e42e3005f2..0000000000
--- a/3rdparty/imgui/src/imgui_impl_dx11.cpp
+++ /dev/null
@@ -1,503 +0,0 @@
-// dear imgui: Renderer for DirectX11
-// This needs to be used along with a Platform Binding (e.g. Win32)
-
-// Implemented features:
-// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
-// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
-
-// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
-// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp
-// https://github.com/ocornut/imgui
-
-// CHANGELOG
-// (minor and older changes stripped away, please see git history for details)
-// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
-// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
-// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
-// 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility.
-// 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions.
-// 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example.
-// 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
-// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself.
-// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
-// 2016-05-07: DirectX11: Disabling depth-write.
-
-#include "imgui.h"
-#include "imgui_impl_dx11.h"
-
-// DirectX
-#include
-#include
-#include
-#ifdef _MSC_VER
-#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
-#endif
-
-// DirectX data
-static ID3D11Device* g_pd3dDevice = NULL;
-static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
-static ID3D11Buffer* g_pVB = NULL;
-static ID3D11Buffer* g_pIB = NULL;
-static ID3D10Blob* g_pVertexShaderBlob = NULL;
-static ID3D11VertexShader* g_pVertexShader = NULL;
-static ID3D11InputLayout* g_pInputLayout = NULL;
-static ID3D11Buffer* g_pVertexConstantBuffer = NULL;
-static ID3D10Blob* g_pPixelShaderBlob = NULL;
-static ID3D11PixelShader* g_pPixelShader = NULL;
-static ID3D11SamplerState* g_pFontSampler = NULL;
-static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
-static ID3D11RasterizerState* g_pRasterizerState = NULL;
-static ID3D11BlendState* g_pBlendState = NULL;
-static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
-static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
-
-struct VERTEX_CONSTANT_BUFFER
-{
- float mvp[4][4];
-};
-
-// 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_ImplDX11_RenderDrawData(ImDrawData* draw_data)
-{
- // Avoid rendering when minimized
- if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
- return;
-
- ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
-
- // Create and grow vertex/index buffers if needed
- if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
- {
- if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
- g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
- D3D11_BUFFER_DESC desc;
- memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
- desc.Usage = D3D11_USAGE_DYNAMIC;
- desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
- desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- desc.MiscFlags = 0;
- if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0)
- return;
- }
- if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
- {
- if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
- g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
- D3D11_BUFFER_DESC desc;
- memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
- desc.Usage = D3D11_USAGE_DYNAMIC;
- desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
- desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)
- return;
- }
-
- // Upload vertex/index data into a single contiguous GPU buffer
- D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
- if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
- return;
- if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
- return;
- ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
- ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
- for (int n = 0; n < draw_data->CmdListsCount; n++)
- {
- const ImDrawList* cmd_list = draw_data->CmdLists[n];
- memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
- memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
- vtx_dst += cmd_list->VtxBuffer.Size;
- idx_dst += cmd_list->IdxBuffer.Size;
- }
- ctx->Unmap(g_pVB, 0);
- ctx->Unmap(g_pIB, 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). DisplayMin is (0,0) for single viewport apps.
- {
- D3D11_MAPPED_SUBRESOURCE mapped_resource;
- if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
- return;
- VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
- 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 },
- };
- memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
- ctx->Unmap(g_pVertexConstantBuffer, 0);
- }
-
- // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
- struct BACKUP_DX11_STATE
- {
- UINT ScissorRectsCount, ViewportsCount;
- D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
- D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
- ID3D11RasterizerState* RS;
- ID3D11BlendState* BlendState;
- FLOAT BlendFactor[4];
- UINT SampleMask;
- UINT StencilRef;
- ID3D11DepthStencilState* DepthStencilState;
- ID3D11ShaderResourceView* PSShaderResource;
- ID3D11SamplerState* PSSampler;
- ID3D11PixelShader* PS;
- ID3D11VertexShader* VS;
- UINT PSInstancesCount, VSInstancesCount;
- ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
- D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
- ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
- UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
- DXGI_FORMAT IndexBufferFormat;
- ID3D11InputLayout* InputLayout;
- };
- BACKUP_DX11_STATE old;
- old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
- ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
- ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
- ctx->RSGetState(&old.RS);
- ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
- ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
- ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
- ctx->PSGetSamplers(0, 1, &old.PSSampler);
- old.PSInstancesCount = old.VSInstancesCount = 256;
- ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
- ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
- ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
- ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
- ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
- ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
- ctx->IAGetInputLayout(&old.InputLayout);
-
- // Setup viewport
- D3D11_VIEWPORT vp;
- memset(&vp, 0, sizeof(D3D11_VIEWPORT));
- vp.Width = draw_data->DisplaySize.x;
- vp.Height = draw_data->DisplaySize.y;
- vp.MinDepth = 0.0f;
- vp.MaxDepth = 1.0f;
- vp.TopLeftX = vp.TopLeftY = 0;
- ctx->RSSetViewports(1, &vp);
-
- // Bind shader and vertex buffers
- unsigned int stride = sizeof(ImDrawVert);
- unsigned int offset = 0;
- ctx->IASetInputLayout(g_pInputLayout);
- ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
- ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
- ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
- ctx->VSSetShader(g_pVertexShader, NULL, 0);
- ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
- ctx->PSSetShader(g_pPixelShader, NULL, 0);
- ctx->PSSetSamplers(0, 1, &g_pFontSampler);
-
- // Setup render state
- const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
- ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
- ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
- ctx->RSSetState(g_pRasterizerState);
-
- // Render command lists
- int vtx_offset = 0;
- int idx_offset = 0;
- ImVec2 clip_off = draw_data->DisplayPos;
- for (int n = 0; n < draw_data->CmdListsCount; n++)
- {
- const ImDrawList* cmd_list = draw_data->CmdLists[n];
- for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
- {
- const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
- if (pcmd->UserCallback)
- {
- // User callback (registered via ImDrawList::AddCallback)
- pcmd->UserCallback(cmd_list, pcmd);
- }
- else
- {
- // Apply scissor/clipping rectangle
- const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
- ctx->RSSetScissorRects(1, &r);
-
- // Bind texture, Draw
- ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId;
- ctx->PSSetShaderResources(0, 1, &texture_srv);
- ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
- }
- idx_offset += pcmd->ElemCount;
- }
- vtx_offset += cmd_list->VtxBuffer.Size;
- }
-
- // Restore modified DX state
- ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
- ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
- ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
- ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
- ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
- ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
- ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
- ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
- for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
- ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
- ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
- for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
- ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
- ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
- ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
- ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
-}
-
-void ImGui_ImplDX11_CreateFontsTexture()
-{
- // Build texture atlas
- ImGuiIO& io = ImGui::GetIO();
- unsigned char* pixels;
- int width, height;
- io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
-
- // Upload texture to graphics system
- if (g_pFontTextureView)
- {
- g_pFontTextureView->Release();
- g_pFontTextureView = nullptr;
- }
- {
- D3D11_TEXTURE2D_DESC desc;
- ZeroMemory(&desc, sizeof(desc));
- desc.Width = width;
- desc.Height = 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;
-
- ID3D11Texture2D *pTexture = NULL;
- D3D11_SUBRESOURCE_DATA subResource;
- subResource.pSysMem = pixels;
- subResource.SysMemPitch = desc.Width * 4;
- subResource.SysMemSlicePitch = 0;
- g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
-
- // Create texture view
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- ZeroMemory(&srvDesc, sizeof(srvDesc));
- srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- srvDesc.Texture2D.MipLevels = desc.MipLevels;
- srvDesc.Texture2D.MostDetailedMip = 0;
- g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
- pTexture->Release();
- }
-
- // Store our identifier
- io.Fonts->TexID = (ImTextureID)g_pFontTextureView;
-
- // Create texture sampler
- if (!g_pFontSampler)
- {
- D3D11_SAMPLER_DESC desc;
- ZeroMemory(&desc, sizeof(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.f;
- desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
- desc.MinLOD = 0.f;
- desc.MaxLOD = 0.f;
- g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
- }
-
- io.Fonts->ClearTexData();
-}
-
-bool ImGui_ImplDX11_CreateDeviceObjects()
-{
- if (!g_pd3dDevice)
- return false;
- if (g_pFontSampler)
- ImGui_ImplDX11_InvalidateDeviceObjects();
-
- // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
- // If you would like to use this DX11 sample code but remove this dependency you can:
- // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
- // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
- // See https://github.com/ocornut/imgui/pull/638 for sources and details.
-
- // Create the vertex shader
- {
- static const char* vertexShader =
- "cbuffer vertexBuffer : register(b0) \
- {\
- float4x4 ProjectionMatrix; \
- };\
- struct VS_INPUT\
- {\
- float2 pos : POSITION;\
- float4 col : COLOR0;\
- float2 uv : TEXCOORD0;\
- };\
- \
- struct PS_INPUT\
- {\
- float4 pos : SV_POSITION;\
- float4 col : COLOR0;\
- float2 uv : TEXCOORD0;\
- };\
- \
- PS_INPUT main(VS_INPUT input)\
- {\
- PS_INPUT output;\
- output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
- output.col = input.col;\
- output.uv = input.uv;\
- return output;\
- }";
-
- D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL);
- if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
- return false;
- if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK)
- return false;
-
- // Create the input layout
- D3D11_INPUT_ELEMENT_DESC local_layout[] =
- {
- { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
- { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
- };
- if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
- return false;
-
- // Create the constant buffer
- {
- D3D11_BUFFER_DESC desc;
- desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
- desc.Usage = D3D11_USAGE_DYNAMIC;
- desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- desc.MiscFlags = 0;
- g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
- }
- }
-
- // Create the pixel shader
- {
- static const char* pixelShader =
- "struct PS_INPUT\
- {\
- float4 pos : SV_POSITION;\
- float4 col : COLOR0;\
- float2 uv : TEXCOORD0;\
- };\
- sampler sampler0;\
- Texture2D texture0;\
- \
- float4 main(PS_INPUT input) : SV_Target\
- {\
- float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
- return out_col; \
- }";
-
- D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL);
- if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
- return false;
- if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK)
- return false;
- }
-
- // Create the blending setup
- {
- D3D11_BLEND_DESC desc;
- ZeroMemory(&desc, sizeof(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_INV_SRC_ALPHA;
- desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
- desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
- desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
- g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
- }
-
- // Create the rasterizer state
- {
- D3D11_RASTERIZER_DESC desc;
- ZeroMemory(&desc, sizeof(desc));
- desc.FillMode = D3D11_FILL_SOLID;
- desc.CullMode = D3D11_CULL_NONE;
- desc.ScissorEnable = true;
- desc.DepthClipEnable = true;
- g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
- }
-
- // Create depth-stencil State
- {
- D3D11_DEPTH_STENCIL_DESC desc;
- ZeroMemory(&desc, sizeof(desc));
- desc.DepthEnable = false;
- desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
- desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
- desc.StencilEnable = false;
- desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
- desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
- desc.BackFace = desc.FrontFace;
- g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
- }
-
- return true;
-}
-
-void ImGui_ImplDX11_InvalidateDeviceObjects()
-{
- if (!g_pd3dDevice)
- return;
-
- if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
- if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
- if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
- if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
-
- if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
- if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
- if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
- if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
- if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
- if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
- if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }
- if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }
- if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; }
-}
-
-bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
-{
- // Setup back-end capabilities flags
- ImGuiIO& io = ImGui::GetIO();
- io.BackendRendererName = "imgui_impl_dx11";
- g_pd3dDevice = device;
- g_pd3dDeviceContext = device_context;
-
- return ImGui_ImplDX11_CreateDeviceObjects();
-}
-
-void ImGui_ImplDX11_Shutdown()
-{
- ImGui_ImplDX11_InvalidateDeviceObjects();
- g_pd3dDevice = NULL;
- g_pd3dDeviceContext = NULL;
-}
diff --git a/3rdparty/imgui/src/imgui_impl_opengl3.cpp b/3rdparty/imgui/src/imgui_impl_opengl3.cpp
deleted file mode 100644
index d9d84bc775..0000000000
--- a/3rdparty/imgui/src/imgui_impl_opengl3.cpp
+++ /dev/null
@@ -1,567 +0,0 @@
-// dear imgui: Renderer for modern OpenGL with shaders / programmatic pipeline
-// - Desktop GL: 2.x 3.x 4.x
-// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
-// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
-
-// Implemented features:
-// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
-// [X] Renderer: Multi-viewport support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
-// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bits indices.
-
-// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
-// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
-// https://github.com/ocornut/imgui
-
-// CHANGELOG
-// (minor and older changes stripped away, please see git history for details)
-// 2019-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
-// 2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility.
-// 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call.
-// 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
-// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
-// 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop.
-// 2019-03-15: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early.
-// 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0).
-// 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader.
-// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
-// 2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450).
-// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
-// 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT) / GL_CLIP_ORIGIN.
-// 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used.
-// 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES".
-// 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation.
-// 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link.
-// 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples.
-// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
-// 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state.
-// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer.
-// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150".
-// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context.
-// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself.
-// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150.
-// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode.
-// 2017-05-01: OpenGL: Fixed save and restore of current blend func state.
-// 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE.
-// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
-// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)
-
-//----------------------------------------
-// OpenGL GLSL GLSL
-// version version string
-//----------------------------------------
-// 2.0 110 "#version 110"
-// 2.1 120 "#version 120"
-// 3.0 130 "#version 130"
-// 3.1 140 "#version 140"
-// 3.2 150 "#version 150"
-// 3.3 330 "#version 330 core"
-// 4.0 400 "#version 400 core"
-// 4.1 410 "#version 410 core"
-// 4.2 420 "#version 410 core"
-// 4.3 430 "#version 430 core"
-// ES 2.0 100 "#version 100" = WebGL 1.0
-// ES 3.0 300 "#version 300 es" = WebGL 2.0
-//----------------------------------------
-
-#include "imgui.h"
-#include "imgui_impl_opengl3.h"
-#include
-#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
-#include // intptr_t
-#else
-#include // intptr_t
-#endif
-#if defined(__APPLE__)
-#include "TargetConditionals.h"
-#endif
-
-// GL includes
-#include
-
-// OpenGL Data
-static char g_GlslVersionString[32] = "";
-static GLuint g_FontTexture = 0;
-static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
-static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; // Uniforms location
-static int g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_AttribLocationVtxColor = 0; // Vertex attributes location
-static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0;
-static bool g_IsGLES = false;
-static bool g_IsGLES2 = false;
-
-// Functions
-bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
-{
- // Setup back-end capabilities flags
- ImGuiIO& io = ImGui::GetIO();
- io.BackendRendererName = "imgui_impl_opengl3";
-
- // Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
- if (GLAD_GL_ES_VERSION_3_0)
- {
- if (glsl_version == NULL)
- glsl_version = "#version 300 es";
- g_IsGLES = true;
- g_IsGLES2 = false;
- }
- else if (GLAD_GL_ES_VERSION_2_0)
- {
- if (glsl_version == NULL)
- glsl_version = "#version 100";
- g_IsGLES = true;
- g_IsGLES2 = true;
- }
- else
- {
- if (glsl_version == NULL)
- glsl_version = "#version 130";
- g_IsGLES = false;
- g_IsGLES2 = false;
- }
-
- if (!g_IsGLES)
- io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
-
- IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString));
-#ifndef _MSC_VER
- strcpy(g_GlslVersionString, glsl_version);
- strcat(g_GlslVersionString, "\n");
-#else
- strncpy_s(g_GlslVersionString, sizeof(g_GlslVersionString), glsl_version, _TRUNCATE);
- strncat_s(g_GlslVersionString, sizeof(g_GlslVersionString), "\n", _TRUNCATE);
-#endif
- return ImGui_ImplOpenGL3_CreateDeviceObjects();
-}
-
-void ImGui_ImplOpenGL3_Shutdown()
-{
- ImGui_ImplOpenGL3_DestroyDeviceObjects();
-}
-
-void ImGui_ImplOpenGL3_NewFrame()
-{
- if (!g_ShaderHandle)
- ImGui_ImplOpenGL3_CreateDeviceObjects();
-}
-
-static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
-{
- // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
- glEnable(GL_BLEND);
- glBlendEquation(GL_FUNC_ADD);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_SCISSOR_TEST);
-#ifdef GL_POLYGON_MODE
- if (!g_IsGLES)
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-#endif
-
- // Setup viewport, orthographic projection matrix
- // 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.
- glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
- 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;
- const float ortho_projection[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, -1.0f, 0.0f },
- { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
- };
- glUseProgram(g_ShaderHandle);
- glUniform1i(g_AttribLocationTex, 0);
- glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
-
- if (!g_IsGLES2)
- {
- glBindVertexArray(g_VaoHandle);
- glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
- }
- else
- {
- glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
- glEnableVertexAttribArray(g_AttribLocationVtxPos);
- glEnableVertexAttribArray(g_AttribLocationVtxUV);
- glEnableVertexAttribArray(g_AttribLocationVtxColor);
- glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert),
- (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
- glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert),
- (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
- glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert),
- (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
- }
-}
-
-// OpenGL3 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)
-// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
-void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
-{
- // Avoid rendering when minimized
- int fb_width = (int)(draw_data->DisplaySize.x);
- int fb_height = (int)(draw_data->DisplaySize.y);
- if (fb_width <= 0 || fb_height <= 0)
- return;
-
- ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height);
-
- // Will project scissor/clipping rectangles into framebuffer space
- ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
-
- // Render command lists
- for (int n = 0; n < draw_data->CmdListsCount; n++)
- {
- const ImDrawList* cmd_list = draw_data->CmdLists[n];
-
- // Upload vertex/index buffers
- glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
-
- for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
- {
- const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
- if (pcmd->UserCallback != NULL)
- {
- // 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_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height);
- else
- pcmd->UserCallback(cmd_list, pcmd);
- }
- else
- {
- // Project scissor/clipping rectangles into framebuffer space
- ImVec4 clip_rect;
- clip_rect.x = pcmd->ClipRect.x - clip_off.x;
- clip_rect.y = pcmd->ClipRect.y - clip_off.y;
- clip_rect.z = pcmd->ClipRect.z - clip_off.x;
- clip_rect.w = pcmd->ClipRect.w - clip_off.y;
-
- if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
- {
- // Apply scissor/clipping rectangle
- glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
-
- // Bind texture, Draw
- glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
-
- if (!g_IsGLES)
- glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset);
- else
- glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)));
- }
- }
- }
- }
-
- if (!g_IsGLES2)
- {
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- else
- {
- glDisableVertexAttribArray(g_AttribLocationVtxPos);
- glDisableVertexAttribArray(g_AttribLocationVtxUV);
- glDisableVertexAttribArray(g_AttribLocationVtxColor);
- }
-}
-
-bool ImGui_ImplOpenGL3_CreateFontsTexture()
-{
- // Build texture atlas
- ImGuiIO& io = ImGui::GetIO();
- unsigned char* pixels;
- int width, height;
- io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
-
- // Upload texture to graphics system
- GLint last_texture;
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
- glGenTextures(1, &g_FontTexture);
- glBindTexture(GL_TEXTURE_2D, g_FontTexture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-#ifdef GL_UNPACK_ROW_LENGTH
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-#endif
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-
- // Store our identifier
- io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture;
-
- // Restore state
- glBindTexture(GL_TEXTURE_2D, last_texture);
- io.Fonts->ClearTexData();
-
- return true;
-}
-
-void ImGui_ImplOpenGL3_DestroyFontsTexture()
-{
- if (g_FontTexture)
- {
- ImGuiIO& io = ImGui::GetIO();
- glDeleteTextures(1, &g_FontTexture);
- io.Fonts->TexID = 0;
- g_FontTexture = 0;
- }
-}
-
-// If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file.
-static bool CheckShader(GLuint handle, const char* desc)
-{
- GLint status = 0, log_length = 0;
- glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
- glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);
- if ((GLboolean)status == GL_FALSE)
- fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc);
- if (log_length > 1)
- {
- ImVector buf;
- buf.resize((int)(log_length + 1));
- glGetShaderInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());
- fprintf(stderr, "%s\n", buf.begin());
- }
- return (GLboolean)status == GL_TRUE;
-}
-
-// If you get an error please report on GitHub. You may try different GL context version or GLSL version.
-static bool CheckProgram(GLuint handle, const char* desc)
-{
- GLint status = 0, log_length = 0;
- glGetProgramiv(handle, GL_LINK_STATUS, &status);
- glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);
- if ((GLboolean)status == GL_FALSE)
- fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! (with GLSL '%s')\n", desc, g_GlslVersionString);
- if (log_length > 1)
- {
- ImVector buf;
- buf.resize((int)(log_length + 1));
- glGetProgramInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());
- fprintf(stderr, "%s\n", buf.begin());
- }
- return (GLboolean)status == GL_TRUE;
-}
-
-bool ImGui_ImplOpenGL3_CreateDeviceObjects()
-{
- // Backup GL state
- GLint last_texture, last_array_buffer;
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
- glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
-#ifndef IMGUI_IMPL_OPENGL_ES2
- GLint last_vertex_array;
- glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
-#endif
-
- // Parse GLSL version string
- int glsl_version = 130;
-#ifndef _MSC_VER
- sscanf(g_GlslVersionString, "#version %d", &glsl_version);
-#else
- sscanf_s(g_GlslVersionString, "#version %d", &glsl_version);
-#endif
-
- const GLchar* vertex_shader_glsl_120 =
- "uniform mat4 ProjMtx;\n"
- "attribute vec2 Position;\n"
- "attribute vec2 UV;\n"
- "attribute vec4 Color;\n"
- "varying vec2 Frag_UV;\n"
- "varying vec4 Frag_Color;\n"
- "void main()\n"
- "{\n"
- " Frag_UV = UV;\n"
- " Frag_Color = Color;\n"
- " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
- "}\n";
-
- const GLchar* vertex_shader_glsl_130 =
- "uniform mat4 ProjMtx;\n"
- "in vec2 Position;\n"
- "in vec2 UV;\n"
- "in vec4 Color;\n"
- "out vec2 Frag_UV;\n"
- "out vec4 Frag_Color;\n"
- "void main()\n"
- "{\n"
- " Frag_UV = UV;\n"
- " Frag_Color = Color;\n"
- " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
- "}\n";
-
- const GLchar* vertex_shader_glsl_300_es =
- "precision mediump float;\n"
- "layout (location = 0) in vec2 Position;\n"
- "layout (location = 1) in vec2 UV;\n"
- "layout (location = 2) in vec4 Color;\n"
- "uniform mat4 ProjMtx;\n"
- "out vec2 Frag_UV;\n"
- "out vec4 Frag_Color;\n"
- "void main()\n"
- "{\n"
- " Frag_UV = UV;\n"
- " Frag_Color = Color;\n"
- " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
- "}\n";
-
- const GLchar* vertex_shader_glsl_410_core =
- "layout (location = 0) in vec2 Position;\n"
- "layout (location = 1) in vec2 UV;\n"
- "layout (location = 2) in vec4 Color;\n"
- "uniform mat4 ProjMtx;\n"
- "out vec2 Frag_UV;\n"
- "out vec4 Frag_Color;\n"
- "void main()\n"
- "{\n"
- " Frag_UV = UV;\n"
- " Frag_Color = Color;\n"
- " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
- "}\n";
-
- const GLchar* fragment_shader_glsl_120 =
- "#ifdef GL_ES\n"
- " precision mediump float;\n"
- "#endif\n"
- "uniform sampler2D Texture;\n"
- "varying vec2 Frag_UV;\n"
- "varying vec4 Frag_Color;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n"
- "}\n";
-
- const GLchar* fragment_shader_glsl_130 =
- "uniform sampler2D Texture;\n"
- "in vec2 Frag_UV;\n"
- "in vec4 Frag_Color;\n"
- "out vec4 Out_Color;\n"
- "void main()\n"
- "{\n"
- " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
- "}\n";
-
- const GLchar* fragment_shader_glsl_300_es =
- "precision mediump float;\n"
- "uniform sampler2D Texture;\n"
- "in vec2 Frag_UV;\n"
- "in vec4 Frag_Color;\n"
- "layout (location = 0) out vec4 Out_Color;\n"
- "void main()\n"
- "{\n"
- " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
- "}\n";
-
- const GLchar* fragment_shader_glsl_410_core =
- "in vec2 Frag_UV;\n"
- "in vec4 Frag_Color;\n"
- "uniform sampler2D Texture;\n"
- "layout (location = 0) out vec4 Out_Color;\n"
- "void main()\n"
- "{\n"
- " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
- "}\n";
-
- // Select shaders matching our GLSL versions
- const GLchar* vertex_shader = NULL;
- const GLchar* fragment_shader = NULL;
- if (glsl_version < 130)
- {
- vertex_shader = vertex_shader_glsl_120;
- fragment_shader = fragment_shader_glsl_120;
- }
- else if (glsl_version >= 410)
- {
- vertex_shader = vertex_shader_glsl_410_core;
- fragment_shader = fragment_shader_glsl_410_core;
- }
- else if (glsl_version == 300)
- {
- vertex_shader = vertex_shader_glsl_300_es;
- fragment_shader = fragment_shader_glsl_300_es;
- }
- else
- {
- vertex_shader = vertex_shader_glsl_130;
- fragment_shader = fragment_shader_glsl_130;
- }
-
- // Create shaders
- const GLchar* vertex_shader_with_version[2] = { g_GlslVersionString, vertex_shader };
- g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL);
- glCompileShader(g_VertHandle);
- CheckShader(g_VertHandle, "vertex shader");
-
- const GLchar* fragment_shader_with_version[2] = { g_GlslVersionString, fragment_shader };
- g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL);
- glCompileShader(g_FragHandle);
- CheckShader(g_FragHandle, "fragment shader");
-
- g_ShaderHandle = glCreateProgram();
- glAttachShader(g_ShaderHandle, g_VertHandle);
- glAttachShader(g_ShaderHandle, g_FragHandle);
- glLinkProgram(g_ShaderHandle);
- CheckProgram(g_ShaderHandle, "shader program");
-
- g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
- g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
- g_AttribLocationVtxPos = glGetAttribLocation(g_ShaderHandle, "Position");
- g_AttribLocationVtxUV = glGetAttribLocation(g_ShaderHandle, "UV");
- g_AttribLocationVtxColor = glGetAttribLocation(g_ShaderHandle, "Color");
-
- // Create buffers
- glGenBuffers(1, &g_VboHandle);
- glGenBuffers(1, &g_ElementsHandle);
-
- glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
- glBufferData(GL_ARRAY_BUFFER, sizeof(ImDrawVert), nullptr, GL_STREAM_DRAW);
-
-
- if (!g_IsGLES2)
- {
- glGenVertexArrays(1, &g_VaoHandle);
- glBindVertexArray(g_VaoHandle);
-
- glEnableVertexAttribArray(g_AttribLocationVtxPos);
- glEnableVertexAttribArray(g_AttribLocationVtxUV);
- glEnableVertexAttribArray(g_AttribLocationVtxColor);
- glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert),
- (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
- glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert),
- (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
- glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert),
- (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
- }
-
- // Restore modified GL state
- glBindTexture(GL_TEXTURE_2D, last_texture);
- glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
- if (!g_IsGLES2)
- glBindVertexArray(last_vertex_array);
-
- return true;
-}
-
-void ImGui_ImplOpenGL3_DestroyDeviceObjects()
-{
- if (g_VaoHandle) { glDeleteVertexArrays(1, &g_VaoHandle); g_VaoHandle = 0; }
- if (g_VboHandle) { glDeleteBuffers(1, &g_VboHandle); g_VboHandle = 0; }
- if (g_ElementsHandle) { glDeleteBuffers(1, &g_ElementsHandle); g_ElementsHandle = 0; }
- if (g_ShaderHandle && g_VertHandle) { glDetachShader(g_ShaderHandle, g_VertHandle); }
- if (g_ShaderHandle && g_FragHandle) { glDetachShader(g_ShaderHandle, g_FragHandle); }
- if (g_VertHandle) { glDeleteShader(g_VertHandle); g_VertHandle = 0; }
- if (g_FragHandle) { glDeleteShader(g_FragHandle); g_FragHandle = 0; }
- if (g_ShaderHandle) { glDeleteProgram(g_ShaderHandle); g_ShaderHandle = 0; }
-
- ImGui_ImplOpenGL3_DestroyFontsTexture();
-}
diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt
index 12bbcdfdda..d81fc0a0ba 100644
--- a/pcsx2/CMakeLists.txt
+++ b/pcsx2/CMakeLists.txt
@@ -1004,9 +1004,11 @@ set(pcsx2FrontendHeaders
if(USE_OPENGL)
list(APPEND pcsx2FrontendSources
Frontend/OpenGLHostDisplay.cpp
+ Frontend/imgui_impl_opengl3.cpp
)
list(APPEND pcsx2FrontendHeaders
Frontend/OpenGLHostDisplay.h
+ Frontend/imgui_impl_opengl3.h
)
endif()
@@ -1025,10 +1027,14 @@ if(WIN32)
list(APPEND pcsx2FrontendSources
Frontend/D3D11HostDisplay.cpp
Frontend/D3D12HostDisplay.cpp
+ Frontend/imgui_impl_dx11.cpp
+ Frontend/imgui_impl_dx12.cpp
)
list(APPEND pcsx2FrontendHeaders
Frontend/D3D11HostDisplay.h
Frontend/D3D12HostDisplay.h
+ Frontend/imgui_impl_dx11.h
+ Frontend/imgui_impl_dx12.h
)
elseif(APPLE)
list(APPEND pcsx2GSSources
diff --git a/pcsx2/Frontend/D3D12HostDisplay.cpp b/pcsx2/Frontend/D3D12HostDisplay.cpp
index ecfb86ac4c..ef7cd51f2d 100644
--- a/pcsx2/Frontend/D3D12HostDisplay.cpp
+++ b/pcsx2/Frontend/D3D12HostDisplay.cpp
@@ -23,7 +23,7 @@
#include "common/StringUtil.h"
#include "imgui.h"
-#include "backends/imgui_impl_dx12.h"
+#include "imgui_impl_dx12.h"
#include
#include
@@ -584,24 +584,9 @@ bool D3D12HostDisplay::CreateImGuiContext()
ImGui::GetIO().DisplaySize.x = static_cast(m_window_info.surface_width);
ImGui::GetIO().DisplaySize.y = static_cast(m_window_info.surface_height);
- if (!m_imgui_descriptor_heap.Create(g_d3d12_context->GetDevice(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1, true))
+ if (!ImGui_ImplDX12_Init(DXGI_FORMAT_R8G8B8A8_UNORM))
return false;
- if (!m_imgui_descriptor_heap.Allocate(&m_imgui_descriptor_handle))
- {
- m_imgui_descriptor_heap.Destroy();
- return false;
- }
-
- if (!ImGui_ImplDX12_Init(g_d3d12_context->GetDevice(), D3D12::Context::NUM_COMMAND_LISTS,
- DXGI_FORMAT_R8G8B8A8_UNORM, m_imgui_descriptor_heap.GetDescriptorHeap(),
- m_imgui_descriptor_handle, m_imgui_descriptor_handle))
- {
- m_imgui_descriptor_heap.Free(m_imgui_descriptor_handle);
- m_imgui_descriptor_heap.Destroy();
- return false;
- }
-
return true;
}
@@ -610,15 +595,11 @@ void D3D12HostDisplay::DestroyImGuiContext()
g_d3d12_context->WaitForGPUIdle();
ImGui_ImplDX12_Shutdown();
-
- m_imgui_descriptor_heap.Free(&m_imgui_descriptor_handle);
- m_imgui_descriptor_heap.Destroy();
}
bool D3D12HostDisplay::UpdateImGuiFontTexture()
{
- ImGui_ImplDX12_InvalidateDeviceObjects();
- return ImGui_ImplDX12_CreateDeviceObjects();
+ return ImGui_ImplDX12_CreateFontsTexture();
}
bool D3D12HostDisplay::BeginPresent(bool frame_skip)
@@ -646,17 +627,13 @@ bool D3D12HostDisplay::BeginPresent(bool frame_skip)
void D3D12HostDisplay::EndPresent()
{
- ID3D12GraphicsCommandList* cmdlist = g_d3d12_context->GetCommandList();
- ID3D12DescriptorHeap* heaps[] = {m_imgui_descriptor_heap.GetDescriptorHeap()};
- cmdlist->SetDescriptorHeaps(std::size(heaps), heaps);
-
ImGui::Render();
- ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), cmdlist);
+ ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData());
D3D12::Texture& swap_chain_buf = m_swap_chain_buffers[m_current_swap_chain_buffer];
m_current_swap_chain_buffer = ((m_current_swap_chain_buffer + 1) % static_cast(m_swap_chain_buffers.size()));
- swap_chain_buf.TransitionToState(cmdlist, D3D12_RESOURCE_STATE_PRESENT);
+ swap_chain_buf.TransitionToState(g_d3d12_context->GetCommandList(), D3D12_RESOURCE_STATE_PRESENT);
g_d3d12_context->ExecuteCommandList(false);
const UINT vsync_rate = static_cast(m_vsync_mode != VsyncMode::Off);
diff --git a/pcsx2/Frontend/D3D12HostDisplay.h b/pcsx2/Frontend/D3D12HostDisplay.h
index f0dcb7ab41..100d4b5363 100644
--- a/pcsx2/Frontend/D3D12HostDisplay.h
+++ b/pcsx2/Frontend/D3D12HostDisplay.h
@@ -96,9 +96,6 @@ protected:
std::vector m_swap_chain_buffers;
u32 m_current_swap_chain_buffer = 0;
- D3D12::DescriptorHeapManager m_imgui_descriptor_heap;
- D3D12::DescriptorHandle m_imgui_descriptor_handle;
-
bool m_allow_tearing_supported = false;
bool m_using_allow_tearing = false;
bool m_vsync = true;
diff --git a/pcsx2/Frontend/OpenGLHostDisplay.cpp b/pcsx2/Frontend/OpenGLHostDisplay.cpp
index 04a08e5b7b..0bb262d7fb 100644
--- a/pcsx2/Frontend/OpenGLHostDisplay.cpp
+++ b/pcsx2/Frontend/OpenGLHostDisplay.cpp
@@ -85,10 +85,16 @@ std::unique_ptr OpenGLHostDisplay::CreateTexture(u32 width,
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
- if ((GLAD_GL_ARB_texture_storage || GLAD_GL_ES_VERSION_3_0) && !data)
+ if (GLAD_GL_ARB_texture_storage || GLAD_GL_ES_VERSION_3_0)
+ {
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ }
else
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ }
GLenum error = glGetError();
if (error != GL_NO_ERROR)
@@ -339,7 +345,6 @@ void OpenGLHostDisplay::DestroyImGuiContext()
bool OpenGLHostDisplay::UpdateImGuiFontTexture()
{
- ImGui_ImplOpenGL3_DestroyFontsTexture();
return ImGui_ImplOpenGL3_CreateFontsTexture();
}
diff --git a/pcsx2/Frontend/VulkanHostDisplay.cpp b/pcsx2/Frontend/VulkanHostDisplay.cpp
index 878adeb40d..05aff63c1c 100644
--- a/pcsx2/Frontend/VulkanHostDisplay.cpp
+++ b/pcsx2/Frontend/VulkanHostDisplay.cpp
@@ -275,18 +275,7 @@ bool VulkanHostDisplay::HasRenderSurface() const { return static_cast(m_sw
bool VulkanHostDisplay::CreateImGuiContext()
{
- ImGui_ImplVulkan_InitInfo vii = {};
- vii.Instance = g_vulkan_context->GetVulkanInstance();
- vii.PhysicalDevice = g_vulkan_context->GetPhysicalDevice();
- vii.Device = g_vulkan_context->GetDevice();
- vii.QueueFamily = g_vulkan_context->GetGraphicsQueueFamilyIndex();
- vii.Queue = g_vulkan_context->GetGraphicsQueue();
- vii.PipelineCache = g_vulkan_shader_cache->GetPipelineCache();
- vii.MinImageCount = m_swap_chain->GetImageCount();
- vii.ImageCount = m_swap_chain->GetImageCount();
- vii.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
-
- return ImGui_ImplVulkan_Init(&vii, m_swap_chain->GetClearRenderPass());
+ return ImGui_ImplVulkan_Init(m_swap_chain->GetClearRenderPass());
}
void VulkanHostDisplay::DestroyImGuiContext()
@@ -297,10 +286,7 @@ void VulkanHostDisplay::DestroyImGuiContext()
bool VulkanHostDisplay::UpdateImGuiFontTexture()
{
- // Just in case we were drawing something.
- g_vulkan_context->ExecuteCommandBuffer(true);
- ImGui_ImplVulkan_DestroyFontObjects();
- return ImGui_ImplVulkan_CreateFontsTexture(g_vulkan_context->GetCurrentCommandBuffer());
+ return ImGui_ImplVulkan_CreateFontsTexture();
}
void VulkanHostDisplay::DestroyRenderDevice()
@@ -387,7 +373,7 @@ bool VulkanHostDisplay::BeginPresent(bool frame_skip)
void VulkanHostDisplay::EndPresent()
{
ImGui::Render();
- ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), g_vulkan_context->GetCurrentCommandBuffer());
+ ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData());
VkCommandBuffer cmdbuffer = g_vulkan_context->GetCurrentCommandBuffer();
vkCmdEndRenderPass(g_vulkan_context->GetCurrentCommandBuffer());
diff --git a/pcsx2/Frontend/imgui_impl_dx11.cpp b/pcsx2/Frontend/imgui_impl_dx11.cpp
new file mode 100644
index 0000000000..44a59299dc
--- /dev/null
+++ b/pcsx2/Frontend/imgui_impl_dx11.cpp
@@ -0,0 +1,531 @@
+// dear imgui: Renderer Backend for DirectX11
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
+// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
+// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
+// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
+// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility.
+// 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions.
+// 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example.
+// 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself.
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2016-05-07: DirectX11: Disabling depth-write.
+
+#include "PrecompiledHeader.h"
+
+#include "imgui.h"
+#include "imgui_impl_dx11.h"
+
+// DirectX
+#include
+#include
+#include
+#ifdef _MSC_VER
+#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
+#endif
+
+// DirectX11 data
+struct ImGui_ImplDX11_Data
+{
+ ID3D11Device* pd3dDevice;
+ ID3D11DeviceContext* pd3dDeviceContext;
+ IDXGIFactory* pFactory;
+ ID3D11Buffer* pVB;
+ ID3D11Buffer* pIB;
+ ID3D11VertexShader* pVertexShader;
+ ID3D11InputLayout* pInputLayout;
+ ID3D11Buffer* pVertexConstantBuffer;
+ ID3D11PixelShader* pPixelShader;
+ ID3D11SamplerState* pFontSampler;
+ ID3D11ShaderResourceView* pFontTextureView;
+ ID3D11RasterizerState* pRasterizerState;
+ ID3D11BlendState* pBlendState;
+ ID3D11DepthStencilState* pDepthStencilState;
+ int VertexBufferSize;
+ int IndexBufferSize;
+
+ ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
+};
+
+struct VERTEX_CONSTANT_BUFFER
+{
+ float mvp[4][4];
+};
+
+// 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_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
+// Functions
+static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
+{
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+
+ // Setup viewport
+ D3D11_VIEWPORT vp;
+ memset(&vp, 0, sizeof(D3D11_VIEWPORT));
+ vp.Width = draw_data->DisplaySize.x;
+ vp.Height = draw_data->DisplaySize.y;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ vp.TopLeftX = vp.TopLeftY = 0;
+ ctx->RSSetViewports(1, &vp);
+
+ // Setup shader and vertex buffers
+ unsigned int stride = sizeof(ImDrawVert);
+ unsigned int offset = 0;
+ ctx->IASetInputLayout(bd->pInputLayout);
+ ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
+ ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
+ ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ ctx->VSSetShader(bd->pVertexShader, NULL, 0);
+ ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
+ ctx->PSSetShader(bd->pPixelShader, NULL, 0);
+ ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
+ ctx->GSSetShader(NULL, NULL, 0);
+ ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
+ ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
+ ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
+
+ // Setup blend state
+ const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
+ ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
+ ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
+ ctx->RSSetState(bd->pRasterizerState);
+}
+
+// Render function
+void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
+{
+ // Avoid rendering when minimized
+ if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
+ return;
+
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ ID3D11DeviceContext* ctx = bd->pd3dDeviceContext;
+
+ // Create and grow vertex/index buffers if needed
+ if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
+ {
+ if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
+ bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
+ D3D11_BUFFER_DESC desc;
+ memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
+ desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+ if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVB) < 0)
+ return;
+ }
+ if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
+ {
+ if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
+ bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
+ D3D11_BUFFER_DESC desc;
+ memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
+ desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pIB) < 0)
+ return;
+ }
+
+ // Upload vertex/index data into a single contiguous GPU buffer
+ D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
+ if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
+ return;
+ if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
+ return;
+ ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
+ ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
+ memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+ vtx_dst += cmd_list->VtxBuffer.Size;
+ idx_dst += cmd_list->IdxBuffer.Size;
+ }
+ ctx->Unmap(bd->pVB, 0);
+ ctx->Unmap(bd->pIB, 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.
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped_resource;
+ if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
+ return;
+ VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
+ 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 },
+ };
+ memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
+ ctx->Unmap(bd->pVertexConstantBuffer, 0);
+ }
+
+ // Setup desired DX state
+ ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
+
+ // Render command lists
+ // (Because we merged all buffers into a single one, we maintain our own offset into them)
+ int global_idx_offset = 0;
+ int global_vtx_offset = 0;
+ ImVec2 clip_off = draw_data->DisplayPos;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback != NULL)
+ {
+ // 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_ImplDX11_SetupRenderState(draw_data, ctx);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
+ ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
+ if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle
+ const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
+ ctx->RSSetScissorRects(1, &r);
+
+ // Bind texture, Draw
+ ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
+ ctx->PSSetShaderResources(0, 1, &texture_srv);
+ ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
+ }
+ }
+ global_idx_offset += cmd_list->IdxBuffer.Size;
+ global_vtx_offset += cmd_list->VtxBuffer.Size;
+ }
+}
+
+void ImGui_ImplDX11_CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ if (bd->pFontTextureView)
+ bd->pFontTextureView->Release();
+
+ // Upload texture to graphics system
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Width = width;
+ desc.Height = 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;
+
+ ID3D11Texture2D* pTexture = NULL;
+ D3D11_SUBRESOURCE_DATA subResource;
+ subResource.pSysMem = pixels;
+ subResource.SysMemPitch = desc.Width * 4;
+ subResource.SysMemSlicePitch = 0;
+ bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
+ IM_ASSERT(pTexture != NULL);
+
+ // Create texture view
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ ZeroMemory(&srvDesc, sizeof(srvDesc));
+ srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MipLevels = desc.MipLevels;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView);
+ pTexture->Release();
+ }
+
+ // Store our identifier
+ io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
+
+ // Create texture sampler
+ // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
+ if (!bd->pFontSampler)
+ {
+ D3D11_SAMPLER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+ desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+ desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ desc.MipLODBias = 0.f;
+ desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
+ desc.MinLOD = 0.f;
+ desc.MaxLOD = 0.f;
+ bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
+ }
+}
+
+bool ImGui_ImplDX11_CreateDeviceObjects()
+{
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ if (!bd->pd3dDevice)
+ return false;
+ if (bd->pFontSampler)
+ ImGui_ImplDX11_InvalidateDeviceObjects();
+
+ // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
+ // If you would like to use this DX11 sample code but remove this dependency you can:
+ // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
+ // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
+ // See https://github.com/ocornut/imgui/pull/638 for sources and details.
+
+ // Create the vertex shader
+ {
+ static const char* vertexShader =
+ "cbuffer vertexBuffer : register(b0) \
+ {\
+ float4x4 ProjectionMatrix; \
+ };\
+ struct VS_INPUT\
+ {\
+ float2 pos : POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ PS_INPUT main(VS_INPUT input)\
+ {\
+ PS_INPUT output;\
+ output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
+ output.col = input.col;\
+ output.uv = input.uv;\
+ return output;\
+ }";
+
+ ID3DBlob* vertexShaderBlob;
+ if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL)))
+ return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &bd->pVertexShader) != S_OK)
+ {
+ vertexShaderBlob->Release();
+ return false;
+ }
+
+ // Create the input layout
+ D3D11_INPUT_ELEMENT_DESC local_layout[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+ if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
+ {
+ vertexShaderBlob->Release();
+ return false;
+ }
+ vertexShaderBlob->Release();
+
+ // Create the constant buffer
+ {
+ D3D11_BUFFER_DESC desc;
+ desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+ bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVertexConstantBuffer);
+ }
+ }
+
+ // Create the pixel shader
+ {
+ static const char* pixelShader =
+ "struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ sampler sampler0;\
+ Texture2D texture0;\
+ \
+ float4 main(PS_INPUT input) : SV_Target\
+ {\
+ float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
+ return out_col; \
+ }";
+
+ ID3DBlob* pixelShaderBlob;
+ if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL)))
+ return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &bd->pPixelShader) != S_OK)
+ {
+ pixelShaderBlob->Release();
+ return false;
+ }
+ pixelShaderBlob->Release();
+ }
+
+ // Create the blending setup
+ {
+ D3D11_BLEND_DESC desc;
+ ZeroMemory(&desc, sizeof(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 = D3D11_COLOR_WRITE_ENABLE_ALL;
+ bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
+ }
+
+ // Create the rasterizer state
+ {
+ D3D11_RASTERIZER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.FillMode = D3D11_FILL_SOLID;
+ desc.CullMode = D3D11_CULL_NONE;
+ desc.ScissorEnable = true;
+ desc.DepthClipEnable = true;
+ bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
+ }
+
+ // Create depth-stencil State
+ {
+ D3D11_DEPTH_STENCIL_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.DepthEnable = false;
+ desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
+ desc.StencilEnable = false;
+ desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+ desc.BackFace = desc.FrontFace;
+ bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
+ }
+
+ ImGui_ImplDX11_CreateFontsTexture();
+
+ return true;
+}
+
+void ImGui_ImplDX11_InvalidateDeviceObjects()
+{
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ if (!bd->pd3dDevice)
+ return;
+
+ if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = NULL; }
+ if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
+ if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
+ if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
+ if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = NULL; }
+ if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = NULL; }
+ if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = NULL; }
+ if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = NULL; }
+ if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = NULL; }
+ if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = NULL; }
+ if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = NULL; }
+}
+
+bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)();
+ io.BackendRendererUserData = (void*)bd;
+ io.BackendRendererName = "imgui_impl_dx11";
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+
+ // Get factory from device
+ IDXGIDevice* pDXGIDevice = NULL;
+ IDXGIAdapter* pDXGIAdapter = NULL;
+ IDXGIFactory* pFactory = NULL;
+
+ if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
+ if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
+ if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
+ {
+ bd->pd3dDevice = device;
+ bd->pd3dDeviceContext = device_context;
+ bd->pFactory = pFactory;
+ }
+ if (pDXGIDevice) pDXGIDevice->Release();
+ if (pDXGIAdapter) pDXGIAdapter->Release();
+ bd->pd3dDevice->AddRef();
+ bd->pd3dDeviceContext->AddRef();
+
+ return ImGui_ImplDX11_CreateDeviceObjects();
+}
+
+void ImGui_ImplDX11_Shutdown()
+{
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ if (bd == NULL)
+ return;
+
+ ImGui_ImplDX11_InvalidateDeviceObjects();
+ if (bd->pFactory) { bd->pFactory->Release(); }
+ if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
+ if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
+
+ ImGuiIO& io = ImGui::GetIO();
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
+}
diff --git a/pcsx2/Frontend/imgui_impl_dx11.h b/pcsx2/Frontend/imgui_impl_dx11.h
new file mode 100644
index 0000000000..ae5c967407
--- /dev/null
+++ b/pcsx2/Frontend/imgui_impl_dx11.h
@@ -0,0 +1,17 @@
+// dear imgui: Renderer Backend for DirectX11
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+struct ID3D11Device;
+struct ID3D11DeviceContext;
+
+bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
+void ImGui_ImplDX11_Shutdown();
+void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
+
+// Use if you want to reset your rendering device without losing Dear ImGui state.
+void ImGui_ImplDX11_InvalidateDeviceObjects();
+bool ImGui_ImplDX11_CreateDeviceObjects();
+void ImGui_ImplDX11_CreateFontsTexture();
diff --git a/3rdparty/imgui/src/imgui_impl_dx12.cpp b/pcsx2/Frontend/imgui_impl_dx12.cpp
similarity index 57%
rename from 3rdparty/imgui/src/imgui_impl_dx12.cpp
rename to pcsx2/Frontend/imgui_impl_dx12.cpp
index 91b1ba274e..553d8f70bb 100644
--- a/3rdparty/imgui/src/imgui_impl_dx12.cpp
+++ b/pcsx2/Frontend/imgui_impl_dx12.cpp
@@ -37,6 +37,14 @@
// 2018-06-08: DirectX12: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle (to ease support for future multi-viewport).
// 2018-02-22: Merged into master with all Win32 code synchronized to other examples.
+#include "PrecompiledHeader.h"
+
+#include "common/Assertions.h"
+#include "common/D3D12/Context.h"
+#include "common/D3D12/Texture.h"
+#include "common/D3D12/StreamBuffer.h"
+#include "common/RedtapeWindows.h"
+
#include "imgui.h"
#include "imgui_impl_dx12.h"
@@ -48,30 +56,18 @@
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
#endif
-// DirectX data
-struct ImGui_ImplDX12_RenderBuffers
-{
- ID3D12Resource* IndexBuffer;
- ID3D12Resource* VertexBuffer;
- int IndexBufferSize;
- int VertexBufferSize;
-};
+// If we're doing more than this... wtf?
+static constexpr u32 VERTEX_BUFFER_SIZE = 8 * 1024 * 1024;
+static constexpr u32 INDEX_BUFFER_SIZE = 4 * 1024 * 1024;
struct ImGui_ImplDX12_Data
{
- ID3D12Device* pd3dDevice;
- ID3D12RootSignature* pRootSignature;
- ID3D12PipelineState* pPipelineState;
- DXGI_FORMAT RTVFormat;
- ID3D12Resource* pFontTextureResource;
- D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle;
- D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle;
-
- ImGui_ImplDX12_RenderBuffers* pFrameResources;
- UINT numFramesInFlight;
- UINT frameIndex;
-
- ImGui_ImplDX12_Data() { memset(this, 0, sizeof(*this)); frameIndex = UINT_MAX; }
+ D3D12::StreamBuffer VertexStreamBuffer;
+ D3D12::StreamBuffer IndexStreamBuffer;
+ D3D12::Texture FontTexture;
+ ID3D12RootSignature* pRootSignature = nullptr;
+ ID3D12PipelineState* pPipelineState = nullptr;
+ DXGI_FORMAT RTVFormat = DXGI_FORMAT_UNKNOWN;
};
struct VERTEX_CONSTANT_BUFFER
@@ -87,7 +83,7 @@ static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData()
}
// Functions
-static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, ImGui_ImplDX12_RenderBuffers* fr)
+static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx)
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
@@ -124,14 +120,14 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic
unsigned int offset = 0;
D3D12_VERTEX_BUFFER_VIEW vbv;
memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW));
- vbv.BufferLocation = fr->VertexBuffer->GetGPUVirtualAddress() + offset;
- vbv.SizeInBytes = fr->VertexBufferSize * stride;
+ vbv.BufferLocation = bd->VertexStreamBuffer.GetCurrentGPUPointer();
+ vbv.SizeInBytes = bd->VertexStreamBuffer.GetCurrentSpace();
vbv.StrideInBytes = stride;
ctx->IASetVertexBuffers(0, 1, &vbv);
D3D12_INDEX_BUFFER_VIEW ibv;
memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW));
- ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress();
- ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx);
+ ibv.BufferLocation = bd->IndexStreamBuffer.GetCurrentGPUPointer();
+ ibv.SizeInBytes = bd->IndexStreamBuffer.GetCurrentSpace();
ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
ctx->IASetIndexBuffer(&ibv);
ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
@@ -153,7 +149,7 @@ static inline void SafeRelease(T*& res)
}
// Render function
-void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx)
+void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
@@ -162,67 +158,24 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
// FIXME: I'm assuming that this only gets called once per frame!
// If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator.
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
- bd->frameIndex = bd->frameIndex + 1;
- ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[bd->frameIndex % bd->numFramesInFlight];
- // Create and grow vertex/index buffers if needed
- if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount)
+ const u32 needed_vb = draw_data->TotalVtxCount * sizeof(ImDrawVert);
+ const u32 needed_ib = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
+
+ if (!bd->VertexStreamBuffer.ReserveMemory(needed_vb, sizeof(ImDrawVert)) ||
+ !bd->IndexStreamBuffer.ReserveMemory(needed_ib, sizeof(ImDrawIdx)))
{
- SafeRelease(fr->VertexBuffer);
- fr->VertexBufferSize = draw_data->TotalVtxCount + 5000;
- D3D12_HEAP_PROPERTIES props;
- memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
- props.Type = D3D12_HEAP_TYPE_UPLOAD;
- props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- D3D12_RESOURCE_DESC desc;
- memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC));
- desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
- desc.Width = fr->VertexBufferSize * sizeof(ImDrawVert);
- desc.Height = 1;
- desc.DepthOrArraySize = 1;
- desc.MipLevels = 1;
- desc.Format = DXGI_FORMAT_UNKNOWN;
- desc.SampleDesc.Count = 1;
- desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
- desc.Flags = D3D12_RESOURCE_FLAG_NONE;
- if (bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->VertexBuffer)) < 0)
- return;
- }
- if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount)
- {
- SafeRelease(fr->IndexBuffer);
- fr->IndexBufferSize = draw_data->TotalIdxCount + 10000;
- D3D12_HEAP_PROPERTIES props;
- memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
- props.Type = D3D12_HEAP_TYPE_UPLOAD;
- props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- D3D12_RESOURCE_DESC desc;
- memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC));
- desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
- desc.Width = fr->IndexBufferSize * sizeof(ImDrawIdx);
- desc.Height = 1;
- desc.DepthOrArraySize = 1;
- desc.MipLevels = 1;
- desc.Format = DXGI_FORMAT_UNKNOWN;
- desc.SampleDesc.Count = 1;
- desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
- desc.Flags = D3D12_RESOURCE_FLAG_NONE;
- if (bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->IndexBuffer)) < 0)
- return;
+ g_d3d12_context->ExecuteCommandList(false);
+ if (!bd->VertexStreamBuffer.ReserveMemory(needed_vb, sizeof(ImDrawVert)) ||
+ !bd->IndexStreamBuffer.ReserveMemory(needed_ib, sizeof(ImDrawIdx)))
+ {
+ pxFailRel("Failed to allocate space for imgui vertices/indices");
+ }
}
// Upload vertex/index data into a single contiguous GPU buffer
- void* vtx_resource, *idx_resource;
- D3D12_RANGE range;
- memset(&range, 0, sizeof(D3D12_RANGE));
- if (fr->VertexBuffer->Map(0, &range, &vtx_resource) != S_OK)
- return;
- if (fr->IndexBuffer->Map(0, &range, &idx_resource) != S_OK)
- return;
- ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource;
- ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource;
+ ImDrawVert* vtx_dst = (ImDrawVert*)bd->VertexStreamBuffer.GetCurrentHostPointer();
+ ImDrawIdx* idx_dst = (ImDrawIdx*)bd->IndexStreamBuffer.GetCurrentHostPointer();
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -231,17 +184,19 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
vtx_dst += cmd_list->VtxBuffer.Size;
idx_dst += cmd_list->IdxBuffer.Size;
}
- fr->VertexBuffer->Unmap(0, &range);
- fr->IndexBuffer->Unmap(0, &range);
- // Setup desired DX state
- ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr);
+ // Setup desired DX state (must happen before commit, because it uses the offsets)
+ ID3D12GraphicsCommandList* ctx = g_d3d12_context->GetCommandList();
+ ImGui_ImplDX12_SetupRenderState(draw_data, ctx);
+ bd->VertexStreamBuffer.CommitMemory(needed_vb);
+ bd->IndexStreamBuffer.CommitMemory(needed_ib);
// 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;
ImVec2 clip_off = draw_data->DisplayPos;
+ const D3D12::Texture* last_texture = nullptr;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -253,7 +208,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
// 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_ImplDX12_SetupRenderState(draw_data, ctx, fr);
+ ImGui_ImplDX12_SetupRenderState(draw_data, ctx);
else
pcmd->UserCallback(cmd_list, pcmd);
}
@@ -267,9 +222,26 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
// Apply Scissor/clipping rectangle, Bind texture, Draw
const D3D12_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
- D3D12_GPU_DESCRIPTOR_HANDLE texture_handle = {};
- texture_handle.ptr = (UINT64)pcmd->GetTexID();
- ctx->SetGraphicsRootDescriptorTable(1, texture_handle);
+
+ const D3D12::Texture* tex = (D3D12::Texture*)pcmd->GetTexID();
+ if (tex && last_texture != tex)
+ {
+ D3D12::DescriptorHandle handle;
+ if (!g_d3d12_context->GetDescriptorAllocator().Allocate(1, &handle))
+ {
+ // ugh.
+ g_d3d12_context->ExecuteCommandList(false);
+ ctx = g_d3d12_context->GetCommandList();
+ ImGui_ImplDX12_SetupRenderState(draw_data, ctx);
+ if (!g_d3d12_context->GetDescriptorAllocator().Allocate(1, &handle))
+ pxFailRel("Failed to allocate descriptor after cmdlist kick");
+ }
+
+ g_d3d12_context->GetDevice()->CopyDescriptorsSimple(1, handle, tex->GetSRVDescriptor(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ ctx->SetGraphicsRootDescriptorTable(1, handle);
+ last_texture = tex;
+ }
+
ctx->RSSetScissorRects(1, &r);
ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
}
@@ -279,7 +251,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
}
}
-static void ImGui_ImplDX12_CreateFontsTexture()
+bool ImGui_ImplDX12_CreateFontsTexture()
{
// Build texture atlas
ImGuiIO& io = ImGui::GetIO();
@@ -289,160 +261,28 @@ static void ImGui_ImplDX12_CreateFontsTexture()
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// Upload texture to graphics system
+ if (bd->FontTexture.GetWidth() != width || bd->FontTexture.GetHeight() != height)
{
- D3D12_HEAP_PROPERTIES props;
- memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
- props.Type = D3D12_HEAP_TYPE_DEFAULT;
- props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
-
- D3D12_RESOURCE_DESC desc;
- ZeroMemory(&desc, sizeof(desc));
- desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
- desc.Alignment = 0;
- desc.Width = width;
- desc.Height = height;
- desc.DepthOrArraySize = 1;
- desc.MipLevels = 1;
- desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- desc.SampleDesc.Count = 1;
- desc.SampleDesc.Quality = 0;
- desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
- desc.Flags = D3D12_RESOURCE_FLAG_NONE;
-
- ID3D12Resource* pTexture = NULL;
- bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
- D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&pTexture));
-
- UINT uploadPitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
- UINT uploadSize = height * uploadPitch;
- desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
- desc.Alignment = 0;
- desc.Width = uploadSize;
- desc.Height = 1;
- desc.DepthOrArraySize = 1;
- desc.MipLevels = 1;
- desc.Format = DXGI_FORMAT_UNKNOWN;
- desc.SampleDesc.Count = 1;
- desc.SampleDesc.Quality = 0;
- desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
- desc.Flags = D3D12_RESOURCE_FLAG_NONE;
-
- props.Type = D3D12_HEAP_TYPE_UPLOAD;
- props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
-
- ID3D12Resource* uploadBuffer = NULL;
- HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
- D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer));
- IM_ASSERT(SUCCEEDED(hr));
-
- void* mapped = NULL;
- D3D12_RANGE range = { 0, uploadSize };
- hr = uploadBuffer->Map(0, &range, &mapped);
- IM_ASSERT(SUCCEEDED(hr));
- for (int y = 0; y < height; y++)
- memcpy((void*) ((uintptr_t) mapped + y * uploadPitch), pixels + y * width * 4, width * 4);
- uploadBuffer->Unmap(0, &range);
-
- D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
- srcLocation.pResource = uploadBuffer;
- srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- srcLocation.PlacedFootprint.Footprint.Width = width;
- srcLocation.PlacedFootprint.Footprint.Height = height;
- srcLocation.PlacedFootprint.Footprint.Depth = 1;
- srcLocation.PlacedFootprint.Footprint.RowPitch = uploadPitch;
-
- D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
- dstLocation.pResource = pTexture;
- dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- dstLocation.SubresourceIndex = 0;
-
- D3D12_RESOURCE_BARRIER barrier = {};
- barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
- barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
- barrier.Transition.pResource = pTexture;
- barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
- barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
- barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
-
- ID3D12Fence* fence = NULL;
- hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
- IM_ASSERT(SUCCEEDED(hr));
-
- HANDLE event = CreateEvent(0, 0, 0, 0);
- IM_ASSERT(event != NULL);
-
- D3D12_COMMAND_QUEUE_DESC queueDesc = {};
- queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
- queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
- queueDesc.NodeMask = 1;
-
- ID3D12CommandQueue* cmdQueue = NULL;
- hr = bd->pd3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue));
- IM_ASSERT(SUCCEEDED(hr));
-
- ID3D12CommandAllocator* cmdAlloc = NULL;
- hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc));
- IM_ASSERT(SUCCEEDED(hr));
-
- ID3D12GraphicsCommandList* cmdList = NULL;
- hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList));
- IM_ASSERT(SUCCEEDED(hr));
-
- cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL);
- cmdList->ResourceBarrier(1, &barrier);
-
- hr = cmdList->Close();
- IM_ASSERT(SUCCEEDED(hr));
-
- cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList);
- hr = cmdQueue->Signal(fence, 1);
- IM_ASSERT(SUCCEEDED(hr));
-
- fence->SetEventOnCompletion(1, event);
- WaitForSingleObject(event, INFINITE);
-
- cmdList->Release();
- cmdAlloc->Release();
- cmdQueue->Release();
- CloseHandle(event);
- fence->Release();
- uploadBuffer->Release();
-
- // Create texture view
- D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
- ZeroMemory(&srvDesc, sizeof(srvDesc));
- srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
- srvDesc.Texture2D.MipLevels = desc.MipLevels;
- srvDesc.Texture2D.MostDetailedMip = 0;
- srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
- bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, bd->hFontSrvCpuDescHandle);
- SafeRelease(bd->pFontTextureResource);
- bd->pFontTextureResource = pTexture;
+ if (!bd->FontTexture.Create(width, height, 1, DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
+ D3D12_RESOURCE_FLAG_NONE))
+ {
+ return false;
+ }
}
- // Store our identifier
- // READ THIS IF THE STATIC_ASSERT() TRIGGERS:
- // - Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
- // - This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
- // [Solution 1] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'ImTextureID=ImU64' (this is what we do in the 'example_win32_direct12/example_win32_direct12.vcxproj' project file)
- // [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like.
- // [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!)
- // [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in the example_win32_direct12/build_win32.bat file)
- static_assert(sizeof(ImTextureID) >= sizeof(bd->hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID, 32-bit not supported yet.");
- io.Fonts->SetTexID((ImTextureID)bd->hFontSrvGpuDescHandle.ptr);
+ if (!bd->FontTexture.LoadData(0, 0, 0, width, height, pixels, width * sizeof(u32)))
+ return false;
+
+ io.Fonts->SetTexID((ImTextureID)&bd->FontTexture);
+ return true;
}
bool ImGui_ImplDX12_CreateDeviceObjects()
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
- if (!bd || !bd->pd3dDevice)
- return false;
if (bd->pPipelineState)
- ImGui_ImplDX12_InvalidateDeviceObjects();
+ ImGui_ImplDX12_DestroyDeviceObjects();
// Create the root signature
{
@@ -466,11 +306,12 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
param[1].DescriptorTable.pDescriptorRanges = &descRange;
param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+ // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
D3D12_STATIC_SAMPLER_DESC staticSampler = {};
staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
- staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
- staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
- staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+ staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
staticSampler.MipLODBias = 0.f;
staticSampler.MaxAnisotropy = 0;
staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
@@ -492,22 +333,11 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS;
- // Load d3d12.dll and D3D12SerializeRootSignature() function address dynamically to facilitate using with D3D12On7.
- // See if any version of d3d12.dll is already loaded in the process. If so, give preference to that.
- HMODULE d3d12_dll = ::GetModuleHandleA("d3d12.dll");
- if (d3d12_dll == NULL)
- return false;
+ auto blob = g_d3d12_context->SerializeRootSignature(&desc);
+ if (!blob)
+ return false;
- PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFn = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)::GetProcAddress(d3d12_dll, "D3D12SerializeRootSignature");
- if (D3D12SerializeRootSignatureFn == NULL)
- return false;
-
- ID3DBlob* blob = NULL;
- if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL) != S_OK)
- return false;
-
- bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignature));
- blob->Release();
+ g_d3d12_context->GetDevice()->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignature));
}
// By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
@@ -642,39 +472,31 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
desc.BackFace = desc.FrontFace;
}
- HRESULT result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineState));
+ HRESULT result_pipeline_state = g_d3d12_context->GetDevice()->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineState));
vertexShaderBlob->Release();
pixelShaderBlob->Release();
if (result_pipeline_state != S_OK)
return false;
- ImGui_ImplDX12_CreateFontsTexture();
-
return true;
}
-void ImGui_ImplDX12_InvalidateDeviceObjects()
+void ImGui_ImplDX12_DestroyDeviceObjects()
{
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
- if (!bd || !bd->pd3dDevice)
+ if (!bd)
return;
ImGuiIO& io = ImGui::GetIO();
SafeRelease(bd->pRootSignature);
SafeRelease(bd->pPipelineState);
- SafeRelease(bd->pFontTextureResource);
+ bd->FontTexture.Destroy(false);
+ bd->VertexStreamBuffer.Destroy(false);
+ bd->IndexStreamBuffer.Destroy(false);
io.Fonts->SetTexID(NULL); // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
-
- for (UINT i = 0; i < bd->numFramesInFlight; i++)
- {
- ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[i];
- SafeRelease(fr->IndexBuffer);
- SafeRelease(fr->VertexBuffer);
- }
}
-bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
- D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle)
+bool ImGui_ImplDX12_Init(DXGI_FORMAT rtv_format)
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
@@ -685,26 +507,12 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
io.BackendRendererName = "imgui_impl_dx12";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
- bd->pd3dDevice = device;
bd->RTVFormat = rtv_format;
- bd->hFontSrvCpuDescHandle = font_srv_cpu_desc_handle;
- bd->hFontSrvGpuDescHandle = font_srv_gpu_desc_handle;
- bd->pFrameResources = new ImGui_ImplDX12_RenderBuffers[num_frames_in_flight];
- bd->numFramesInFlight = num_frames_in_flight;
- bd->frameIndex = UINT_MAX;
- IM_UNUSED(cbv_srv_heap); // Unused in master branch (will be used by multi-viewports)
- // Create buffers with a default size (they will later be grown as needed)
- for (int i = 0; i < num_frames_in_flight; i++)
- {
- ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[i];
- fr->IndexBuffer = NULL;
- fr->VertexBuffer = NULL;
- fr->IndexBufferSize = 10000;
- fr->VertexBufferSize = 5000;
- }
+ if (!bd->VertexStreamBuffer.Create(VERTEX_BUFFER_SIZE) || !bd->IndexStreamBuffer.Create(INDEX_BUFFER_SIZE))
+ return false;
- return true;
+ return ImGui_ImplDX12_CreateDeviceObjects();
}
void ImGui_ImplDX12_Shutdown()
@@ -713,8 +521,7 @@ void ImGui_ImplDX12_Shutdown()
IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
- ImGui_ImplDX12_InvalidateDeviceObjects();
- delete[] bd->pFrameResources;
+ ImGui_ImplDX12_DestroyDeviceObjects();
io.BackendRendererName = NULL;
io.BackendRendererUserData = NULL;
IM_DELETE(bd);
diff --git a/pcsx2/Frontend/imgui_impl_dx12.h b/pcsx2/Frontend/imgui_impl_dx12.h
new file mode 100644
index 0000000000..6776da3740
--- /dev/null
+++ b/pcsx2/Frontend/imgui_impl_dx12.h
@@ -0,0 +1,14 @@
+// dear imgui: Renderer Backend for DirectX12
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+bool ImGui_ImplDX12_Init(DXGI_FORMAT rtv_format);
+void ImGui_ImplDX12_Shutdown();
+void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data);
+
+// Use if you want to reset your rendering device without losing Dear ImGui state.
+void ImGui_ImplDX12_DestroyDeviceObjects();
+bool ImGui_ImplDX12_CreateDeviceObjects();
+bool ImGui_ImplDX12_CreateFontsTexture();
diff --git a/pcsx2/Frontend/imgui_impl_opengl3.cpp b/pcsx2/Frontend/imgui_impl_opengl3.cpp
new file mode 100644
index 0000000000..fef9abc86b
--- /dev/null
+++ b/pcsx2/Frontend/imgui_impl_opengl3.cpp
@@ -0,0 +1,577 @@
+// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
+// - Desktop GL: 2.x 3.x 4.x
+// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
+// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2022-05-13: OpenGL: Fix state corruption on OpenGL ES 2.0 due to not preserving GL_ELEMENT_ARRAY_BUFFER_BINDING and vertex attribute states.
+// 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers.
+// 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions.
+// 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader.
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state.
+// 2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader.
+// 2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version.
+// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater.
+// 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.
+// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
+// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
+// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
+// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader.
+// 2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
+// 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX.
+// 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix.
+// 2020-04-12: OpenGL: Fixed context version check mistakenly testing for 4.0+ instead of 3.2+ to enable ImGuiBackendFlags_RendererHasVtxOffset.
+// 2020-03-24: OpenGL: Added support for glbinding 2.x OpenGL loader.
+// 2020-01-07: OpenGL: Added support for glbinding 3.x OpenGL loader.
+// 2019-10-25: OpenGL: Using a combination of GL define and runtime GL version to decide whether to use glDrawElementsBaseVertex(). Fix building with pre-3.2 GL loaders.
+// 2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility.
+// 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call.
+// 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
+// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop.
+// 2019-03-15: OpenGL: Added a GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early.
+// 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0).
+// 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader.
+// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
+// 2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450).
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT) / GL_CLIP_ORIGIN.
+// 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used.
+// 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES".
+// 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation.
+// 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link.
+// 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples.
+// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
+// 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state.
+// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer.
+// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150".
+// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself.
+// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150.
+// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode.
+// 2017-05-01: OpenGL: Fixed save and restore of current blend func state.
+// 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE.
+// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
+// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)
+
+//----------------------------------------
+// OpenGL GLSL GLSL
+// version version string
+//----------------------------------------
+// 2.0 110 "#version 110"
+// 2.1 120 "#version 120"
+// 3.0 130 "#version 130"
+// 3.1 140 "#version 140"
+// 3.2 150 "#version 150"
+// 3.3 330 "#version 330 core"
+// 4.0 400 "#version 400 core"
+// 4.1 410 "#version 410 core"
+// 4.2 420 "#version 410 core"
+// 4.3 430 "#version 430 core"
+// ES 2.0 100 "#version 100" = WebGL 1.0
+// ES 3.0 300 "#version 300 es" = WebGL 2.0
+//----------------------------------------
+
+#include "PrecompiledHeader.h"
+
+#include "imgui.h"
+#include "imgui_impl_opengl3.h"
+#include
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include // intptr_t
+#else
+#include // intptr_t
+#endif
+
+// Clang warnings with -Weverything
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast
+#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
+#if __has_warning("-Wzero-as-null-pointer-constant")
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
+#endif
+#endif
+
+// GL includes
+#include
+
+// OpenGL Data
+struct ImGui_ImplOpenGL3_Data
+{
+ GLuint GlVersion; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)
+ char GlslVersionString[32]; // Specified by user or detected based on compile time GL settings.
+ GLuint FontTexture;
+ GLuint ShaderHandle;
+ GLint AttribLocationTex; // Uniforms location
+ GLint AttribLocationProjMtx;
+ GLuint AttribLocationVtxPos; // Vertex attributes location
+ GLuint AttribLocationVtxUV;
+ GLuint AttribLocationVtxColor;
+ unsigned int VboHandle, ElementsHandle, VaoHandle, SamplerHandle;
+ GLsizeiptr VertexBufferSize;
+ GLsizeiptr IndexBufferSize;
+
+ ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
+};
+
+// 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_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
+// Functions
+bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
+ io.BackendRendererUserData = (void*)bd;
+ io.BackendRendererName = "imgui_impl_opengl3";
+
+ // Query for GL version (e.g. 320 for GL 3.2)
+ GLint major = 0;
+ GLint minor = 0;
+ glGetIntegerv(GL_MAJOR_VERSION, &major);
+ glGetIntegerv(GL_MINOR_VERSION, &minor);
+ if (major == 0 && minor == 0)
+ {
+ // Query GL_VERSION in desktop GL 2.x, the string will start with "."
+ const char* gl_version = (const char*)glGetString(GL_VERSION);
+ sscanf(gl_version, "%d.%d", &major, &minor);
+ }
+ bd->GlVersion = (GLuint)(major * 100 + minor * 10);
+
+ if (bd->GlVersion >= 320)
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+
+ // Store GLSL version string so we can refer to it later in case we recreate shaders.
+ // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
+ if (glsl_version == NULL)
+ glsl_version = "#version 130";
+
+ IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString));
+ strcpy(bd->GlslVersionString, glsl_version);
+ strcat(bd->GlslVersionString, "\n");
+ return ImGui_ImplOpenGL3_CreateDeviceObjects();
+}
+
+void ImGui_ImplOpenGL3_Shutdown()
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui_ImplOpenGL3_DestroyDeviceObjects();
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
+}
+
+static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+
+ // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
+ glEnable(GL_BLEND);
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_STENCIL_TEST);
+ glEnable(GL_SCISSOR_TEST);
+ if (glPolygonMode)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ // Setup viewport, orthographic projection matrix
+ // 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.
+ glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
+ 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;
+ const float ortho_projection[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, -1.0f, 0.0f },
+ { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
+ };
+ glUseProgram(bd->ShaderHandle);
+ glUniform1i(bd->AttribLocationTex, 0);
+ glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
+ glBindSampler(0, bd->SamplerHandle);
+
+ // Bind vertex/index buffers and setup attributes for ImDrawVert
+ glBindVertexArray(bd->VaoHandle);
+ glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle);
+ glEnableVertexAttribArray(bd->AttribLocationVtxPos);
+ glEnableVertexAttribArray(bd->AttribLocationVtxUV);
+ glEnableVertexAttribArray(bd->AttribLocationVtxColor);
+ glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
+ glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
+ glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
+}
+
+// OpenGL3 Render function.
+// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
+// This is in order to be able to run within an OpenGL engine that doesn't do so.
+void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
+{
+ // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
+ 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)
+ return;
+
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+
+ // Setup desired GL state
+ ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height);
+
+ // Will project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
+ ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
+
+ // Render command lists
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+
+ // Upload vertex/index buffers
+ GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
+ GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
+ if (bd->VertexBufferSize < vtx_buffer_size)
+ {
+ bd->VertexBufferSize = vtx_buffer_size;
+ glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, NULL, GL_STREAM_DRAW);
+ }
+ if (bd->IndexBufferSize < idx_buffer_size)
+ {
+ bd->IndexBufferSize = idx_buffer_size;
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, NULL, GL_STREAM_DRAW);
+ }
+ glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data);
+ glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data);
+
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback != NULL)
+ {
+ // 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_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // 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);
+ if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle (Y is inverted in OpenGL)
+ glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
+
+ // Bind texture, Draw
+ glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
+ glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset);
+ }
+ }
+ }
+
+ glBindVertexArray(0);
+}
+
+bool ImGui_ImplOpenGL3_CreateFontsTexture()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+
+ // Build texture atlas
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
+
+ // Upload texture to graphics system
+ // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
+ if (bd->FontTexture == 0)
+ glGenTextures(1, &bd->FontTexture);
+
+ glBindTexture(GL_TEXTURE_2D, bd->FontTexture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+ // Store our identifier
+ io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
+ return true;
+}
+
+void ImGui_ImplOpenGL3_DestroyFontsTexture()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ if (bd->FontTexture)
+ {
+ glDeleteTextures(1, &bd->FontTexture);
+ io.Fonts->SetTexID(0);
+ bd->FontTexture = 0;
+ }
+}
+
+// If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file.
+static bool CheckShader(GLuint handle, const char* desc)
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ GLint status = 0, log_length = 0;
+ glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
+ glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);
+ if ((GLboolean)status == GL_FALSE)
+ fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s! With GLSL: %s\n", desc, bd->GlslVersionString);
+ if (log_length > 1)
+ {
+ ImVector buf;
+ buf.resize((int)(log_length + 1));
+ glGetShaderInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());
+ fprintf(stderr, "%s\n", buf.begin());
+ }
+ return (GLboolean)status == GL_TRUE;
+}
+
+// If you get an error please report on GitHub. You may try different GL context version or GLSL version.
+static bool CheckProgram(GLuint handle, const char* desc)
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ GLint status = 0, log_length = 0;
+ glGetProgramiv(handle, GL_LINK_STATUS, &status);
+ glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);
+ if ((GLboolean)status == GL_FALSE)
+ fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! With GLSL %s\n", desc, bd->GlslVersionString);
+ if (log_length > 1)
+ {
+ ImVector buf;
+ buf.resize((int)(log_length + 1));
+ glGetProgramInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());
+ fprintf(stderr, "%s\n", buf.begin());
+ }
+ return (GLboolean)status == GL_TRUE;
+}
+
+bool ImGui_ImplOpenGL3_CreateDeviceObjects()
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+
+ // Parse GLSL version string
+ int glsl_version = 130;
+ sscanf(bd->GlslVersionString, "#version %d", &glsl_version);
+
+ const GLchar* vertex_shader_glsl_120 =
+ "uniform mat4 ProjMtx;\n"
+ "attribute vec2 Position;\n"
+ "attribute vec2 UV;\n"
+ "attribute vec4 Color;\n"
+ "varying vec2 Frag_UV;\n"
+ "varying vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* vertex_shader_glsl_130 =
+ "uniform mat4 ProjMtx;\n"
+ "in vec2 Position;\n"
+ "in vec2 UV;\n"
+ "in vec4 Color;\n"
+ "out vec2 Frag_UV;\n"
+ "out vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* vertex_shader_glsl_300_es =
+ "precision highp float;\n"
+ "layout (location = 0) in vec2 Position;\n"
+ "layout (location = 1) in vec2 UV;\n"
+ "layout (location = 2) in vec4 Color;\n"
+ "uniform mat4 ProjMtx;\n"
+ "out vec2 Frag_UV;\n"
+ "out vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* vertex_shader_glsl_410_core =
+ "layout (location = 0) in vec2 Position;\n"
+ "layout (location = 1) in vec2 UV;\n"
+ "layout (location = 2) in vec4 Color;\n"
+ "uniform mat4 ProjMtx;\n"
+ "out vec2 Frag_UV;\n"
+ "out vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_120 =
+ "#ifdef GL_ES\n"
+ " precision mediump float;\n"
+ "#endif\n"
+ "uniform sampler2D Texture;\n"
+ "varying vec2 Frag_UV;\n"
+ "varying vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_130 =
+ "uniform sampler2D Texture;\n"
+ "in vec2 Frag_UV;\n"
+ "in vec4 Frag_Color;\n"
+ "out vec4 Out_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_300_es =
+ "precision mediump float;\n"
+ "uniform sampler2D Texture;\n"
+ "in vec2 Frag_UV;\n"
+ "in vec4 Frag_Color;\n"
+ "layout (location = 0) out vec4 Out_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_410_core =
+ "in vec2 Frag_UV;\n"
+ "in vec4 Frag_Color;\n"
+ "uniform sampler2D Texture;\n"
+ "layout (location = 0) out vec4 Out_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ // Select shaders matching our GLSL versions
+ const GLchar* vertex_shader = NULL;
+ const GLchar* fragment_shader = NULL;
+ if (glsl_version < 130)
+ {
+ vertex_shader = vertex_shader_glsl_120;
+ fragment_shader = fragment_shader_glsl_120;
+ }
+ else if (glsl_version >= 410)
+ {
+ vertex_shader = vertex_shader_glsl_410_core;
+ fragment_shader = fragment_shader_glsl_410_core;
+ }
+ else if (glsl_version == 300)
+ {
+ vertex_shader = vertex_shader_glsl_300_es;
+ fragment_shader = fragment_shader_glsl_300_es;
+ }
+ else
+ {
+ vertex_shader = vertex_shader_glsl_130;
+ fragment_shader = fragment_shader_glsl_130;
+ }
+
+ // Create shaders
+ const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader };
+ GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vert_handle, 2, vertex_shader_with_version, NULL);
+ glCompileShader(vert_handle);
+ CheckShader(vert_handle, "vertex shader");
+
+ const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader };
+ GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(frag_handle, 2, fragment_shader_with_version, NULL);
+ glCompileShader(frag_handle);
+ CheckShader(frag_handle, "fragment shader");
+
+ // Link
+ bd->ShaderHandle = glCreateProgram();
+ glAttachShader(bd->ShaderHandle, vert_handle);
+ glAttachShader(bd->ShaderHandle, frag_handle);
+ glLinkProgram(bd->ShaderHandle);
+ CheckProgram(bd->ShaderHandle, "shader program");
+
+ glDetachShader(bd->ShaderHandle, vert_handle);
+ glDetachShader(bd->ShaderHandle, frag_handle);
+ glDeleteShader(vert_handle);
+ glDeleteShader(frag_handle);
+
+ bd->AttribLocationTex = glGetUniformLocation(bd->ShaderHandle, "Texture");
+ bd->AttribLocationProjMtx = glGetUniformLocation(bd->ShaderHandle, "ProjMtx");
+ bd->AttribLocationVtxPos = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Position");
+ bd->AttribLocationVtxUV = (GLuint)glGetAttribLocation(bd->ShaderHandle, "UV");
+ bd->AttribLocationVtxColor = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Color");
+
+ // Create buffers
+ glGenBuffers(1, &bd->VboHandle);
+ glGenBuffers(1, &bd->ElementsHandle);
+ glGenVertexArrays(1, &bd->VaoHandle);
+
+ // Create sampler
+ if (bd->SamplerHandle == 0)
+ {
+ glGenSamplers(1, &bd->SamplerHandle);
+ glSamplerParameteri(bd->SamplerHandle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glSamplerParameteri(bd->SamplerHandle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glSamplerParameteri(bd->SamplerHandle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glSamplerParameteri(bd->SamplerHandle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+
+ return true;
+}
+
+void ImGui_ImplOpenGL3_DestroyDeviceObjects()
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ if (bd->VaoHandle) { glDeleteVertexArrays(1, &bd->VaoHandle); bd->VaoHandle = 0; }
+ if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
+ if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }
+ if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; }
+ if (bd->SamplerHandle) { glDeleteSamplers(1, &bd->SamplerHandle); bd->SamplerHandle = 0; }
+ ImGui_ImplOpenGL3_DestroyFontsTexture();
+}
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
diff --git a/pcsx2/Frontend/imgui_impl_opengl3.h b/pcsx2/Frontend/imgui_impl_opengl3.h
new file mode 100644
index 0000000000..0549fe3cab
--- /dev/null
+++ b/pcsx2/Frontend/imgui_impl_opengl3.h
@@ -0,0 +1,16 @@
+// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+// Backend API
+bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL);
+void ImGui_ImplOpenGL3_Shutdown();
+void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
+
+// (Optional) Called by Init/NewFrame/Shutdown
+bool ImGui_ImplOpenGL3_CreateFontsTexture();
+void ImGui_ImplOpenGL3_DestroyFontsTexture();
+bool ImGui_ImplOpenGL3_CreateDeviceObjects();
+void ImGui_ImplOpenGL3_DestroyDeviceObjects();
diff --git a/pcsx2/Frontend/imgui_impl_vulkan.cpp b/pcsx2/Frontend/imgui_impl_vulkan.cpp
index 47da607137..8583989a06 100644
--- a/pcsx2/Frontend/imgui_impl_vulkan.cpp
+++ b/pcsx2/Frontend/imgui_impl_vulkan.cpp
@@ -1,27 +1,44 @@
-// dear imgui: Renderer for Vulkan
-// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
+// dear imgui: Renderer Backend for Vulkan
+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
// Implemented features:
-// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
-// Missing features:
-// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
-// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
-// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
-// https://github.com/ocornut/imgui
+// Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
+// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
+// To build this on 32-bit systems and support texture changes:
+// - [Solution 1] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'ImTextureID=ImU64' (this is what we do in our .vcxproj files)
+// - [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like.
+// - [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!)
+// - [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in our batch files)
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
-// You will use those if you want to use this rendering back-end in your engine/app.
+// You will use those if you want to use this rendering backend in your engine/app.
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
-// the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
+// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
// Read comments in imgui_impl_vulkan.h.
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
+// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.
+// 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer.
+// 2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions().
+// 2020-11-11: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation.
+// 2020-09-07: Vulkan: Added VkPipeline parameter to ImGui_ImplVulkan_RenderDrawData (default to one passed to ImGui_ImplVulkan_Init).
+// 2020-05-04: Vulkan: Fixed crash if initial frame has no vertices.
+// 2020-04-26: Vulkan: Fixed edge case where render callbacks wouldn't be called if the ImDrawData didn't have vertices.
// 2019-08-01: Vulkan: Added support for specifying multisample count. Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values to use, default is non-multisampled as before.
// 2019-05-29: Vulkan: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
// 2019-04-30: Vulkan: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
@@ -32,7 +49,7 @@
// 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
// 2018-08-25: Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
-// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other bindings.
+// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other backends.
// 2018-06-08: Misc: Extracted imgui_impl_vulkan.cpp/.h away from the old combined GLFW+Vulkan example.
// 2018-06-08: Vulkan: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
// 2018-03-03: Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use.
@@ -44,64 +61,47 @@
// 2016-10-18: Vulkan: Add location decorators & change to use structs as in/out in glsl, update embedded spv (produced with glslangValidator -x). Null the released resources.
// 2016-08-27: Vulkan: Fix Vulkan example for use when a depth buffer is active.
-#include "PrecompiledHeader.h"
-
-#include "imgui.h"
#include "imgui_impl_vulkan.h"
+
+#include "common/Vulkan/Builders.h"
#include "common/Vulkan/Context.h"
#include "common/Vulkan/Texture.h"
-#include
+#include "common/Vulkan/StreamBuffer.h"
+#include "common/Vulkan/Util.h"
-// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData()
-// [Please zero-clear before use!]
-struct ImGui_ImplVulkanH_FrameRenderBuffers
-{
- VkDeviceMemory VertexBufferMemory;
- VkDeviceMemory IndexBufferMemory;
- VkDeviceSize VertexBufferSize;
- VkDeviceSize IndexBufferSize;
- VkBuffer VertexBuffer;
- VkBuffer IndexBuffer;
-};
+#include
+#include
-// Each viewport will hold 1 ImGui_ImplVulkanH_WindowRenderBuffers
-// [Please zero-clear before use!]
-struct ImGui_ImplVulkanH_WindowRenderBuffers
-{
- uint32_t Index;
- uint32_t Count;
- ImGui_ImplVulkanH_FrameRenderBuffers* FrameRenderBuffers;
-};
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4127) // condition expression is constant
+#endif
+
+// If we're doing more than this... wtf?
+static constexpr u32 VERTEX_BUFFER_SIZE = 8 * 1024 * 1024;
+static constexpr u32 INDEX_BUFFER_SIZE = 4 * 1024 * 1024;
// Vulkan data
-static ImGui_ImplVulkan_InitInfo g_VulkanInitInfo = {};
-static VkRenderPass g_RenderPass = VK_NULL_HANDLE;
-static VkDeviceSize g_BufferMemoryAlignment = 256;
-static VkPipelineCreateFlags g_PipelineCreateFlags = 0x00;
-static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE;
-static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE;
-static VkPipeline g_Pipeline = VK_NULL_HANDLE;
+struct ImGui_ImplVulkan_Data
+{
+ VkRenderPass RenderPass = VK_NULL_HANDLE;
+ VkPipelineCreateFlags PipelineCreateFlags = 0;
+ VkDescriptorSetLayout DescriptorSetLayout = VK_NULL_HANDLE;
+ VkPipelineLayout PipelineLayout = VK_NULL_HANDLE;
+ VkPipeline Pipeline = VK_NULL_HANDLE;
+ VkShaderModule ShaderModuleVert = VK_NULL_HANDLE;
+ VkShaderModule ShaderModuleFrag = VK_NULL_HANDLE;
-// Font data
-static VkSampler g_FontSampler = VK_NULL_HANDLE;
-static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE;
-static VkImage g_FontImage = VK_NULL_HANDLE;
-static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE;
-static VkBuffer g_UploadBuffer = VK_NULL_HANDLE;
-static Vulkan::Texture g_FontTexture;
+ VkSampler FontSampler = VK_NULL_HANDLE;
-// Render buffers
-static ImGui_ImplVulkanH_WindowRenderBuffers g_MainWindowRenderBuffers;
+ Vulkan::StreamBuffer VertexStreamBuffer;
+ Vulkan::StreamBuffer IndexStreamBuffer;
+ Vulkan::Texture FontTexture;
+};
// Forward Declarations
-bool ImGui_ImplVulkan_CreateDeviceObjects();
-void ImGui_ImplVulkan_DestroyDeviceObjects();
-void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator);
-void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator);
-void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
-void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
-void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
-void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
+static bool ImGui_ImplVulkan_CreateDeviceObjects();
+static void ImGui_ImplVulkan_DestroyDeviceObjects();
//-----------------------------------------------------------------------------
// SHADERS
@@ -216,70 +216,30 @@ static uint32_t __glsl_shader_frag_spv[] =
// FUNCTIONS
//-----------------------------------------------------------------------------
-static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
+// 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.
+// FIXME: multi-context support is not tested and probably dysfunctional in this backend.
+static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData()
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
- VkPhysicalDeviceMemoryProperties prop;
- vkGetPhysicalDeviceMemoryProperties(v->PhysicalDevice, &prop);
- for (uint32_t i = 0; i < prop.memoryTypeCount; i++)
- if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<CheckVkResultFn)
- v->CheckVkResultFn(err);
-}
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
-static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
-{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
- VkResult err;
- if (buffer != VK_NULL_HANDLE)
- vkDestroyBuffer(v->Device, buffer, v->Allocator);
- if (buffer_memory != VK_NULL_HANDLE)
- vkFreeMemory(v->Device, buffer_memory, v->Allocator);
-
- VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / g_BufferMemoryAlignment + 1) * g_BufferMemoryAlignment;
- VkBufferCreateInfo buffer_info = {};
- buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- buffer_info.size = vertex_buffer_size_aligned;
- buffer_info.usage = usage;
- buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &buffer);
- check_vk_result(err);
-
- VkMemoryRequirements req;
- vkGetBufferMemoryRequirements(v->Device, buffer, &req);
- g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;
- VkMemoryAllocateInfo alloc_info = {};
- alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- alloc_info.allocationSize = req.size;
- alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
- err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &buffer_memory);
- check_vk_result(err);
-
- err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0);
- check_vk_result(err);
- p_buffer_size = vertex_buffer_size_aligned;
-}
-
-static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height)
-{
- // Bind pipeline and descriptor sets:
+ // Bind pipeline:
{
- vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline);
+ vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
}
// Bind Vertex And Index Buffer:
+ if (draw_data->TotalVtxCount > 0)
{
- VkBuffer vertex_buffers[1] = { rb->VertexBuffer };
- VkDeviceSize vertex_offset[1] = { 0 };
+ VkBuffer vertex_buffers[1] = { bd->VertexStreamBuffer.GetBuffer() };
+ VkDeviceSize vertex_offset[1] = { bd->VertexStreamBuffer.GetCurrentOffset() };
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, vertex_offset);
- vkCmdBindIndexBuffer(command_buffer, rb->IndexBuffer, 0, sizeof(ImDrawIdx) == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32);
+ vkCmdBindIndexBuffer(command_buffer, bd->IndexStreamBuffer.GetBuffer(), bd->IndexStreamBuffer.GetCurrentOffset(), sizeof(ImDrawIdx) == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32);
}
// Setup viewport:
@@ -303,74 +263,36 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkCommandBu
float translate[2];
translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0];
translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1];
- vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);
- vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);
+ vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);
+ vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);
}
}
-static void ImGui_ImplVulkan_UpdateAndBindDescriptors(const ImDrawCmd* pcmd, VkCommandBuffer command_buffer)
-{
- const Vulkan::Texture* tex = static_cast(pcmd->TextureId);
-
- VkDescriptorSet desc_set = g_vulkan_context->AllocateDescriptorSet(g_DescriptorSetLayout);
-
- VkDescriptorImageInfo desc_image[1] = {};
- desc_image[0].sampler = g_FontSampler;
- desc_image[0].imageView = tex->GetView();
- desc_image[0].imageLayout = tex->GetLayout();
- VkWriteDescriptorSet write_desc[1] = {};
- write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- write_desc[0].dstSet = desc_set;
- write_desc[0].descriptorCount = 1;
- write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- write_desc[0].pImageInfo = desc_image;
- vkUpdateDescriptorSets(g_VulkanInitInfo.Device, 1, write_desc, 0, NULL);
- vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, &desc_set, 0, NULL);
-}
-
// 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_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer)
+void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
- int fb_width = (int)(draw_data->DisplaySize.x);
- int fb_height = (int)(draw_data->DisplaySize.y);
- if (fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount == 0)
+ 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)
return;
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
-
- // Allocate array to store enough vertex/index buffers
- ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &g_MainWindowRenderBuffers;
- if (wrb->FrameRenderBuffers == NULL)
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (draw_data->TotalVtxCount > 0)
{
- wrb->Index = 0;
- wrb->Count = Vulkan::Context::NUM_COMMAND_BUFFERS;
- wrb->FrameRenderBuffers = (ImGui_ImplVulkanH_FrameRenderBuffers*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count);
- memset(wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count);
- }
- IM_ASSERT(wrb->Count == Vulkan::Context::NUM_COMMAND_BUFFERS);
- wrb->Index = (wrb->Index + 1) % wrb->Count;
- ImGui_ImplVulkanH_FrameRenderBuffers* rb = &wrb->FrameRenderBuffers[g_vulkan_context->GetCurrentCommandBufferIndex()];
+ // Create or resize the vertex/index buffers
+ const size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
+ const size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
+ if (!bd->VertexStreamBuffer.ReserveMemory(vertex_size, sizeof(ImDrawVert)) ||
+ !bd->IndexStreamBuffer.ReserveMemory(index_size, sizeof(ImDrawIdx)))
+ {
+ // this is annoying, because we can't restart the render pass...
+ return;
+ }
- VkResult err;
-
- // Create or resize the vertex/index buffers
- size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
- size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
- if (rb->VertexBuffer == VK_NULL_HANDLE || rb->VertexBufferSize < vertex_size)
- CreateOrResizeBuffer(rb->VertexBuffer, rb->VertexBufferMemory, rb->VertexBufferSize, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
- if (rb->IndexBuffer == VK_NULL_HANDLE || rb->IndexBufferSize < index_size)
- CreateOrResizeBuffer(rb->IndexBuffer, rb->IndexBufferMemory, rb->IndexBufferSize, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
-
- // Upload vertex/index data into a single contiguous GPU buffer
- {
- ImDrawVert* vtx_dst = NULL;
- ImDrawIdx* idx_dst = NULL;
- err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, rb->VertexBufferSize, 0, (void**)(&vtx_dst));
- check_vk_result(err);
- err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, rb->IndexBufferSize, 0, (void**)(&idx_dst));
- check_vk_result(err);
+ // Upload vertex/index data into a single contiguous GPU buffer
+ ImDrawVert* vtx_dst = (ImDrawVert*)bd->VertexStreamBuffer.GetCurrentHostPointer();
+ ImDrawIdx* idx_dst = (ImDrawIdx*)bd->IndexStreamBuffer.GetCurrentHostPointer();
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -379,29 +301,23 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
vtx_dst += cmd_list->VtxBuffer.Size;
idx_dst += cmd_list->IdxBuffer.Size;
}
- VkMappedMemoryRange range[2] = {};
- range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
- range[0].memory = rb->VertexBufferMemory;
- range[0].size = VK_WHOLE_SIZE;
- range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
- range[1].memory = rb->IndexBufferMemory;
- range[1].size = VK_WHOLE_SIZE;
- err = vkFlushMappedMemoryRanges(v->Device, 2, range);
- check_vk_result(err);
- vkUnmapMemory(v->Device, rb->VertexBufferMemory);
- vkUnmapMemory(v->Device, rb->IndexBufferMemory);
- }
- // Setup desired Vulkan state
- ImGui_ImplVulkan_SetupRenderState(draw_data, command_buffer, rb, fb_width, fb_height);
+ // Setup desired Vulkan state (must come before buffer commit)
+ ImGui_ImplVulkan_SetupRenderState(draw_data, bd->Pipeline, g_vulkan_context->GetCurrentCommandBuffer(), fb_width, fb_height);
+ bd->VertexStreamBuffer.CommitMemory(vertex_size);
+ bd->IndexStreamBuffer.CommitMemory(index_size);
+ }
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
+ ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
// 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;
+ const Vulkan::Texture* last_texture = nullptr;
+ VkCommandBuffer command_buffer = g_vulkan_context->GetCurrentCommandBuffer();
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -413,259 +329,226 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
// 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_ImplVulkan_SetupRenderState(draw_data, command_buffer, rb, fb_width, fb_height);
+ ImGui_ImplVulkan_SetupRenderState(draw_data, bd->Pipeline, command_buffer, fb_width, fb_height);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
// Project scissor/clipping rectangles into framebuffer space
- ImVec4 clip_rect;
- clip_rect.x = (pcmd->ClipRect.x - clip_off.x);
- clip_rect.y = (pcmd->ClipRect.y - clip_off.y);
- clip_rect.z = (pcmd->ClipRect.z - clip_off.x);
- clip_rect.w = (pcmd->ClipRect.w - clip_off.y);
+ 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);
- if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
+ // Clamp to viewport as vkCmdSetScissor() 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; }
+ if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle
+ VkRect2D scissor;
+ scissor.offset.x = (int32_t)(clip_min.x);
+ scissor.offset.y = (int32_t)(clip_min.y);
+ scissor.extent.width = (uint32_t)(clip_max.x - clip_min.x);
+ scissor.extent.height = (uint32_t)(clip_max.y - clip_min.y);
+ vkCmdSetScissor(command_buffer, 0, 1, &scissor);
+
+ // Bind DescriptorSet with font or user texture
+ const Vulkan::Texture* tex = (const Vulkan::Texture*)pcmd->TextureId;
+ if (tex && last_texture != tex)
{
- ImGui_ImplVulkan_UpdateAndBindDescriptors(pcmd, command_buffer);
+ // if we can't get a descriptor set, we'll we're in trouble, since we can't restart the render pass from here.
+ VkDescriptorSet ds = g_vulkan_context->AllocateDescriptorSet(bd->DescriptorSetLayout);
+ if (ds == VK_NULL_HANDLE)
+ {
+ continue;
+ }
- // Negative offsets are illegal for vkCmdSetScissor
- if (clip_rect.x < 0.0f)
- clip_rect.x = 0.0f;
- if (clip_rect.y < 0.0f)
- clip_rect.y = 0.0f;
-
- // Apply scissor/clipping rectangle
- VkRect2D scissor;
- scissor.offset.x = (int32_t)(clip_rect.x);
- scissor.offset.y = (int32_t)(clip_rect.y);
- scissor.extent.width = (uint32_t)(clip_rect.z - clip_rect.x);
- scissor.extent.height = (uint32_t)(clip_rect.w - clip_rect.y);
- vkCmdSetScissor(command_buffer, 0, 1, &scissor);
-
- // Draw
- vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
+ Vulkan::DescriptorSetUpdateBuilder dsb;
+ dsb.AddCombinedImageSamplerDescriptorWrite(ds, 0, tex->GetView(), bd->FontSampler);
+ dsb.Update(g_vulkan_context->GetDevice());
+ vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, &ds, 0, nullptr);
+ last_texture = tex;
}
+
+ // Draw
+ vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
}
}
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
+
+ // Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
+ // Our last values will leak into user/application rendering IF:
+ // - Your app uses a pipeline with VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR dynamic state
+ // - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitely set that state.
+ // If you use VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR you are responsible for setting the values before rendering.
+ // In theory we should aim to backup/restore those values but I am not sure this is possible.
+ // We perform a call to vkCmdSetScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
+ VkRect2D scissor = { { 0, 0 }, { (uint32_t)fb_width, (uint32_t)fb_height } };
+ vkCmdSetScissor(command_buffer, 0, 1, &scissor);
}
-bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
+bool ImGui_ImplVulkan_CreateFontsTexture()
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
- size_t upload_size = width*height*4*sizeof(char);
- VkResult err;
-
- // Create the Image:
+ if (bd->FontTexture.GetWidth() != static_cast(width) || bd->FontTexture.GetHeight() != static_cast(height))
{
- VkImageCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- info.imageType = VK_IMAGE_TYPE_2D;
- info.format = VK_FORMAT_R8G8B8A8_UNORM;
- info.extent.width = width;
- info.extent.height = height;
- info.extent.depth = 1;
- info.mipLevels = 1;
- info.arrayLayers = 1;
- info.samples = VK_SAMPLE_COUNT_1_BIT;
- info.tiling = VK_IMAGE_TILING_OPTIMAL;
- info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- err = vkCreateImage(v->Device, &info, v->Allocator, &g_FontImage);
- check_vk_result(err);
- VkMemoryRequirements req;
- vkGetImageMemoryRequirements(v->Device, g_FontImage, &req);
- VkMemoryAllocateInfo alloc_info = {};
- alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- alloc_info.allocationSize = req.size;
- alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);
- err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &g_FontMemory);
- check_vk_result(err);
- err = vkBindImageMemory(v->Device, g_FontImage, g_FontMemory, 0);
- check_vk_result(err);
+ if (!bd->FontTexture.Create(width, height, 1, 1, VK_FORMAT_R8G8B8A8_UNORM,
+ VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT))
+ {
+ return false;
+ }
}
- // Create the Image View:
- {
- g_FontTexture.Adopt(g_FontImage, VK_IMAGE_VIEW_TYPE_2D, width, height, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT);
- g_FontTexture.TransitionToLayout(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
- }
+ const size_t upload_size = width * height * 4 * sizeof(unsigned char);
+ const VkBufferCreateInfo bci = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, nullptr, 0,
+ static_cast(upload_size), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_SHARING_MODE_EXCLUSIVE, 0, nullptr};
+ VmaAllocationCreateInfo aci = {};
+ aci.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
+ aci.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
- // Create the Upload Buffer:
- {
- VkBufferCreateInfo buffer_info = {};
- buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- buffer_info.size = upload_size;
- buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &g_UploadBuffer);
- check_vk_result(err);
- VkMemoryRequirements req;
- vkGetBufferMemoryRequirements(v->Device, g_UploadBuffer, &req);
- g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;
- VkMemoryAllocateInfo alloc_info = {};
- alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- alloc_info.allocationSize = req.size;
- alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
- err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &g_UploadBufferMemory);
- check_vk_result(err);
- err = vkBindBufferMemory(v->Device, g_UploadBuffer, g_UploadBufferMemory, 0);
- check_vk_result(err);
- }
+ VmaAllocationInfo ai;
+ VkBuffer buffer;
+ VmaAllocation allocation;
+ VkResult res = vmaCreateBuffer(g_vulkan_context->GetAllocator(), &bci, &aci, &buffer, &allocation, &ai);
+ if (res != VK_SUCCESS)
+ return false;
- // Upload to Buffer:
- {
- char* map = NULL;
- err = vkMapMemory(v->Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map));
- check_vk_result(err);
- memcpy(map, pixels, upload_size);
- VkMappedMemoryRange range[1] = {};
- range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
- range[0].memory = g_UploadBufferMemory;
- range[0].size = upload_size;
- err = vkFlushMappedMemoryRanges(v->Device, 1, range);
- check_vk_result(err);
- vkUnmapMemory(v->Device, g_UploadBufferMemory);
- }
+ std::memcpy(ai.pMappedData, pixels, upload_size);
+ vmaFlushAllocation(g_vulkan_context->GetAllocator(), allocation, 0, upload_size);
+ bd->FontTexture.TransitionToLayout(g_vulkan_context->GetCurrentInitCommandBuffer(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ bd->FontTexture.UpdateFromBuffer(g_vulkan_context->GetCurrentInitCommandBuffer(), 0, 0, 0, 0, width, height, width, buffer, 0);
+ bd->FontTexture.TransitionToLayout(g_vulkan_context->GetCurrentInitCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
- // Copy to Image:
- {
- VkImageMemoryBarrier copy_barrier[1] = {};
- copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- copy_barrier[0].image = g_FontImage;
- copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copy_barrier[0].subresourceRange.levelCount = 1;
- copy_barrier[0].subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier);
-
- VkBufferImageCopy region = {};
- region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- region.imageSubresource.layerCount = 1;
- region.imageExtent.width = width;
- region.imageExtent.height = height;
- region.imageExtent.depth = 1;
- vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
-
- VkImageMemoryBarrier use_barrier[1] = {};
- use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
- use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- use_barrier[0].image = g_FontImage;
- use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- use_barrier[0].subresourceRange.levelCount = 1;
- use_barrier[0].subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier);
- }
+ // Immediately queue it for freeing after the command buffer finishes, since it's only needed for the copy.
+ g_vulkan_context->DeferBufferDestruction(buffer, allocation);
// Store our identifier
- io.Fonts->TexID = (ImTextureID)(intptr_t)&g_FontTexture;
- io.Fonts->ClearTexData();
-
+ io.Fonts->SetTexID((ImTextureID)&bd->FontTexture);
return true;
}
-bool ImGui_ImplVulkan_CreateDeviceObjects()
+static bool ImGui_ImplVulkan_CreateShaderModules(VkDevice device)
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
- VkResult err;
- VkShaderModule vert_module;
- VkShaderModule frag_module;
-
- // Create The Shader Modules:
+ // Create the shader modules
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->ShaderModuleVert == VK_NULL_HANDLE)
{
VkShaderModuleCreateInfo vert_info = {};
vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
- err = vkCreateShaderModule(v->Device, &vert_info, v->Allocator, &vert_module);
- check_vk_result(err);
+ VkResult err = vkCreateShaderModule(device, &vert_info, nullptr, &bd->ShaderModuleVert);
+ if (err != VK_SUCCESS)
+ return false;
+ }
+ if (bd->ShaderModuleFrag == VK_NULL_HANDLE)
+ {
VkShaderModuleCreateInfo frag_info = {};
frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
- err = vkCreateShaderModule(v->Device, &frag_info, v->Allocator, &frag_module);
- check_vk_result(err);
+ VkResult err = vkCreateShaderModule(device, &frag_info, nullptr, &bd->ShaderModuleFrag);
+ if (err != VK_SUCCESS)
+ return false;
}
- if (!g_FontSampler)
- {
- VkSamplerCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
- info.magFilter = VK_FILTER_LINEAR;
- info.minFilter = VK_FILTER_LINEAR;
- info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
- info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
- info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
- info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
- info.minLod = -1000;
- info.maxLod = 1000;
- info.maxAnisotropy = 1.0f;
- err = vkCreateSampler(v->Device, &info, v->Allocator, &g_FontSampler);
- check_vk_result(err);
- }
+ return true;
+}
- if (!g_DescriptorSetLayout)
- {
- VkSampler sampler[1] = {g_FontSampler};
- VkDescriptorSetLayoutBinding binding[1] = {};
- binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- binding[0].descriptorCount = 1;
- binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
- binding[0].pImmutableSamplers = sampler;
- VkDescriptorSetLayoutCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
- info.bindingCount = 1;
- info.pBindings = binding;
- err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &g_DescriptorSetLayout);
- check_vk_result(err);
- }
+static bool ImGui_ImplVulkan_CreateFontSampler(VkDevice device)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->FontSampler)
+ return true;
- if (!g_PipelineLayout)
- {
- // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
- VkPushConstantRange push_constants[1] = {};
- push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
- push_constants[0].offset = sizeof(float) * 0;
- push_constants[0].size = sizeof(float) * 4;
- VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout };
- VkPipelineLayoutCreateInfo layout_info = {};
- layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
- layout_info.setLayoutCount = 1;
- layout_info.pSetLayouts = set_layout;
- layout_info.pushConstantRangeCount = 1;
- layout_info.pPushConstantRanges = push_constants;
- err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &g_PipelineLayout);
- check_vk_result(err);
- }
+ // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
+ VkSamplerCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ info.magFilter = VK_FILTER_LINEAR;
+ info.minFilter = VK_FILTER_LINEAR;
+ info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+ info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+ info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
+ info.minLod = -1000;
+ info.maxLod = 1000;
+ info.maxAnisotropy = 1.0f;
+ VkResult err = vkCreateSampler(device, &info, nullptr, &bd->FontSampler);
+ return (err == VK_SUCCESS);
+}
+
+static bool ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->DescriptorSetLayout)
+ return true;
+
+ if (!ImGui_ImplVulkan_CreateFontSampler(device))
+ return false;
+
+ VkSampler sampler[1] = { bd->FontSampler };
+ VkDescriptorSetLayoutBinding binding[1] = {};
+ binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ binding[0].descriptorCount = 1;
+ binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+ binding[0].pImmutableSamplers = sampler;
+ VkDescriptorSetLayoutCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ info.bindingCount = 1;
+ info.pBindings = binding;
+ VkResult err = vkCreateDescriptorSetLayout(device, &info, nullptr, &bd->DescriptorSetLayout);
+ return (err == VK_SUCCESS);
+}
+
+static bool ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->PipelineLayout)
+ return true;
+
+ // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
+ ImGui_ImplVulkan_CreateDescriptorSetLayout(device);
+ VkPushConstantRange push_constants[1] = {};
+ push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+ push_constants[0].offset = sizeof(float) * 0;
+ push_constants[0].size = sizeof(float) * 4;
+ VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout };
+ VkPipelineLayoutCreateInfo layout_info = {};
+ layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ layout_info.setLayoutCount = 1;
+ layout_info.pSetLayouts = set_layout;
+ layout_info.pushConstantRangeCount = 1;
+ layout_info.pPushConstantRanges = push_constants;
+ VkResult err = vkCreatePipelineLayout(device, &layout_info, nullptr, &bd->PipelineLayout);
+ return (err == VK_SUCCESS);
+}
+
+static bool ImGui_ImplVulkan_CreatePipeline(VkDevice device, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkPipeline* pipeline)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (!ImGui_ImplVulkan_CreateShaderModules(device))
+ return false;
VkPipelineShaderStageCreateInfo stage[2] = {};
stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
- stage[0].module = vert_module;
+ stage[0].module = bd->ShaderModuleVert;
stage[0].pName = "main";
stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
- stage[1].module = frag_module;
+ stage[1].module = bd->ShaderModuleFrag;
stage[1].pName = "main";
VkVertexInputBindingDescription binding_desc[1] = {};
@@ -711,18 +594,15 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
VkPipelineMultisampleStateCreateInfo ms_info = {};
ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- if (v->MSAASamples != 0)
- ms_info.rasterizationSamples = v->MSAASamples;
- else
- ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
VkPipelineColorBlendAttachmentState color_attachment[1] = {};
color_attachment[0].blendEnable = VK_TRUE;
color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD;
- color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
- color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
+ color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+ color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD;
color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
@@ -740,9 +620,12 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states);
dynamic_state.pDynamicStates = dynamic_states;
+ if (!ImGui_ImplVulkan_CreatePipelineLayout(device))
+ return false;
+
VkGraphicsPipelineCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- info.flags = g_PipelineCreateFlags;
+ info.flags = bd->PipelineCreateFlags;
info.stageCount = 2;
info.pStages = stage;
info.pVertexInputState = &vertex_info;
@@ -753,455 +636,71 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
info.pDepthStencilState = &depth_info;
info.pColorBlendState = &blend_info;
info.pDynamicState = &dynamic_state;
- info.layout = g_PipelineLayout;
- info.renderPass = g_RenderPass;
- err = vkCreateGraphicsPipelines(v->Device, v->PipelineCache, 1, &info, v->Allocator, &g_Pipeline);
- check_vk_result(err);
-
- vkDestroyShaderModule(v->Device, vert_module, v->Allocator);
- vkDestroyShaderModule(v->Device, frag_module, v->Allocator);
-
- return true;
+ info.layout = bd->PipelineLayout;
+ info.renderPass = renderPass;
+ info.subpass = 0;
+ VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, nullptr, pipeline);
+ return (err == VK_SUCCESS);
}
-void ImGui_ImplVulkan_DestroyFontObjects()
+bool ImGui_ImplVulkan_CreateDeviceObjects()
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
- if (g_UploadBuffer)
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+
+ if (!bd->VertexStreamBuffer.Create(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VERTEX_BUFFER_SIZE) ||
+ !bd->IndexStreamBuffer.Create(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, INDEX_BUFFER_SIZE))
{
- vkDestroyBuffer(v->Device, g_UploadBuffer, v->Allocator);
- g_UploadBuffer = VK_NULL_HANDLE;
- }
- if (g_UploadBufferMemory)
- {
- vkFreeMemory(v->Device, g_UploadBufferMemory, v->Allocator);
- g_UploadBufferMemory = VK_NULL_HANDLE;
+ return false;
}
- g_FontTexture.Destroy(false);
- if (g_FontImage) { vkDestroyImage(v->Device, g_FontImage, v->Allocator); g_FontImage = VK_NULL_HANDLE; }
- if (g_FontMemory) { vkFreeMemory(v->Device, g_FontMemory, v->Allocator); g_FontMemory = VK_NULL_HANDLE; }
+ if (!ImGui_ImplVulkan_CreatePipeline(g_vulkan_context->GetDevice(), VK_NULL_HANDLE, bd->RenderPass, &bd->Pipeline))
+ return false;
+
+ return true;
}
void ImGui_ImplVulkan_DestroyDeviceObjects()
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
- ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator);
- ImGui_ImplVulkan_DestroyFontObjects();
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
- if (g_FontSampler) { vkDestroySampler(v->Device, g_FontSampler, v->Allocator); g_FontSampler = VK_NULL_HANDLE; }
- if (g_DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, g_DescriptorSetLayout, v->Allocator); g_DescriptorSetLayout = VK_NULL_HANDLE; }
- if (g_PipelineLayout) { vkDestroyPipelineLayout(v->Device, g_PipelineLayout, v->Allocator); g_PipelineLayout = VK_NULL_HANDLE; }
- if (g_Pipeline) { vkDestroyPipeline(v->Device, g_Pipeline, v->Allocator); g_Pipeline = VK_NULL_HANDLE; }
+ bd->VertexStreamBuffer.Destroy(false);
+ bd->IndexStreamBuffer.Destroy(false);
+ bd->FontTexture.Destroy(false);
+
+ if (bd->ShaderModuleVert) { vkDestroyShaderModule(g_vulkan_context->GetDevice(), bd->ShaderModuleVert, nullptr); bd->ShaderModuleVert = VK_NULL_HANDLE; }
+ if (bd->ShaderModuleFrag) { vkDestroyShaderModule(g_vulkan_context->GetDevice(), bd->ShaderModuleFrag, nullptr); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
+ if (bd->FontSampler) { vkDestroySampler(g_vulkan_context->GetDevice(), bd->FontSampler, nullptr); bd->FontSampler = VK_NULL_HANDLE; }
+ if (bd->DescriptorSetLayout) { vkDestroyDescriptorSetLayout(g_vulkan_context->GetDevice(), bd->DescriptorSetLayout, nullptr); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
+ if (bd->PipelineLayout) { vkDestroyPipelineLayout(g_vulkan_context->GetDevice(), bd->PipelineLayout, nullptr); bd->PipelineLayout = VK_NULL_HANDLE; }
+ if (bd->Pipeline) { vkDestroyPipeline(g_vulkan_context->GetDevice(), bd->Pipeline, nullptr); bd->Pipeline = VK_NULL_HANDLE; }
}
-bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass)
+bool ImGui_ImplVulkan_Init(VkRenderPass render_pass)
{
- // Setup back-end capabilities flags
ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplVulkan_Data* bd = IM_NEW(ImGui_ImplVulkan_Data)();
+ io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_vulkan";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
- IM_ASSERT(info->Instance != VK_NULL_HANDLE);
- IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE);
- IM_ASSERT(info->Device != VK_NULL_HANDLE);
- IM_ASSERT(info->Queue != VK_NULL_HANDLE);
- IM_ASSERT(info->MinImageCount >= 2);
- IM_ASSERT(info->ImageCount >= info->MinImageCount);
IM_ASSERT(render_pass != VK_NULL_HANDLE);
- g_VulkanInitInfo = *info;
- g_RenderPass = render_pass;
- ImGui_ImplVulkan_CreateDeviceObjects();
+ bd->RenderPass = render_pass;
- return true;
+ return ImGui_ImplVulkan_CreateDeviceObjects();
}
void ImGui_ImplVulkan_Shutdown()
{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
ImGui_ImplVulkan_DestroyDeviceObjects();
-}
-
-void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
-{
- IM_ASSERT(min_image_count >= 2);
- if (g_VulkanInitInfo.MinImageCount == min_image_count)
- return;
-
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
- VkResult err = vkDeviceWaitIdle(v->Device);
- check_vk_result(err);
- ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator);
- g_VulkanInitInfo.MinImageCount = min_image_count;
-}
-
-
-//-------------------------------------------------------------------------
-// Internal / Miscellaneous Vulkan Helpers
-// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
-//-------------------------------------------------------------------------
-// You probably do NOT need to use or care about those functions.
-// Those functions only exist because:
-// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
-// 2) the upcoming multi-viewport feature will need them internally.
-// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings,
-// but it is too much code to duplicate everywhere so we exceptionally expose them.
-//
-// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
-// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
-// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
-//-------------------------------------------------------------------------
-
-VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)
-{
- IM_ASSERT(request_formats != NULL);
- IM_ASSERT(request_formats_count > 0);
-
- // Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation
- // Assuming that the default behavior is without setting this bit, there is no need for separate Swapchain image and image view format
- // Additionally several new color spaces were introduced with Vulkan Spec v1.0.40,
- // hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used.
- uint32_t avail_count;
- vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, NULL);
- ImVector avail_format;
- avail_format.resize((int)avail_count);
- vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, avail_format.Data);
-
- // First check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available
- if (avail_count == 1)
- {
- if (avail_format[0].format == VK_FORMAT_UNDEFINED)
- {
- VkSurfaceFormatKHR ret;
- ret.format = request_formats[0];
- ret.colorSpace = request_color_space;
- return ret;
- }
- else
- {
- // No point in searching another format
- return avail_format[0];
- }
- }
- else
- {
- // Request several formats, the first found will be used
- for (int request_i = 0; request_i < request_formats_count; request_i++)
- for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)
- if (avail_format[avail_i].format == request_formats[request_i] && avail_format[avail_i].colorSpace == request_color_space)
- return avail_format[avail_i];
-
- // If none of the requested image formats could be found, use the first available
- return avail_format[0];
- }
-}
-
-VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)
-{
- IM_ASSERT(request_modes != NULL);
- IM_ASSERT(request_modes_count > 0);
-
- // Request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
- uint32_t avail_count = 0;
- vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, NULL);
- ImVector avail_modes;
- avail_modes.resize((int)avail_count);
- vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, avail_modes.Data);
- //for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)
- // printf("[vulkan] avail_modes[%d] = %d\n", avail_i, avail_modes[avail_i]);
-
- for (int request_i = 0; request_i < request_modes_count; request_i++)
- for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)
- if (request_modes[request_i] == avail_modes[avail_i])
- return request_modes[request_i];
-
- return VK_PRESENT_MODE_FIFO_KHR; // Always available
-}
-
-void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator)
-{
- IM_ASSERT(physical_device != VK_NULL_HANDLE && device != VK_NULL_HANDLE);
- (void)physical_device;
- (void)allocator;
-
- // Create Command Buffers
- VkResult err;
- for (uint32_t i = 0; i < wd->ImageCount; i++)
- {
- ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
- ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i];
- {
- VkCommandPoolCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- info.queueFamilyIndex = queue_family;
- err = vkCreateCommandPool(device, &info, allocator, &fd->CommandPool);
- check_vk_result(err);
- }
- {
- VkCommandBufferAllocateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- info.commandPool = fd->CommandPool;
- info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- info.commandBufferCount = 1;
- err = vkAllocateCommandBuffers(device, &info, &fd->CommandBuffer);
- check_vk_result(err);
- }
- {
- VkFenceCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
- err = vkCreateFence(device, &info, allocator, &fd->Fence);
- check_vk_result(err);
- }
- {
- VkSemaphoreCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- err = vkCreateSemaphore(device, &info, allocator, &fsd->ImageAcquiredSemaphore);
- check_vk_result(err);
- err = vkCreateSemaphore(device, &info, allocator, &fsd->RenderCompleteSemaphore);
- check_vk_result(err);
- }
- }
-}
-
-int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode)
-{
- if (present_mode == VK_PRESENT_MODE_MAILBOX_KHR)
- return 3;
- if (present_mode == VK_PRESENT_MODE_FIFO_KHR || present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR)
- return 2;
- if (present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR)
- return 1;
- IM_ASSERT(0);
- return 1;
-}
-
-// Also destroy old swap chain and in-flight frames data, if any.
-void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count)
-{
- VkResult err;
- VkSwapchainKHR old_swapchain = wd->Swapchain;
- err = vkDeviceWaitIdle(device);
- check_vk_result(err);
-
- // We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.
- // Destroy old Framebuffer
- for (uint32_t i = 0; i < wd->ImageCount; i++)
- {
- ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
- ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
- }
- IM_FREE(wd->Frames);
- IM_FREE(wd->FrameSemaphores);
- wd->Frames = NULL;
- wd->FrameSemaphores = NULL;
- wd->ImageCount = 0;
- if (wd->RenderPass)
- vkDestroyRenderPass(device, wd->RenderPass, allocator);
-
- // If min image count was not specified, request different count of images dependent on selected present mode
- if (min_image_count == 0)
- min_image_count = ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(wd->PresentMode);
-
- // Create Swapchain
- {
- VkSwapchainCreateInfoKHR info = {};
- info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
- info.surface = wd->Surface;
- info.minImageCount = min_image_count;
- info.imageFormat = wd->SurfaceFormat.format;
- info.imageColorSpace = wd->SurfaceFormat.colorSpace;
- info.imageArrayLayers = 1;
- info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
- info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family
- info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- info.presentMode = wd->PresentMode;
- info.clipped = VK_TRUE;
- info.oldSwapchain = old_swapchain;
- VkSurfaceCapabilitiesKHR cap;
- err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap);
- check_vk_result(err);
- if (info.minImageCount < cap.minImageCount)
- info.minImageCount = cap.minImageCount;
- else if (cap.maxImageCount != 0 && info.minImageCount > cap.maxImageCount)
- info.minImageCount = cap.maxImageCount;
-
- if (cap.currentExtent.width == 0xffffffff)
- {
- info.imageExtent.width = wd->Width = w;
- info.imageExtent.height = wd->Height = h;
- }
- else
- {
- info.imageExtent.width = wd->Width = cap.currentExtent.width;
- info.imageExtent.height = wd->Height = cap.currentExtent.height;
- }
- err = vkCreateSwapchainKHR(device, &info, allocator, &wd->Swapchain);
- check_vk_result(err);
- err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, NULL);
- check_vk_result(err);
- VkImage backbuffers[16] = {};
- IM_ASSERT(wd->ImageCount >= min_image_count);
- IM_ASSERT(wd->ImageCount < IM_ARRAYSIZE(backbuffers));
- err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
- check_vk_result(err);
-
- IM_ASSERT(wd->Frames == NULL);
- wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount);
- wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->ImageCount);
- memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount);
- memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->ImageCount);
- for (uint32_t i = 0; i < wd->ImageCount; i++)
- wd->Frames[i].Backbuffer = backbuffers[i];
- }
- if (old_swapchain)
- vkDestroySwapchainKHR(device, old_swapchain, allocator);
-
- // Create the Render Pass
- {
- VkAttachmentDescription attachment = {};
- attachment.format = wd->SurfaceFormat.format;
- attachment.samples = VK_SAMPLE_COUNT_1_BIT;
- attachment.loadOp = wd->ClearEnable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- VkAttachmentReference color_attachment = {};
- color_attachment.attachment = 0;
- color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- VkSubpassDescription subpass = {};
- subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpass.colorAttachmentCount = 1;
- subpass.pColorAttachments = &color_attachment;
- VkSubpassDependency dependency = {};
- dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
- dependency.dstSubpass = 0;
- dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- dependency.srcAccessMask = 0;
- dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- VkRenderPassCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- info.attachmentCount = 1;
- info.pAttachments = &attachment;
- info.subpassCount = 1;
- info.pSubpasses = &subpass;
- info.dependencyCount = 1;
- info.pDependencies = &dependency;
- err = vkCreateRenderPass(device, &info, allocator, &wd->RenderPass);
- check_vk_result(err);
- }
-
- // Create The Image Views
- {
- VkImageViewCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- info.viewType = VK_IMAGE_VIEW_TYPE_2D;
- info.format = wd->SurfaceFormat.format;
- info.components.r = VK_COMPONENT_SWIZZLE_R;
- info.components.g = VK_COMPONENT_SWIZZLE_G;
- info.components.b = VK_COMPONENT_SWIZZLE_B;
- info.components.a = VK_COMPONENT_SWIZZLE_A;
- VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
- info.subresourceRange = image_range;
- for (uint32_t i = 0; i < wd->ImageCount; i++)
- {
- ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
- info.image = fd->Backbuffer;
- err = vkCreateImageView(device, &info, allocator, &fd->BackbufferView);
- check_vk_result(err);
- }
- }
-
- // Create Framebuffer
- {
- VkImageView attachment[1];
- VkFramebufferCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- info.renderPass = wd->RenderPass;
- info.attachmentCount = 1;
- info.pAttachments = attachment;
- info.width = wd->Width;
- info.height = wd->Height;
- info.layers = 1;
- for (uint32_t i = 0; i < wd->ImageCount; i++)
- {
- ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
- attachment[0] = fd->BackbufferView;
- err = vkCreateFramebuffer(device, &info, allocator, &fd->Framebuffer);
- check_vk_result(err);
- }
- }
-}
-
-void ImGui_ImplVulkanH_CreateWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count)
-{
- (void)instance;
- ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count);
- ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator);
-}
-
-void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator)
-{
- vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)
- //vkQueueWaitIdle(g_Queue);
-
- for (uint32_t i = 0; i < wd->ImageCount; i++)
- {
- ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
- ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
- }
- IM_FREE(wd->Frames);
- IM_FREE(wd->FrameSemaphores);
- wd->Frames = NULL;
- wd->FrameSemaphores = NULL;
- vkDestroyRenderPass(device, wd->RenderPass, allocator);
- vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
- vkDestroySurfaceKHR(instance, wd->Surface, allocator);
-
- *wd = ImGui_ImplVulkanH_Window();
-}
-
-void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator)
-{
- vkDestroyFence(device, fd->Fence, allocator);
- vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);
- vkDestroyCommandPool(device, fd->CommandPool, allocator);
- fd->Fence = VK_NULL_HANDLE;
- fd->CommandBuffer = VK_NULL_HANDLE;
- fd->CommandPool = VK_NULL_HANDLE;
-
- vkDestroyImageView(device, fd->BackbufferView, allocator);
- vkDestroyFramebuffer(device, fd->Framebuffer, allocator);
-}
-
-void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator)
-{
- vkDestroySemaphore(device, fsd->ImageAcquiredSemaphore, allocator);
- vkDestroySemaphore(device, fsd->RenderCompleteSemaphore, allocator);
- fsd->ImageAcquiredSemaphore = fsd->RenderCompleteSemaphore = VK_NULL_HANDLE;
-}
-
-void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
-{
- if (buffers->VertexBuffer) { vkDestroyBuffer(device, buffers->VertexBuffer, allocator); buffers->VertexBuffer = VK_NULL_HANDLE; }
- if (buffers->VertexBufferMemory) { vkFreeMemory(device, buffers->VertexBufferMemory, allocator); buffers->VertexBufferMemory = VK_NULL_HANDLE; }
- if (buffers->IndexBuffer) { vkDestroyBuffer(device, buffers->IndexBuffer, allocator); buffers->IndexBuffer = VK_NULL_HANDLE; }
- if (buffers->IndexBufferMemory) { vkFreeMemory(device, buffers->IndexBufferMemory, allocator); buffers->IndexBufferMemory = VK_NULL_HANDLE; }
- buffers->VertexBufferSize = 0;
- buffers->IndexBufferSize = 0;
-}
-
-void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
-{
- for (uint32_t n = 0; n < buffers->Count; n++)
- ImGui_ImplVulkanH_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator);
- IM_FREE(buffers->FrameRenderBuffers);
- buffers->FrameRenderBuffers = NULL;
- buffers->Index = 0;
- buffers->Count = 0;
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
}
diff --git a/pcsx2/Frontend/imgui_impl_vulkan.h b/pcsx2/Frontend/imgui_impl_vulkan.h
index 7a28c38b51..e6732431c6 100644
--- a/pcsx2/Frontend/imgui_impl_vulkan.h
+++ b/pcsx2/Frontend/imgui_impl_vulkan.h
@@ -1,125 +1,13 @@
-// dear imgui: Renderer for Vulkan
-// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
-
-// Implemented features:
-// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
-// Missing features:
-// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914
-
-// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
-// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
-// https://github.com/ocornut/imgui
-
-// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
-// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
-
-// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
-// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
-// You will use those if you want to use this rendering back-end in your engine/app.
-// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
-// the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
-// Read comments in imgui_impl_vulkan.h.
+// dear imgui: Renderer Backend for Vulkan
+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
#pragma once
-
-#include "imgui.h"
+#include "imgui.h" // IMGUI_IMPL_API
#include "common/Vulkan/Loader.h"
-// Initialization data, for ImGui_ImplVulkan_Init()
-// [Please zero-clear before use!]
-struct ImGui_ImplVulkan_InitInfo
-{
- VkInstance Instance;
- VkPhysicalDevice PhysicalDevice;
- VkDevice Device;
- uint32_t QueueFamily;
- VkQueue Queue;
- VkPipelineCache PipelineCache;
- uint32_t MinImageCount; // >= 2
- uint32_t ImageCount; // >= MinImageCount
- VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT
- const VkAllocationCallbacks* Allocator;
- void (*CheckVkResultFn)(VkResult err);
-};
-
// Called by user code
-IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
-IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown();
-IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer);
-IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
-IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontObjects();
-IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
-
-
-//-------------------------------------------------------------------------
-// Internal / Miscellaneous Vulkan Helpers
-// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.)
-//-------------------------------------------------------------------------
-// You probably do NOT need to use or care about those functions.
-// Those functions only exist because:
-// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
-// 2) the upcoming multi-viewport feature will need them internally.
-// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings,
-// but it is too much code to duplicate everywhere so we exceptionally expose them.
-//
-// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
-// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
-// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
-//-------------------------------------------------------------------------
-
-struct ImGui_ImplVulkanH_Frame;
-struct ImGui_ImplVulkanH_Window;
-
-// Helpers
-IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
-IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator);
-IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
-IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
-IMGUI_IMPL_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode);
-
-// Helper structure to hold the data needed by one rendering frame
-// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
-// [Please zero-clear before use!]
-struct ImGui_ImplVulkanH_Frame
-{
- VkCommandPool CommandPool;
- VkCommandBuffer CommandBuffer;
- VkFence Fence;
- VkImage Backbuffer;
- VkImageView BackbufferView;
- VkFramebuffer Framebuffer;
-};
-
-struct ImGui_ImplVulkanH_FrameSemaphores
-{
- VkSemaphore ImageAcquiredSemaphore;
- VkSemaphore RenderCompleteSemaphore;
-};
-
-// Helper structure to hold the data needed by one rendering context into one OS window
-// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
-struct ImGui_ImplVulkanH_Window
-{
- int Width;
- int Height;
- VkSwapchainKHR Swapchain;
- VkSurfaceKHR Surface;
- VkSurfaceFormatKHR SurfaceFormat;
- VkPresentModeKHR PresentMode;
- VkRenderPass RenderPass;
- bool ClearEnable;
- VkClearValue ClearValue;
- uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
- uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
- uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
- ImGui_ImplVulkanH_Frame* Frames;
- ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores;
-
- ImGui_ImplVulkanH_Window()
- {
- memset(this, 0, sizeof(*this));
- PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
- ClearEnable = true;
- }
-};
-
+bool ImGui_ImplVulkan_Init(VkRenderPass render_pass);
+void ImGui_ImplVulkan_Shutdown();
+void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data);
+bool ImGui_ImplVulkan_CreateFontsTexture();
+void ImGui_ImplVulkan_DestroyFontUploadObjects();
diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj
index 91756d8f3d..a380fdb9f0 100644
--- a/pcsx2/pcsx2.vcxproj
+++ b/pcsx2/pcsx2.vcxproj
@@ -325,6 +325,9 @@
+
+
+
@@ -789,6 +792,10 @@
+
+
+
+
diff --git a/pcsx2/pcsx2.vcxproj.filters b/pcsx2/pcsx2.vcxproj.filters
index d61759fb75..b165802bb9 100644
--- a/pcsx2/pcsx2.vcxproj.filters
+++ b/pcsx2/pcsx2.vcxproj.filters
@@ -1739,9 +1739,6 @@
Host
-
- Host
-
System\Ps2\GS\Renderers\Vulkan
@@ -1775,6 +1772,18 @@
AppHost
+
+ Host
+
+
+ Host
+
+
+ Host
+
+
+ Host
+
@@ -2954,6 +2963,18 @@
AppHost
+
+ Host
+
+
+ Host
+
+
+ Host
+
+
+ Host
+
diff --git a/pcsx2/pcsx2core.vcxproj b/pcsx2/pcsx2core.vcxproj
index 81cb90c86a..ae4d72c49a 100644
--- a/pcsx2/pcsx2core.vcxproj
+++ b/pcsx2/pcsx2core.vcxproj
@@ -188,6 +188,9 @@
+
+
+
@@ -502,6 +505,10 @@
+
+
+
+
diff --git a/pcsx2/pcsx2core.vcxproj.filters b/pcsx2/pcsx2core.vcxproj.filters
index a9c280aa15..08cc889df0 100644
--- a/pcsx2/pcsx2core.vcxproj.filters
+++ b/pcsx2/pcsx2core.vcxproj.filters
@@ -1163,9 +1163,6 @@
Host
-
- Host
-
System\Ps2\GS\Renderers\Vulkan
@@ -1251,6 +1248,18 @@
Host
+
+ Host
+
+
+ Host
+
+
+ Host
+
+
+ Host
+
@@ -2071,6 +2080,18 @@
Host
+
+ Host
+
+
+ Host
+
+
+ Host
+
+
+ Host
+