From eaff38f161b7ab632d2415b035b9c44a3be2ee41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 26 Nov 2024 09:38:30 +0100 Subject: [PATCH] Implement ImGui clipped batch texturing support in the other backends too --- Common/GPU/D3D11/thin3d_d3d11.cpp | 74 +++++++++++++++------------ Common/GPU/D3D9/thin3d_d3d9.cpp | 36 +++++++------ Common/GPU/OpenGL/GLRenderManager.cpp | 1 + Common/GPU/OpenGL/thin3d_gl.cpp | 7 ++- Common/GPU/Vulkan/thin3d_vulkan.cpp | 1 + ext/imgui/imgui_impl_thin3d.cpp | 29 +++++------ 6 files changed, 82 insertions(+), 66 deletions(-) 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 3466ec3f7337..c8f919425177 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -1585,6 +1585,7 @@ void VKContext::DrawIndexedClippedBatchUP(const void *vdata, int vertexCount, co ApplyDynamicState(); for (auto &draw : draws) { + // TODO: Dirty-check these. if (draw.bindTexture) { BindTexture(0, draw.bindTexture); } else if (draw.bindFramebufferAsTex) { diff --git a/ext/imgui/imgui_impl_thin3d.cpp b/ext/imgui/imgui_impl_thin3d.cpp index 7486f0d2adb6..ac0fc0a69463 100644 --- a/ext/imgui/imgui_impl_thin3d.cpp +++ b/ext/imgui/imgui_impl_thin3d.cpp @@ -92,8 +92,8 @@ void ImGui_ImplThin3d_RenderDrawData(ImDrawData* draw_data, Draw::DrawContext *d ImTextureID prevTexId = (ImTextureID)-1; std::vector draws; - Draw::Texture *boundTexture = nullptr; - Draw::Framebuffer *boundFBAsTexture = nullptr; + Draw::Texture *boundTexture; + Draw::Framebuffer *boundFBAsTexture; // Render command lists for (int n = 0; n < draw_data->CmdListsCount; n++) { @@ -111,23 +111,20 @@ void ImGui_ImplThin3d_RenderDrawData(ImDrawData* draw_data, Draw::DrawContext *d } } else { // Update the texture pointers. - if (pcmd->TextureId != prevTexId) { - if (!pcmd->TextureId) { - draw->BindTexture(0, bd->fontImage); + 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 { - 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; - } + boundTexture = bd->tempTextures[index].texture; + boundFBAsTexture = nullptr; } - prevTexId = pcmd->TextureId; } - // 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);