aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Vulkan/TextureStorage.cs')
-rw-r--r--src/Ryujinx.Graphics.Vulkan/TextureStorage.cs74
1 files changed, 72 insertions, 2 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs
index f78b9ed4..10b36a3f 100644
--- a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs
+++ b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs
@@ -4,6 +4,7 @@ using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
using System.Numerics;
+using System.Runtime.CompilerServices;
using Format = Ryujinx.Graphics.GAL.Format;
using VkBuffer = Silk.NET.Vulkan.Buffer;
using VkFormat = Silk.NET.Vulkan.Format;
@@ -12,6 +13,11 @@ namespace Ryujinx.Graphics.Vulkan
{
class TextureStorage : IDisposable
{
+ private struct TextureSliceInfo
+ {
+ public int BindCount;
+ }
+
private const MemoryPropertyFlags DefaultImageMemoryFlags =
MemoryPropertyFlags.DeviceLocalBit;
@@ -43,6 +49,7 @@ namespace Ryujinx.Graphics.Vulkan
private readonly Image _image;
private readonly Auto<DisposableImage> _imageAuto;
private readonly Auto<MemoryAllocation> _allocationAuto;
+ private readonly int _depthOrLayers;
private Auto<MemoryAllocation> _foreignAllocationAuto;
private Dictionary<Format, TextureStorage> _aliasedStorages;
@@ -55,6 +62,9 @@ namespace Ryujinx.Graphics.Vulkan
private int _viewsCount;
private readonly ulong _size;
+ private int _bindCount;
+ private readonly TextureSliceInfo[] _slices;
+
public VkFormat VkFormat { get; }
public unsafe TextureStorage(
@@ -73,6 +83,7 @@ namespace Ryujinx.Graphics.Vulkan
var depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1);
VkFormat = format;
+ _depthOrLayers = info.GetDepthOrLayers();
var type = info.Target.Convert();
@@ -80,7 +91,7 @@ namespace Ryujinx.Graphics.Vulkan
var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples);
- var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample);
+ var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities);
var flags = ImageCreateFlags.CreateMutableFormatBit | ImageCreateFlags.CreateExtendedUsageBit;
@@ -148,6 +159,8 @@ namespace Ryujinx.Graphics.Vulkan
InitialTransition(ImageLayout.Preinitialized, ImageLayout.General);
}
+
+ _slices = new TextureSliceInfo[levels * _depthOrLayers];
}
public TextureStorage CreateAliasedColorForDepthStorageUnsafe(Format format)
@@ -292,7 +305,7 @@ namespace Ryujinx.Graphics.Vulkan
}
}
- public static ImageUsageFlags GetImageUsage(Format format, Target target, bool supportsMsStorage)
+ public static ImageUsageFlags GetImageUsage(Format format, Target target, in HardwareCapabilities capabilities)
{
var usage = DefaultUsageFlags;
@@ -305,11 +318,19 @@ namespace Ryujinx.Graphics.Vulkan
usage |= ImageUsageFlags.ColorAttachmentBit;
}
+ bool supportsMsStorage = capabilities.SupportsShaderStorageImageMultisample;
+
if (format.IsImageCompatible() && (supportsMsStorage || !target.IsMultisample()))
{
usage |= ImageUsageFlags.StorageBit;
}
+ if (capabilities.SupportsAttachmentFeedbackLoop &&
+ (usage & (ImageUsageFlags.DepthStencilAttachmentBit | ImageUsageFlags.ColorAttachmentBit)) != 0)
+ {
+ usage |= ImageUsageFlags.AttachmentFeedbackLoopBitExt;
+ }
+
return usage;
}
@@ -510,6 +531,55 @@ namespace Ryujinx.Graphics.Vulkan
}
}
+ public void AddBinding(TextureView view)
+ {
+ // Assumes a view only has a first level.
+
+ int index = view.FirstLevel * _depthOrLayers + view.FirstLayer;
+ int layers = view.Layers;
+
+ for (int i = 0; i < layers; i++)
+ {
+ ref TextureSliceInfo info = ref _slices[index++];
+
+ info.BindCount++;
+ }
+
+ _bindCount++;
+ }
+
+ public void ClearBindings()
+ {
+ if (_bindCount != 0)
+ {
+ Array.Clear(_slices, 0, _slices.Length);
+
+ _bindCount = 0;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool IsBound(TextureView view)
+ {
+ if (_bindCount != 0)
+ {
+ int index = view.FirstLevel * _depthOrLayers + view.FirstLayer;
+ int layers = view.Layers;
+
+ for (int i = 0; i < layers; i++)
+ {
+ ref TextureSliceInfo info = ref _slices[index++];
+
+ if (info.BindCount != 0)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
public void IncrementViewsCount()
{
_viewsCount++;