Просмотр исходного кода

Vulkan: Fix swapchain image view leak (#6509)

gdkchan 2 лет назад
Родитель
Сommit
3be616207d

+ 5 - 2
src/Ryujinx.Graphics.Vulkan/RenderPassHolder.cs

@@ -122,7 +122,6 @@ namespace Ryujinx.Graphics.Vulkan
 
                 gd.Api.CreateRenderPass(device, renderPassCreateInfo, null, out var renderPass).ThrowOnError();
 
-                _renderPass?.Dispose();
                 _renderPass = new Auto<DisposableRenderPass>(new DisposableRenderPass(gd.Api, device, renderPass));
             }
 
@@ -162,7 +161,7 @@ namespace Ryujinx.Graphics.Vulkan
 
         public void Dispose()
         {
-            // Dispose all framebuffers
+            // Dispose all framebuffers.
 
             foreach (var fb in _framebuffers.Values)
             {
@@ -175,6 +174,10 @@ namespace Ryujinx.Graphics.Vulkan
             {
                 texture.RemoveRenderPass(_key);
             }
+
+            // Dispose render pass.
+
+            _renderPass.Dispose();
         }
     }
 }

+ 20 - 17
src/Ryujinx.Graphics.Vulkan/TextureView.cs

@@ -4,6 +4,7 @@ using Silk.NET.Vulkan;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Threading;
 using Format = Ryujinx.Graphics.GAL.Format;
 using VkBuffer = Silk.NET.Vulkan.Buffer;
 using VkFormat = Silk.NET.Vulkan.Format;
@@ -36,7 +37,8 @@ namespace Ryujinx.Graphics.Vulkan
         public int FirstLayer { get; }
         public int FirstLevel { get; }
         public VkFormat VkFormat { get; }
-        public bool Valid { get; private set; }
+        private int _isValid;
+        public bool Valid => Volatile.Read(ref _isValid) != 0;
 
         public TextureView(
             VulkanRenderer gd,
@@ -158,7 +160,7 @@ namespace Ryujinx.Graphics.Vulkan
                 }
             }
 
-            Valid = true;
+            _isValid = 1;
         }
 
         /// <summary>
@@ -178,7 +180,7 @@ namespace Ryujinx.Graphics.Vulkan
 
             VkFormat = format;
 
-            Valid = true;
+            _isValid = 1;
         }
 
         public Auto<DisposableImage> GetImage()
@@ -1017,10 +1019,11 @@ namespace Ryujinx.Graphics.Vulkan
         {
             if (disposing)
             {
-                Valid = false;
-
-                if (_gd.Textures.Remove(this))
+                bool wasValid = Interlocked.Exchange(ref _isValid, 0) != 0;
+                if (wasValid)
                 {
+                    _gd.Textures.Remove(this);
+
                     _imageView.Dispose();
                     _imageView2dArray?.Dispose();
 
@@ -1034,7 +1037,7 @@ namespace Ryujinx.Graphics.Vulkan
                         _imageViewDraw.Dispose();
                     }
 
-                    Storage.DecrementViewsCount();
+                    Storage?.DecrementViewsCount();
 
                     if (_renderPasses != null)
                     {
@@ -1045,22 +1048,22 @@ namespace Ryujinx.Graphics.Vulkan
                             pass.Dispose();
                         }
                     }
+
+                    if (_selfManagedViews != null)
+                    {
+                        foreach (var view in _selfManagedViews.Values)
+                        {
+                            view.Dispose();
+                        }
+
+                        _selfManagedViews = null;
+                    }
                 }
             }
         }
 
         public void Dispose()
         {
-            if (_selfManagedViews != null)
-            {
-                foreach (var view in _selfManagedViews.Values)
-                {
-                    view.Dispose();
-                }
-
-                _selfManagedViews = null;
-            }
-
             Dispose(true);
         }