From 62fac86360d1944791da70c2a82da0c1b1f8ca87 Mon Sep 17 00:00:00 2001 From: lindexi Date: Thu, 22 Jan 2026 23:28:46 +0800 Subject: [PATCH] Reduce the number of WrapDirect3D11Texture calls (#20517) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Reduce the number of WrapDirect3D11Texture calls Reduce the number of WrapDirect3D11Texture calls by tying the EglSurface lifetime to _renderTexture. When testing on a 4K display, I observed that eglCreatePbufferFromClientBuffer, which is invoked by WrapDirect3D11Texture, can take around 5 ms per frame. By reducing the number of eglCreatePbufferFromClientBuffer calls, I was able to improve rendering performance by about 30%. However, I’m not sure why the previous implementation needed to call WrapDirect3D11Texture on every frame. * Remove the commented code --- .../DirectX/DxgiRenderTarget.cs | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Windows/Avalonia.Win32/DirectX/DxgiRenderTarget.cs b/src/Windows/Avalonia.Win32/DirectX/DxgiRenderTarget.cs index c7306ce86e..6470aa48b8 100644 --- a/src/Windows/Avalonia.Win32/DirectX/DxgiRenderTarget.cs +++ b/src/Windows/Avalonia.Win32/DirectX/DxgiRenderTarget.cs @@ -23,7 +23,8 @@ namespace Avalonia.Win32.DirectX private IUnknown? _renderTexture; private RECT _clientRect; - + private EglSurface? _surface; + public DxgiRenderTarget(EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo window, EglContext context, DxgiConnection connection) : base(context) { _window = window; @@ -83,7 +84,6 @@ namespace Avalonia.Win32.DirectX } var contextLock = Context.EnsureCurrent(); - EglSurface? surface = null; IDisposable? transaction = null; var success = false; try @@ -96,6 +96,9 @@ namespace Avalonia.Win32.DirectX if (_renderTexture is not null) { + _surface?.Dispose(); + _surface = null; + _renderTexture.Dispose(); _renderTexture = null; } @@ -114,19 +117,24 @@ namespace Avalonia.Win32.DirectX var texture = _renderTexture; if (texture is null) { + _surface?.Dispose(); + _surface = null; + Guid textureGuid = ID3D11Texture2DGuid; texture = MicroComRuntime.CreateProxyFor(_swapChain.GetBuffer(0, &textureGuid), true); } _renderTexture = texture; - // I also have to get the pointer to this texture directly - surface = ((AngleWin32EglDisplay)Context.Display).WrapDirect3D11Texture(MicroComRuntime.GetNativeIntPtr(_renderTexture), - 0, 0, size.Width, size.Height); + if (_surface is null) + { + // I also have to get the pointer to this texture directly + _surface = ((AngleWin32EglDisplay)Context.Display).WrapDirect3D11Texture(MicroComRuntime.GetNativeIntPtr(_renderTexture), + 0, 0, size.Width, size.Height); + } - var res = base.BeginDraw(surface, _window.Size, _window.Scaling, () => + var res = base.BeginDraw(_surface, _window.Size, _window.Scaling, () => { _swapChain.Present((ushort)0U, (ushort)0U); - surface.Dispose(); transaction?.Dispose(); contextLock?.Dispose(); }, true); @@ -137,7 +145,8 @@ namespace Avalonia.Win32.DirectX { if (!success) { - surface?.Dispose(); + _surface?.Dispose(); + _surface = null; if (_renderTexture is not null) { _renderTexture.Dispose(); @@ -155,6 +164,7 @@ namespace Avalonia.Win32.DirectX _dxgiDevice?.Dispose(); _dxgiFactory?.Dispose(); _swapChain?.Dispose(); + _surface?.Dispose(); _renderTexture?.Dispose(); }