From 14dfbeeed9a2e39fcf432aa075db7db043d85fb8 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Sun, 23 Aug 2026 10:46:06 +0800 Subject: [PATCH] [Feat] (Diligent, EGL): wire EGL window swapchain creation via Diligent ISwapChain - Add CreateSwapChain to renderer using IEngineFactoryVk::CreateSwapChainVk - InitWindowSurface creates the swapchain for native window surfaces - Present now presents the active swapchain; ReleaseEGLResources releases it - InitPbufferSurface keeps offscreen target for pbuffer EGL surfaces - Update handoff; 16 Diligent tests pass --- HANDOFF_DILIGENT.md | 3 +- .../Diligent/BackendObject_Diligent.cpp | 28 +++++++- .../Diligent/BackendObject_Diligent.h | 2 + .../Diligent/Renderer/DiligentRenderer.cpp | 70 ++++++++++++++++++- .../Diligent/Renderer/DiligentRenderer.h | 11 +++ 5 files changed, 109 insertions(+), 5 deletions(-) diff --git a/HANDOFF_DILIGENT.md b/HANDOFF_DILIGENT.md index 3a8dca54..48d12e82 100644 --- a/HANDOFF_DILIGENT.md +++ b/HANDOFF_DILIGENT.md @@ -117,6 +117,7 @@ Working tree is clean. Verified locally on Turnip Adreno 750: - Diligent device/context creation +- EGL window-surface swapchain creation path through Diligent `ISwapChain` (offscreen tests still use the offscreen target) - GL 3.2 / GLSL 1.50 capability advertisement - Offscreen color + depth rendering - Clear color and depth @@ -219,7 +220,7 @@ Notes: - User framebuffers now support texture color attachments, renderbuffer color readback, multiple simultaneous color targets, and depth/stencil texture or renderbuffer attachments. - Textures auto-sync `ITextureObject` → Diligent resources, including mip levels and sampler state; compressed textures and integer/3-channel formats that Diligent lacks are still skipped. - Global UBO (default-block `glUniform*`) and named application UBO blocks (through `glBindBufferBase`/`glUniformBlockBinding`) now upload and bind; SSBOs are still not fed from frontend buffer bindings. -- No swapchain / EGL window surface presentation yet; `Present()` only flushes and `SetSwapInterval` is a no-op. +- Swapchain creation is now wired for native EGL window surfaces via `Diligent::ISwapChain`; `Present()` presents the active swap chain when present and otherwise flushes the offscreen target. Actual on-screen EGL presentation is still untested in this headless environment, and the X11 display/connection fields are not yet plumbed through `WindowHandle`. `SetSwapInterval` remains a no-op. - No transform feedback / GPU-accelerated queries / non-color readback; fence sync and timer queries use CPU fallbacks. - Draw range, multi-draw, instanced-draw wrappers, clear-buffer, blit, read-pixels, CopyTexImage*, CopyImageSubData, GenerateMipmap, GetTexImage/GetTextureImage and indirect draws are now wired; buffer subdata paths still remain. - A last-PSO cache now avoids recreating the pipeline when program/render-state/topology/VAO layout is unchanged; texture/UBO resources are still rebound dynamically per draw. diff --git a/MobileGL/MG_Backend/Diligent/BackendObject_Diligent.cpp b/MobileGL/MG_Backend/Diligent/BackendObject_Diligent.cpp index 92fec9f0..cbc17781 100644 --- a/MobileGL/MG_Backend/Diligent/BackendObject_Diligent.cpp +++ b/MobileGL/MG_Backend/Diligent/BackendObject_Diligent.cpp @@ -813,8 +813,32 @@ namespace MobileGL::MG_Backend::DiligentBackend { } Bool BackendObject_Diligent::InitWindowSurface() { - // Skeleton: no native swapchain creation yet. - return true; + if (!m_windowHandle.Handle) { + MGLOG_E("BackendObject_Diligent::InitWindowSurface failed: native window handle is null"); + return false; + } + if (m_pRenderer == nullptr || m_pFactoryVk == nullptr) { + MGLOG_E("BackendObject_Diligent::InitWindowSurface failed: renderer/factory is not ready"); + return false; + } + return m_pRenderer->CreateSwapChain(m_pFactoryVk, m_windowHandle, + m_windowHandle.Width, m_windowHandle.Height); + } + + Bool BackendObject_Diligent::InitPbufferSurface(EGLint width, EGLint height) { + // The Diligent backend keeps its offscreen target for pbuffer EGL surfaces. + // A future enhancement can resize/recreate the offscreen target to match the + // pbuffer dimensions. + (void)width; + (void)height; + return m_pRenderer != nullptr; + } + + void BackendObject_Diligent::ReleaseEGLResources() { + if (m_pRenderer != nullptr) { + m_pRenderer->ReleaseSwapChain(); + } + BackendObject::ReleaseEGLResources(); } const RendererInfo& BackendObject_Diligent::GetRendererInfo() const { diff --git a/MobileGL/MG_Backend/Diligent/BackendObject_Diligent.h b/MobileGL/MG_Backend/Diligent/BackendObject_Diligent.h index 884c497e..e00e29b9 100644 --- a/MobileGL/MG_Backend/Diligent/BackendObject_Diligent.h +++ b/MobileGL/MG_Backend/Diligent/BackendObject_Diligent.h @@ -42,12 +42,14 @@ namespace MobileGL::MG_Backend::DiligentBackend { void Initialize() override; Bool InitCapabilities() override; Bool InitWindowSurface() override; + Bool InitPbufferSurface(EGLint width, EGLint height) override; const RendererInfo& GetRendererInfo() const override; String GetBackendAPIVersionString() const override; const GlobalBackendFunctionsTable& GetBackendFunctions() const override; const DynamicBackendParameters& GetDynamicParameters() const override; BackendType GetBackendType() const override; + void ReleaseEGLResources() override; DiligentRenderer* GetRenderer(); diff --git a/MobileGL/MG_Backend/Diligent/Renderer/DiligentRenderer.cpp b/MobileGL/MG_Backend/Diligent/Renderer/DiligentRenderer.cpp index b696ec52..38a08019 100644 --- a/MobileGL/MG_Backend/Diligent/Renderer/DiligentRenderer.cpp +++ b/MobileGL/MG_Backend/Diligent/Renderer/DiligentRenderer.cpp @@ -14,8 +14,11 @@ #include #include #include +#include +#include #include #include +#include #include #include @@ -378,6 +381,45 @@ void main() return true; } + Bool DiligentRenderer::CreateSwapChain(::Diligent::IEngineFactoryVk* factory, const WindowHandle& handle, + Uint32 width, Uint32 height) { + if (factory == nullptr || m_pDevice == nullptr || m_pContext == nullptr || handle.Handle == nullptr) { + MGLOG_E("DiligentRenderer::CreateSwapChain: invalid factory/device/context/window"); + return false; + } + + ::Diligent::SwapChainDesc desc; + desc.Width = width > 0 ? width : std::max(handle.Width, 1); + desc.Height = height > 0 ? height : std::max(handle.Height, 1); + desc.ColorBufferFormat = ::Diligent::TEX_FORMAT_RGBA8_UNORM_SRGB; + desc.DepthBufferFormat = ::Diligent::TEX_FORMAT_D24_UNORM_S8_UINT; + desc.BufferCount = 2; + + ::Diligent::NativeWindow nativeWindow{}; +#if PLATFORM_ANDROID + nativeWindow.pAWindow = handle.Handle; +#elif PLATFORM_LINUX + // X11 Window IDs are integers that the frontend stores as a void* handle. + // The X11 display/connection could not be plumbed through WindowHandle yet; + // swapchain creation on X11 may need those fields filled by a future change. + nativeWindow.WindowId = static_cast<::Diligent::Uint32>( + reinterpret_cast(handle.Handle)); +#else + (void)nativeWindow; +#endif + + ::Diligent::RefCntAutoPtr<::Diligent::ISwapChain> pSwapChain; + factory->CreateSwapChainVk(m_pDevice, m_pContext, desc, nativeWindow, &pSwapChain); + if (!pSwapChain) { + MGLOG_E("DiligentRenderer::CreateSwapChain: failed to create swap chain"); + return false; + } + m_pSwapChain = pSwapChain; + m_width = desc.Width; + m_height = desc.Height; + return true; + } + Bool DiligentRenderer::CreateOffscreenTargets() { ::Diligent::TextureDesc texDesc; texDesc.Name = "MobileGL Diligent offscreen color target"; @@ -867,7 +909,19 @@ void main() return false; } + auto useSwapChainTargets = [&]() -> Bool { + if (m_pSwapChain && m_pSwapChain->GetCurrentBackBufferRTV()) { + rtvs.push_back(m_pSwapChain->GetCurrentBackBufferRTV()); + dsv = m_pSwapChain->GetDepthBufferDSV(); + return true; + } + return false; + }; + if (MG_State::pGLContext == nullptr) { + if (useSwapChainTargets()) { + return true; + } if (m_pColorRTV) { rtvs.push_back(m_pColorRTV.RawPtr()); } @@ -877,6 +931,9 @@ void main() auto drawFbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject(); if (!drawFbo || drawFbo->IsDefaultFramebuffer()) { + if (useSwapChainTargets()) { + return true; + } if (m_pColorRTV) { rtvs.push_back(m_pColorRTV.RawPtr()); } @@ -1641,6 +1698,9 @@ void main() } ::Diligent::RefCntAutoPtr<::Diligent::ITexture> pSrcTexture = m_pColorTarget; + if (m_pSwapChain && m_pSwapChain->GetCurrentBackBufferRTV()) { + pSrcTexture = m_pSwapChain->GetCurrentBackBufferRTV()->GetTexture(); + } if (MG_State::pGLContext != nullptr) { auto readFbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject(); if (readFbo && !readFbo->IsDefaultFramebuffer()) { @@ -1970,9 +2030,15 @@ void main() return true; } + void DiligentRenderer::ReleaseSwapChain() { + m_pSwapChain.Release(); + } + void DiligentRenderer::Present() { - // Offscreen renderer: nothing to present yet. - if (m_pContext) { + if (m_pSwapChain) { + m_pSwapChain->Present(0); + } else if (m_pContext) { + // Offscreen renderer: nothing to present yet. m_pContext->Flush(); } } diff --git a/MobileGL/MG_Backend/Diligent/Renderer/DiligentRenderer.h b/MobileGL/MG_Backend/Diligent/Renderer/DiligentRenderer.h index 1eae53be..12bf5c37 100644 --- a/MobileGL/MG_Backend/Diligent/Renderer/DiligentRenderer.h +++ b/MobileGL/MG_Backend/Diligent/Renderer/DiligentRenderer.h @@ -20,6 +20,10 @@ #include +namespace MobileGL::MG_Backend { + struct WindowHandle; +} + namespace Diligent { struct IRenderDevice; struct IDeviceContext; @@ -29,6 +33,8 @@ namespace Diligent { struct IBuffer; struct ISampler; struct IShaderResourceBinding; + struct ISwapChain; + struct IEngineFactoryVk; } namespace MobileGL::MG_State::GLState { @@ -55,6 +61,9 @@ namespace MobileGL::MG_Backend::DiligentBackend { void ClearStencil(Uint32 stencil); void DrawTriangle(); void DrawVertices(const Float* vertices, Uint32 vertexCount); + // Creates a real Diligent swap chain for a native EGL window surface. + Bool CreateSwapChain(::Diligent::IEngineFactoryVk* factory, const WindowHandle& handle, + Uint32 width, Uint32 height); // Creates a simple 2D RGBA8 texture from CPU data and makes it available // to state PSOs under the shader variable name "g_Texture". Bool CreateTestTexture(const void* data, Uint32 width, Uint32 height); @@ -73,6 +82,7 @@ namespace MobileGL::MG_Backend::DiligentBackend { void CopyTextureSubData(MG_State::GLState::ITextureObject& src, MG_State::GLState::ITextureObject& dst); void GenerateMipmap(MG_State::GLState::ITextureObject& texture); Bool ReadTextureImage(MG_State::GLState::ITextureObject& texture, Uint32 level, void* pixels); + void ReleaseSwapChain(); void Present(); ::Diligent::IRenderDevice* GetDevice() const { return m_pDevice; } @@ -115,6 +125,7 @@ namespace MobileGL::MG_Backend::DiligentBackend { ::Diligent::RefCntAutoPtr<::Diligent::ITextureView> m_pColorRTV; ::Diligent::RefCntAutoPtr<::Diligent::ITexture> m_pDepthTarget; ::Diligent::RefCntAutoPtr<::Diligent::ITextureView> m_pDepthDSV; + ::Diligent::RefCntAutoPtr<::Diligent::ISwapChain> m_pSwapChain; ::Diligent::RefCntAutoPtr<::Diligent::ITexture> m_pTestTexture; ::Diligent::RefCntAutoPtr<::Diligent::ITextureView> m_pTestSRV; ::Diligent::RefCntAutoPtr<::Diligent::ISampler> m_pTestSampler;