diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index cab7302732f9..4192f7b3be83 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -41,7 +41,6 @@ class D3D11DepthStencilState; class D3D11SamplerState; class D3D11Buffer; class D3D11RasterState; -class D3D11Framebuffer; // This must stay POD for the memcmp to work reliably. struct D3D11DepthStencilKey { @@ -60,6 +59,39 @@ class D3D11DepthStencilState : public DepthStencilState { DepthStencilStateDesc desc; }; +// A D3D11Framebuffer is a D3D11Framebuffer plus all the textures it owns. +class D3D11Framebuffer : public Framebuffer { +public: + D3D11Framebuffer(int width, int height) { + width_ = width; + height_ = height; + } + ~D3D11Framebuffer() { + if (colorTex) + colorTex->Release(); + if (colorRTView) + colorRTView->Release(); + if (colorSRView) + colorSRView->Release(); + if (depthSRView) + depthSRView->Release(); + if (depthStencilTex) + depthStencilTex->Release(); + if (depthStencilRTView) + depthStencilRTView->Release(); + } + + ID3D11Texture2D *colorTex = nullptr; + ID3D11RenderTargetView *colorRTView = nullptr; + ID3D11ShaderResourceView *colorSRView = nullptr; + ID3D11ShaderResourceView *depthSRView = nullptr; + DXGI_FORMAT colorFormat = DXGI_FORMAT_UNKNOWN; + + ID3D11Texture2D *depthStencilTex = nullptr; + ID3D11DepthStencilView *depthStencilRTView = nullptr; + DXGI_FORMAT depthStencilFormat = DXGI_FORMAT_UNKNOWN; +}; + class D3D11DrawContext : public DrawContext { public: D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *deviceContext, ID3D11Device1 *device1, ID3D11DeviceContext1 *deviceContext1, IDXGISwapChain *swapChain, D3D_FEATURE_LEVEL featureLevel, HWND hWnd, std::vector deviceList, int maxInflightFrames); @@ -1388,6 +1420,13 @@ void D3D11DrawContext::DrawIndexedClippedBatchUP(const void *vdata, int vertexCo ApplyCurrentState(); for (int i = 0; i < draws.size(); i++) { + if (draws[i].bindTexture) { + ID3D11ShaderResourceView *view = ((D3D11Texture *)draws[i].bindTexture)->View(); + context_->PSSetShaderResources(0, 1, &view); + } else { + ID3D11ShaderResourceView *view = ((D3D11Framebuffer *)draws[i].bindFramebufferAsTex)->colorSRView; + context_->PSSetShaderResources(0, 1, &view); + } D3D11_RECT rc; rc.left = draws[i].clipx; rc.top = draws[i].clipy; @@ -1420,39 +1459,6 @@ uint32_t D3D11DrawContext::GetDataFormatSupport(DataFormat fmt) const { return support; } -// A D3D11Framebuffer is a D3D11Framebuffer plus all the textures it owns. -class D3D11Framebuffer : public Framebuffer { -public: - D3D11Framebuffer(int width, int height) { - width_ = width; - height_ = height; - } - ~D3D11Framebuffer() { - if (colorTex) - colorTex->Release(); - if (colorRTView) - colorRTView->Release(); - if (colorSRView) - colorSRView->Release(); - if (depthSRView) - depthSRView->Release(); - if (depthStencilTex) - depthStencilTex->Release(); - if (depthStencilRTView) - depthStencilRTView->Release(); - } - - ID3D11Texture2D *colorTex = nullptr; - ID3D11RenderTargetView *colorRTView = nullptr; - ID3D11ShaderResourceView *colorSRView = nullptr; - ID3D11ShaderResourceView *depthSRView = nullptr; - DXGI_FORMAT colorFormat = DXGI_FORMAT_UNKNOWN; - - ID3D11Texture2D *depthStencilTex = nullptr; - ID3D11DepthStencilView *depthStencilRTView = nullptr; - DXGI_FORMAT depthStencilFormat = DXGI_FORMAT_UNKNOWN; -}; - Framebuffer *D3D11DrawContext::CreateFramebuffer(const FramebufferDesc &desc) { HRESULT hr; D3D11Framebuffer *fb = new D3D11Framebuffer(desc.width, desc.height); diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index f2ea19800e4a..733ec78c2f3d 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -1012,6 +1012,21 @@ static void SemanticToD3D9UsageAndIndex(int semantic, BYTE *usage, BYTE *index) } } +class D3D9Framebuffer : public Framebuffer { +public: + D3D9Framebuffer(int width, int height) { + width_ = width; + height_ = height; + } + ~D3D9Framebuffer(); + + uint32_t id = 0; + ComPtr surf; + ComPtr depthstencil; + ComPtr tex; + ComPtr depthstenciltex; +}; + D3D9InputLayout::D3D9InputLayout(LPDIRECT3DDEVICE9 device, const InputLayoutDesc &desc) : decl_(NULL) { D3DVERTEXELEMENT9 *elements = new D3DVERTEXELEMENT9[desc.attributes.size() + 1]; size_t i; @@ -1195,6 +1210,12 @@ void D3D9Context::DrawIndexedClippedBatchUP(const void *vdata, int vertexCount, // Suboptimal! for (int i = 0; i < draws.size(); i++) { + if (draws[i].bindTexture) { + device_->SetTexture(0, ((D3D9Texture *)draws[i].bindTexture)->TexturePtr()); + } else if (draws[i].bindFramebufferAsTex) { + device_->SetTexture(0, ((D3D9Framebuffer *)draws[i].bindFramebufferAsTex)->tex.Get()); + } + RECT rc; rc.left = draws[i].clipx; rc.top = draws[i].clipy; @@ -1286,21 +1307,6 @@ bool D3D9ShaderModule::Compile(LPDIRECT3DDEVICE9 device, const uint8_t *data, si return true; } -class D3D9Framebuffer : public Framebuffer { -public: - D3D9Framebuffer(int width, int height) { - width_ = width; - height_ = height; - } - ~D3D9Framebuffer(); - - uint32_t id = 0; - ComPtr surf; - ComPtr depthstencil; - ComPtr tex; - ComPtr depthstenciltex; -}; - Framebuffer *D3D9Context::CreateFramebuffer(const FramebufferDesc &desc) { // Don't think D3D9 does array layers. _dbg_assert_(desc.numLayers == 1); diff --git a/Common/GPU/OpenGL/GLRenderManager.cpp b/Common/GPU/OpenGL/GLRenderManager.cpp index 18d93a0f4ff8..0967e5138f32 100644 --- a/Common/GPU/OpenGL/GLRenderManager.cpp +++ b/Common/GPU/OpenGL/GLRenderManager.cpp @@ -264,6 +264,7 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende } } +// aspectBit: GL_COLOR_BUFFER_BIT etc void GLRenderManager::BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); _dbg_assert_(binding < MAX_GL_TEXTURE_SLOTS); diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 58a03f57da3b..bfb61dbaf653 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -878,7 +878,7 @@ class OpenGLTexture : public Texture { int NumMipmaps() const { return mipLevels_; } - const GLRTexture *GetTex() const { + GLRTexture *GetTex() const { return tex_; } @@ -1463,6 +1463,11 @@ void OpenGLContext::DrawIndexedClippedBatchUP(const void *vdata, int vertexCount ApplySamplers(); for (auto &draw : draws) { + if (draw.bindTexture) { + renderManager_.BindTexture(0, ((OpenGLTexture *)draw.bindTexture)->GetTex()); + } else if (draw.bindFramebufferAsTex) { + renderManager_.BindFramebufferAsTexture(((OpenGLFramebuffer*)draw.bindFramebufferAsTex)->framebuffer_, 0, GL_COLOR_BUFFER_BIT); + } GLRect2D scissor; scissor.x = draw.clipx; scissor.y = draw.clipy; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index ad64afe5e763..c8f919425177 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -1583,10 +1583,16 @@ void VKContext::DrawIndexedClippedBatchUP(const void *vdata, int vertexCount, co BindCurrentPipeline(); ApplyDynamicState(); - int descSetIndex; - PackedDescriptor *descriptors = renderManager_.PushDescriptorSet(4, &descSetIndex); for (auto &draw : draws) { + // TODO: Dirty-check these. + if (draw.bindTexture) { + BindTexture(0, draw.bindTexture); + } else if (draw.bindFramebufferAsTex) { + BindFramebufferAsTexture(draw.bindFramebufferAsTex, 0, FBChannel::FB_COLOR_BIT, 0); + } + int descSetIndex; + PackedDescriptor *descriptors = renderManager_.PushDescriptorSet(4, &descSetIndex); BindDescriptors(vulkanUBObuf, descriptors); renderManager_.SetScissor(draw.clipx, draw.clipy, draw.clipw, draw.cliph); renderManager_.DrawIndexed(descSetIndex, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset, vulkanIbuf, diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index d2fe0d9222b1..3e2076cc8cb9 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -703,6 +703,8 @@ struct ClippedDraw { s16 clipy; s16 clipw; s16 cliph; + Draw::Texture *bindTexture; + Draw::Framebuffer *bindFramebufferAsTex; }; class DrawContext { diff --git a/Core/Debugger/DebugInterface.h b/Core/Debugger/DebugInterface.h index 37f5bc7c12bf..8d71fc78191a 100644 --- a/Core/Debugger/DebugInterface.h +++ b/Core/Debugger/DebugInterface.h @@ -26,7 +26,7 @@ struct MemMap; class DebugInterface { public: - virtual int getInstructionSize(int instruction) {return 1;} + virtual int getInstructionSize(int instruction) = 0; virtual bool isAlive() = 0; virtual bool isBreakpoint(unsigned int address) = 0; @@ -47,6 +47,7 @@ class DebugInterface { virtual u32 GetHi() = 0; virtual u32 GetLo() = 0; virtual u32 GetLLBit() = 0; + virtual u32 GetFPCond() = 0; virtual void SetHi(u32 val) { }; virtual void SetLo(u32 val) { }; diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index e494b1746a0a..60133595456f 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -481,8 +481,7 @@ u32 sceKernelIcacheClearAll() return 0; } -void KernelObject::GetQuickInfo(char *ptr, int size) -{ +void KernelObject::GetQuickInfo(char *ptr, int size) { strcpy(ptr, "-"); } diff --git a/Core/MIPS/MIPSDebugInterface.h b/Core/MIPS/MIPSDebugInterface.h index 50d180e3d3a5..1ec6bbc01888 100644 --- a/Core/MIPS/MIPSDebugInterface.h +++ b/Core/MIPS/MIPSDebugInterface.h @@ -53,6 +53,7 @@ class MIPSDebugInterface : public DebugInterface u32 GetPC() override { return cpu->pc; } u32 GetLR() override { return cpu->r[MIPS_REG_RA]; } + u32 GetFPCond() override { return cpu->fpcond; } void DisAsm(u32 pc, char *out, size_t outSize) override; void SetPC(u32 _pc) override { cpu->pc = _pc; } diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index c658170964d0..bc3674a9012a 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -20,6 +20,7 @@ #include #include "ext/imgui/imgui.h" +#include "ext/imgui/imgui_impl_thin3d.h" #include "Common/GPU/thin3d.h" #include "Common/GPU/OpenGL/GLFeatures.h" @@ -3704,5 +3705,10 @@ void FramebufferManagerCommon::DrawImGuiDebug(int &selected) const { } ImGui::EndTable(); - // Now, draw the actual framebuffer image. This could be refined a lot. + if (selected != -1) { + // Now, draw the image of the selected framebuffer. + Draw::Framebuffer *fb = vfbs_[selected]->fbo; + ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(fb); + ImGui::Image(texId, ImVec2(fb->Width(), fb->Height())); + } } diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 2c51e91a93f1..5607252c2bf8 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -48,18 +48,17 @@ void DrawRegisterView(MIPSDebugInterface *mipsDebug, bool *open) { ImGui::TableSetupColumn("regname", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("value_i", ImGuiTableColumnFlags_WidthStretch); - ImGui::TableNextRow(); auto gprLine = [&](const char *regname, int value) { - ImGui::TableSetColumnIndex(0); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); ImGui::TextUnformatted(regname); - ImGui::TableSetColumnIndex(1); + ImGui::TableNextColumn(); ImGui::Text("%08x", value); if (value >= -1000000 && value <= 1000000) { ImGui::TableSetColumnIndex(2); ImGui::Text("%d", value); } - ImGui::TableNextRow(); }; for (int i = 0; i < 32; i++) { gprLine(mipsDebug->GetRegName(0, i).c_str(), mipsDebug->GetGPR32Value(i)); @@ -78,19 +77,27 @@ void DrawRegisterView(MIPSDebugInterface *mipsDebug, bool *open) { ImGui::TableSetupColumn("regname", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("value_i", ImGuiTableColumnFlags_WidthStretch); + + // fpcond ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted("fpcond"); + ImGui::TableNextColumn(); + ImGui::Text("%08x", mipsDebug->GetFPCond()); + for (int i = 0; i < 32; i++) { float fvalue = mipsDebug->GetFPR32Value(i); u32 fivalue; memcpy(&fivalue, &fvalue, sizeof(fivalue)); - ImGui::TableSetColumnIndex(0); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); ImGui::TextUnformatted(mipsDebug->GetRegName(1, i).c_str()); - ImGui::TableSetColumnIndex(1); + ImGui::TableNextColumn(); ImGui::Text("%0.7f", fvalue); - ImGui::TableSetColumnIndex(2); + ImGui::TableNextColumn(); ImGui::Text("%08x", fivalue); - ImGui::TableNextRow(); } + ImGui::EndTable(); } ImGui::EndTabItem(); @@ -227,7 +234,7 @@ static void DrawKernelObjects(ImConfig &cfg) { ImGui::End(); return; } - if (ImGui::BeginTable("kos", 5, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) { + if (ImGui::BeginTable("kos", 4, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH | ImGuiTableFlags_Resizable)) { ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed); diff --git a/ext/imgui/imgui_impl_thin3d.cpp b/ext/imgui/imgui_impl_thin3d.cpp index 5eb8e57351f1..ac0fc0a69463 100644 --- a/ext/imgui/imgui_impl_thin3d.cpp +++ b/ext/imgui/imgui_impl_thin3d.cpp @@ -12,28 +12,38 @@ static Lin::Matrix4x4 g_drawMatrix; static ImFont *g_proportionalFont = nullptr; static ImFont *g_fixedFont = nullptr; -struct ImGui_ImplThin3d_Data { +struct RegisteredTexture { + bool isFramebuffer; + union { + Draw::Texture *texture; + Draw::Framebuffer *framebuffer; + }; +}; + +struct BackendData { Draw::SamplerState *fontSampler = nullptr; Draw::Texture *fontImage = nullptr; Draw::Pipeline *pipeline = nullptr; + std::vector tempTextures; }; +#define TEX_ID_OFFSET 256 + // 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_ImplThin3d_Data* ImGui_ImplThin3d_GetBackendData() { - return ImGui::GetCurrentContext() ? (ImGui_ImplThin3d_Data *)ImGui::GetIO().BackendRendererUserData : nullptr; +static BackendData *ImGui_ImplThin3d_GetBackendData() { + return ImGui::GetCurrentContext() ? (BackendData *)ImGui::GetIO().BackendRendererUserData : nullptr; } -static void ImGui_ImplThin3d_SetupRenderState(Draw::DrawContext *draw, ImDrawData* draw_data, Draw::Pipeline *pipeline, int fb_width, int fb_height) { - ImGui_ImplThin3d_Data* bd = ImGui_ImplThin3d_GetBackendData(); +static void ImGui_ImplThin3d_SetupRenderState(Draw::DrawContext *draw, ImDrawData* drawData, Draw::Pipeline *pipeline, int fb_width, int fb_height) { + BackendData *bd = ImGui_ImplThin3d_GetBackendData(); // Bind pipeline and texture draw->BindPipeline(pipeline); - draw->BindTexture(0, bd->fontImage); draw->BindSamplerStates(0, 1, &bd->fontSampler); - // Setup viewport: + // Setup viewport { Draw::Viewport viewport; viewport.TopLeftX = 0; @@ -46,10 +56,11 @@ static void ImGui_ImplThin3d_SetupRenderState(Draw::DrawContext *draw, ImDrawDat } // Setup scale and translation: - // Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. - // We currently ignore DisplayPos. + // Our visible imgui space lies from drawData->DisplayPps (top left) to drawData->DisplayPos + drawData->DisplaySize (bottom right). + // DisplayPos is (0,0) for single viewport apps. We currently ignore DisplayPos. + // We probably only need to do this at the start of the frame. { - Lin::Matrix4x4 mtx = ComputeOrthoMatrix(draw_data->DisplaySize.x, draw_data->DisplaySize.y, draw->GetDeviceCaps().coordConvention); + Lin::Matrix4x4 mtx = ComputeOrthoMatrix(drawData->DisplaySize.x, drawData->DisplaySize.y, draw->GetDeviceCaps().coordConvention); Draw::VsTexColUB ub{}; memcpy(ub.WorldViewProj, mtx.getReadPtr(), sizeof(Lin::Matrix4x4)); @@ -63,10 +74,11 @@ void ImGui_ImplThin3d_RenderDrawData(ImDrawData* draw_data, Draw::DrawContext *d // 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) + if (fb_width <= 0 || fb_height <= 0) { return; + } - ImGui_ImplThin3d_Data* bd = ImGui_ImplThin3d_GetBackendData(); + BackendData* bd = ImGui_ImplThin3d_GetBackendData(); // Setup desired Vulkan state ImGui_ImplThin3d_SetupRenderState(draw, draw_data, bd->pipeline, fb_width, fb_height); @@ -77,7 +89,12 @@ void ImGui_ImplThin3d_RenderDrawData(ImDrawData* draw_data, Draw::DrawContext *d _assert_(sizeof(ImDrawIdx) == 2); + ImTextureID prevTexId = (ImTextureID)-1; + std::vector draws; + Draw::Texture *boundTexture; + Draw::Framebuffer *boundFBAsTexture; + // Render command lists for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -93,6 +110,21 @@ void ImGui_ImplThin3d_RenderDrawData(ImDrawData* draw_data, Draw::DrawContext *d pcmd->UserCallback(cmd_list, pcmd); } } else { + // Update the texture pointers. + if (!pcmd->TextureId) { + boundTexture = bd->fontImage; + boundFBAsTexture = nullptr; + } else { + size_t index = (size_t)pcmd->TextureId - TEX_ID_OFFSET; + _dbg_assert_(index < bd->tempTextures.size()); + if (bd->tempTextures[index].framebuffer) { + boundFBAsTexture = bd->tempTextures[index].framebuffer; + boundTexture = nullptr; + } else { + boundTexture = bd->tempTextures[index].texture; + boundFBAsTexture = nullptr; + } + } // 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); @@ -105,24 +137,29 @@ void ImGui_ImplThin3d_RenderDrawData(ImDrawData* draw_data, Draw::DrawContext *d if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) continue; - Draw::ClippedDraw draw; - draw.clipx = clip_min.x; - draw.clipy = clip_min.y; - draw.clipw = clip_max.x - clip_min.x; - draw.cliph = clip_max.y - clip_min.y; - draw.indexCount = pcmd->ElemCount; - draw.indexOffset = pcmd->IdxOffset; - draws.push_back(draw); + Draw::ClippedDraw clippedDraw; + clippedDraw.bindTexture = boundTexture; + clippedDraw.bindFramebufferAsTex = boundFBAsTexture; + clippedDraw.clipx = clip_min.x; + clippedDraw.clipy = clip_min.y; + clippedDraw.clipw = clip_max.x - clip_min.x; + clippedDraw.cliph = clip_max.y - clip_min.y; + clippedDraw.indexCount = pcmd->ElemCount; + clippedDraw.indexOffset = pcmd->IdxOffset; + draws.push_back(clippedDraw); } } draw->DrawIndexedClippedBatchUP(cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.size(), cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.size(), draws); } draw->SetScissorRect(0, 0, fb_width, fb_height); + + // Discard temp textures. + bd->tempTextures.clear(); } bool ImGui_ImplThin3d_CreateDeviceObjects(Draw::DrawContext *draw) { - ImGui_ImplThin3d_Data* bd = ImGui_ImplThin3d_GetBackendData(); + BackendData* bd = ImGui_ImplThin3d_GetBackendData(); if (!bd->fontSampler) { // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling. @@ -138,7 +175,7 @@ bool ImGui_ImplThin3d_CreateDeviceObjects(Draw::DrawContext *draw) { } if (!bd->pipeline) { - ImGui_ImplThin3d_Data* bd = ImGui_ImplThin3d_GetBackendData(); + BackendData* bd = ImGui_ImplThin3d_GetBackendData(); using namespace Draw; @@ -179,7 +216,7 @@ bool ImGui_ImplThin3d_CreateDeviceObjects(Draw::DrawContext *draw) { if (!bd->fontImage) { ImGuiIO& io = ImGui::GetIO(); - ImGui_ImplThin3d_Data* bd = ImGui_ImplThin3d_GetBackendData(); + BackendData* bd = ImGui_ImplThin3d_GetBackendData(); unsigned char* pixels; int width, height; @@ -196,7 +233,7 @@ bool ImGui_ImplThin3d_CreateDeviceObjects(Draw::DrawContext *draw) { desc.tag = "imgui-font"; desc.initData.push_back((const uint8_t *)pixels); bd->fontImage = draw->CreateTexture(desc); - io.Fonts->SetTexID((ImTextureID)bd->fontImage); + io.Fonts->SetTexID(0); } return true; @@ -204,7 +241,7 @@ bool ImGui_ImplThin3d_CreateDeviceObjects(Draw::DrawContext *draw) { void ImGui_ImplThin3d_DestroyDeviceObjects() { ImGuiIO& io = ImGui::GetIO(); - ImGui_ImplThin3d_Data* bd = ImGui_ImplThin3d_GetBackendData(); + BackendData* bd = ImGui_ImplThin3d_GetBackendData(); if (bd->fontImage) { bd->fontImage->Release(); bd->fontImage = nullptr; @@ -236,7 +273,7 @@ bool ImGui_ImplThin3d_Init(Draw::DrawContext *draw, const uint8_t *ttf_font, siz IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Setup backend capabilities flags - ImGui_ImplThin3d_Data* bd = IM_NEW(ImGui_ImplThin3d_Data)(); + BackendData* bd = IM_NEW(BackendData)(); io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_thin3d"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. @@ -253,7 +290,7 @@ void ImGui_PopFont() { } void ImGui_ImplThin3d_Shutdown() { - ImGui_ImplThin3d_Data* bd = ImGui_ImplThin3d_GetBackendData(); + BackendData* bd = ImGui_ImplThin3d_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); @@ -265,7 +302,7 @@ void ImGui_ImplThin3d_Shutdown() { } void ImGui_ImplThin3d_NewFrame(Draw::DrawContext *draw, Lin::Matrix4x4 drawMatrix) { - ImGui_ImplThin3d_Data* bd = ImGui_ImplThin3d_GetBackendData(); + BackendData* bd = ImGui_ImplThin3d_GetBackendData(); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplThin3d_Init()?"); // This one checks if objects already have been created, so ok to call every time. @@ -273,13 +310,22 @@ void ImGui_ImplThin3d_NewFrame(Draw::DrawContext *draw, Lin::Matrix4x4 drawMatri g_drawMatrix = drawMatrix; } -// Register a texture. No-op. -ImTextureID ImGui_ImplThin3d_AddTexture(Draw::Texture *texture) { - ImGui_ImplThin3d_Data* bd = ImGui_ImplThin3d_GetBackendData(); - return (void *)texture; +ImTextureID ImGui_ImplThin3d_AddTextureTemp(Draw::Texture *texture) { + BackendData* bd = ImGui_ImplThin3d_GetBackendData(); + + RegisteredTexture tex{ false }; + tex.texture = texture; + + bd->tempTextures.push_back(tex); + return (ImTextureID)(uint64_t)(TEX_ID_OFFSET + bd->tempTextures.size() - 1); } -// Unregister a texture. No-op. -Draw::Texture *ImGui_ImplThin3d_RemoveTexture(ImTextureID tex) { - return (Draw::Texture *)tex; +ImTextureID ImGui_ImplThin3d_AddFBAsTextureTemp(Draw::Framebuffer *framebuffer) { + BackendData* bd = ImGui_ImplThin3d_GetBackendData(); + + RegisteredTexture tex{ true }; + tex.framebuffer = framebuffer; + + bd->tempTextures.push_back(tex); + return (ImTextureID)(uint64_t)(TEX_ID_OFFSET + bd->tempTextures.size() - 1); } diff --git a/ext/imgui/imgui_impl_thin3d.h b/ext/imgui/imgui_impl_thin3d.h index 6c86a4589cb9..98cad60f645f 100644 --- a/ext/imgui/imgui_impl_thin3d.h +++ b/ext/imgui/imgui_impl_thin3d.h @@ -41,8 +41,10 @@ IMGUI_IMPL_API void ImGui_ImplThin3d_RenderDrawData(ImDrawData* draw_dat IMGUI_IMPL_API bool ImGui_ImplThin3d_CreateDeviceObjects(Draw::DrawContext *draw); IMGUI_IMPL_API void ImGui_ImplThin3d_DestroyDeviceObjects(); -IMGUI_IMPL_API ImTextureID ImGui_ImplThin3d_AddTexture(Draw::Texture *texture); -IMGUI_IMPL_API Draw::Texture *ImGui_ImplThin3d_RemoveTexture(ImTextureID texture); +// These register a texture for imgui drawing, but just for the current frame. +// Textures are unregistered again in RenderDrawData. This is just simpler. +IMGUI_IMPL_API ImTextureID ImGui_ImplThin3d_AddTextureTemp(Draw::Texture *texture); +IMGUI_IMPL_API ImTextureID ImGui_ImplThin3d_AddFBAsTextureTemp(Draw::Framebuffer *framebuffer); void ImGui_PushFixedFont(); void ImGui_PopFont();