aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2024-09-17 15:52:30 -0300
committerGitHub <noreply@github.com>2024-09-17 15:52:30 -0300
commiteb8132b627d3c0285dd199f4e40c6f3800bdb22d (patch)
tree970a119909a0dd901bbd8cb5454b725a08e329b3
parentccf96bf5e673456ec80f72725e4c9afa4e4c5a85 (diff)
Change image format view handling to allow view incompatible formats (#7311)1.1.1392
* Allow creating texture aliases on texture pool * Delete old image format override code * New format incompatible alias * Missing bounds check * GetForBinding now takes FormatInfo * Make FormatInfo struct more compact
-rw-r--r--src/Ryujinx.Graphics.GAL/IImageArray.cs1
-rw-r--r--src/Ryujinx.Graphics.GAL/IPipeline.cs2
-rw-r--r--src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs1
-rw-r--r--src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs1
-rw-r--r--src/Ryujinx.Graphics.GAL/Multithreading/Commands/ImageArray/ImageArraySetFormatsCommand.cs26
-rw-r--r--src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs6
-rw-r--r--src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs6
-rw-r--r--src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs4
-rw-r--r--src/Ryujinx.Graphics.Gpu/Engine/ShaderTexture.cs83
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs21
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs10
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs42
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs35
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs3
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs180
-rw-r--r--src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs15
-rw-r--r--src/Ryujinx.Graphics.Gpu/Memory/BufferTextureArrayBinding.cs11
-rw-r--r--src/Ryujinx.Graphics.Gpu/Memory/BufferTextureBinding.cs8
-rw-r--r--src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs4
-rw-r--r--src/Ryujinx.Graphics.Gpu/Window.cs2
-rw-r--r--src/Ryujinx.Graphics.OpenGL/Image/ImageArray.cs10
-rw-r--r--src/Ryujinx.Graphics.OpenGL/Pipeline.cs14
-rw-r--r--src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs15
-rw-r--r--src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs2
-rw-r--r--src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs2
-rw-r--r--src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs6
-rw-r--r--src/Ryujinx.Graphics.Vulkan/HelperShader.cs4
-rw-r--r--src/Ryujinx.Graphics.Vulkan/ImageArray.cs17
-rw-r--r--src/Ryujinx.Graphics.Vulkan/PipelineBase.cs4
-rw-r--r--src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs34
-rw-r--r--src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs4
31 files changed, 294 insertions, 279 deletions
diff --git a/src/Ryujinx.Graphics.GAL/IImageArray.cs b/src/Ryujinx.Graphics.GAL/IImageArray.cs
index d119aa9f..d87314eb 100644
--- a/src/Ryujinx.Graphics.GAL/IImageArray.cs
+++ b/src/Ryujinx.Graphics.GAL/IImageArray.cs
@@ -4,7 +4,6 @@ namespace Ryujinx.Graphics.GAL
{
public interface IImageArray : IDisposable
{
- void SetFormats(int index, Format[] imageFormats);
void SetImages(int index, ITexture[] images);
}
}
diff --git a/src/Ryujinx.Graphics.GAL/IPipeline.cs b/src/Ryujinx.Graphics.GAL/IPipeline.cs
index cbf1bc3a..b8409a57 100644
--- a/src/Ryujinx.Graphics.GAL/IPipeline.cs
+++ b/src/Ryujinx.Graphics.GAL/IPipeline.cs
@@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.GAL
void SetIndexBuffer(BufferRange buffer, IndexType type);
- void SetImage(ShaderStage stage, int binding, ITexture texture, Format imageFormat);
+ void SetImage(ShaderStage stage, int binding, ITexture texture);
void SetImageArray(ShaderStage stage, int binding, IImageArray array);
void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array);
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs b/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs
index ef227d4a..a1e6db97 100644
--- a/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs
@@ -67,7 +67,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
Register<CounterEventFlushCommand>(CommandType.CounterEventFlush);
Register<ImageArrayDisposeCommand>(CommandType.ImageArrayDispose);
- Register<ImageArraySetFormatsCommand>(CommandType.ImageArraySetFormats);
Register<ImageArraySetImagesCommand>(CommandType.ImageArraySetImages);
Register<ProgramDisposeCommand>(CommandType.ProgramDispose);
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs b/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs
index cf3f5d6c..348c8e46 100644
--- a/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs
@@ -27,7 +27,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading
CounterEventFlush,
ImageArrayDispose,
- ImageArraySetFormats,
ImageArraySetImages,
ProgramDispose,
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ImageArray/ImageArraySetFormatsCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ImageArray/ImageArraySetFormatsCommand.cs
deleted file mode 100644
index 8e3ba88a..00000000
--- a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ImageArray/ImageArraySetFormatsCommand.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using Ryujinx.Graphics.GAL.Multithreading.Model;
-using Ryujinx.Graphics.GAL.Multithreading.Resources;
-
-namespace Ryujinx.Graphics.GAL.Multithreading.Commands.ImageArray
-{
- struct ImageArraySetFormatsCommand : IGALCommand, IGALCommand<ImageArraySetFormatsCommand>
- {
- public readonly CommandType CommandType => CommandType.ImageArraySetFormats;
- private TableRef<ThreadedImageArray> _imageArray;
- private int _index;
- private TableRef<Format[]> _imageFormats;
-
- public void Set(TableRef<ThreadedImageArray> imageArray, int index, TableRef<Format[]> imageFormats)
- {
- _imageArray = imageArray;
- _index = index;
- _imageFormats = imageFormats;
- }
-
- public static void Run(ref ImageArraySetFormatsCommand command, ThreadedRenderer threaded, IRenderer renderer)
- {
- ThreadedImageArray imageArray = command._imageArray.Get(threaded);
- imageArray.Base.SetFormats(command._index, command._imageFormats.Get(threaded));
- }
- }
-}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs
index 243480a8..2ba9db52 100644
--- a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/SetImageCommand.cs
@@ -10,19 +10,17 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
private ShaderStage _stage;
private int _binding;
private TableRef<ITexture> _texture;
- private Format _imageFormat;
- public void Set(ShaderStage stage, int binding, TableRef<ITexture> texture, Format imageFormat)
+ public void Set(ShaderStage stage, int binding, TableRef<ITexture> texture)
{
_stage = stage;
_binding = binding;
_texture = texture;
- _imageFormat = imageFormat;
}
public static void Run(ref SetImageCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
- renderer.Pipeline.SetImage(command._stage, command._binding, command._texture.GetAs<ThreadedTexture>(threaded)?.Base, command._imageFormat);
+ renderer.Pipeline.SetImage(command._stage, command._binding, command._texture.GetAs<ThreadedTexture>(threaded)?.Base);
}
}
}
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs
index 19bc6f23..82587c18 100644
--- a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs
@@ -27,12 +27,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
_renderer.QueueCommand();
}
- public void SetFormats(int index, Format[] imageFormats)
- {
- _renderer.New<ImageArraySetFormatsCommand>().Set(Ref(this), index, Ref(imageFormats));
- _renderer.QueueCommand();
- }
-
public void SetImages(int index, ITexture[] images)
{
_renderer.New<ImageArraySetImagesCommand>().Set(Ref(this), index, Ref(images));
diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs
index edd79d8a..deec3664 100644
--- a/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs
+++ b/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedPipeline.cs
@@ -177,9 +177,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_renderer.QueueCommand();
}
- public void SetImage(ShaderStage stage, int binding, ITexture texture, Format imageFormat)
+ public void SetImage(ShaderStage stage, int binding, ITexture texture)
{
- _renderer.New<SetImageCommand>().Set(stage, binding, Ref(texture), imageFormat);
+ _renderer.New<SetImageCommand>().Set(stage, binding, Ref(texture));
_renderer.QueueCommand();
}
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/ShaderTexture.cs b/src/Ryujinx.Graphics.Gpu/Engine/ShaderTexture.cs
index 7bff1c4b..bdb34180 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/ShaderTexture.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/ShaderTexture.cs
@@ -1,5 +1,6 @@
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Gpu.Image;
using Ryujinx.Graphics.Shader;
namespace Ryujinx.Graphics.Gpu.Engine
@@ -61,51 +62,51 @@ namespace Ryujinx.Graphics.Gpu.Engine
/// </summary>
/// <param name="format">Shader image format</param>
/// <returns>Texture format</returns>
- public static Format GetFormat(TextureFormat format)
+ public static FormatInfo GetFormatInfo(TextureFormat format)
{
return format switch
{
#pragma warning disable IDE0055 // Disable formatting
- TextureFormat.R8Unorm => Format.R8Unorm,
- TextureFormat.R8Snorm => Format.R8Snorm,
- TextureFormat.R8Uint => Format.R8Uint,
- TextureFormat.R8Sint => Format.R8Sint,
- TextureFormat.R16Float => Format.R16Float,
- TextureFormat.R16Unorm => Format.R16Unorm,
- TextureFormat.R16Snorm => Format.R16Snorm,
- TextureFormat.R16Uint => Format.R16Uint,
- TextureFormat.R16Sint => Format.R16Sint,
- TextureFormat.R32Float => Format.R32Float,
- TextureFormat.R32Uint => Format.R32Uint,
- TextureFormat.R32Sint => Format.R32Sint,
- TextureFormat.R8G8Unorm => Format.R8G8Unorm,
- TextureFormat.R8G8Snorm => Format.R8G8Snorm,
- TextureFormat.R8G8Uint => Format.R8G8Uint,
- TextureFormat.R8G8Sint => Format.R8G8Sint,
- TextureFormat.R16G16Float => Format.R16G16Float,
- TextureFormat.R16G16Unorm => Format.R16G16Unorm,
- TextureFormat.R16G16Snorm => Format.R16G16Snorm,
- TextureFormat.R16G16Uint => Format.R16G16Uint,
- TextureFormat.R16G16Sint => Format.R16G16Sint,
- TextureFormat.R32G32Float => Format.R32G32Float,
- TextureFormat.R32G32Uint => Format.R32G32Uint,
- TextureFormat.R32G32Sint => Format.R32G32Sint,
- TextureFormat.R8G8B8A8Unorm => Format.R8G8B8A8Unorm,
- TextureFormat.R8G8B8A8Snorm => Format.R8G8B8A8Snorm,
- TextureFormat.R8G8B8A8Uint => Format.R8G8B8A8Uint,
- TextureFormat.R8G8B8A8Sint => Format.R8G8B8A8Sint,
- TextureFormat.R16G16B16A16Float => Format.R16G16B16A16Float,
- TextureFormat.R16G16B16A16Unorm => Format.R16G16B16A16Unorm,
- TextureFormat.R16G16B16A16Snorm => Format.R16G16B16A16Snorm,
- TextureFormat.R16G16B16A16Uint => Format.R16G16B16A16Uint,
- TextureFormat.R16G16B16A16Sint => Format.R16G16B16A16Sint,
- TextureFormat.R32G32B32A32Float => Format.R32G32B32A32Float,
- TextureFormat.R32G32B32A32Uint => Format.R32G32B32A32Uint,
- TextureFormat.R32G32B32A32Sint => Format.R32G32B32A32Sint,
- TextureFormat.R10G10B10A2Unorm => Format.R10G10B10A2Unorm,
- TextureFormat.R10G10B10A2Uint => Format.R10G10B10A2Uint,
- TextureFormat.R11G11B10Float => Format.R11G11B10Float,
- _ => 0,
+ TextureFormat.R8Unorm => new(Format.R8Unorm, 1, 1, 1, 1),
+ TextureFormat.R8Snorm => new(Format.R8Snorm, 1, 1, 1, 1),
+ TextureFormat.R8Uint => new(Format.R8Uint, 1, 1, 1, 1),
+ TextureFormat.R8Sint => new(Format.R8Sint, 1, 1, 1, 1),
+ TextureFormat.R16Float => new(Format.R16Float, 1, 1, 2, 1),
+ TextureFormat.R16Unorm => new(Format.R16Unorm, 1, 1, 2, 1),
+ TextureFormat.R16Snorm => new(Format.R16Snorm, 1, 1, 2, 1),
+ TextureFormat.R16Uint => new(Format.R16Uint, 1, 1, 2, 1),
+ TextureFormat.R16Sint => new(Format.R16Sint, 1, 1, 2, 1),
+ TextureFormat.R32Float => new(Format.R32Float, 1, 1, 4, 1),
+ TextureFormat.R32Uint => new(Format.R32Uint, 1, 1, 4, 1),
+ TextureFormat.R32Sint => new(Format.R32Sint, 1, 1, 4, 1),
+ TextureFormat.R8G8Unorm => new(Format.R8G8Unorm, 1, 1, 2, 2),
+ TextureFormat.R8G8Snorm => new(Format.R8G8Snorm, 1, 1, 2, 2),
+ TextureFormat.R8G8Uint => new(Format.R8G8Uint, 1, 1, 2, 2),
+ TextureFormat.R8G8Sint => new(Format.R8G8Sint, 1, 1, 2, 2),
+ TextureFormat.R16G16Float => new(Format.R16G16Float, 1, 1, 4, 2),
+ TextureFormat.R16G16Unorm => new(Format.R16G16Unorm, 1, 1, 4, 2),
+ TextureFormat.R16G16Snorm => new(Format.R16G16Snorm, 1, 1, 4, 2),
+ TextureFormat.R16G16Uint => new(Format.R16G16Uint, 1, 1, 4, 2),
+ TextureFormat.R16G16Sint => new(Format.R16G16Sint, 1, 1, 4, 2),
+ TextureFormat.R32G32Float => new(Format.R32G32Float, 1, 1, 8, 2),
+ TextureFormat.R32G32Uint => new(Format.R32G32Uint, 1, 1, 8, 2),
+ TextureFormat.R32G32Sint => new(Format.R32G32Sint, 1, 1, 8, 2),
+ TextureFormat.R8G8B8A8Unorm => new(Format.R8G8B8A8Unorm, 1, 1, 4, 4),
+ TextureFormat.R8G8B8A8Snorm => new(Format.R8G8B8A8Snorm, 1, 1, 4, 4),
+ TextureFormat.R8G8B8A8Uint => new(Format.R8G8B8A8Uint, 1, 1, 4, 4),
+ TextureFormat.R8G8B8A8Sint => new(Format.R8G8B8A8Sint, 1, 1, 4, 4),
+ TextureFormat.R16G16B16A16Float => new(Format.R16G16B16A16Float, 1, 1, 8, 4),
+ TextureFormat.R16G16B16A16Unorm => new(Format.R16G16B16A16Unorm, 1, 1, 8, 4),
+ TextureFormat.R16G16B16A16Snorm => new(Format.R16G16B16A16Snorm, 1, 1, 8, 4),
+ TextureFormat.R16G16B16A16Uint => new(Format.R16G16B16A16Uint, 1, 1, 8, 4),
+ TextureFormat.R16G16B16A16Sint => new(Format.R16G16B16A16Sint, 1, 1, 8, 4),
+ TextureFormat.R32G32B32A32Float => new(Format.R32G32B32A32Float, 1, 1, 16, 4),
+ TextureFormat.R32G32B32A32Uint => new(Format.R32G32B32A32Uint, 1, 1, 16, 4),
+ TextureFormat.R32G32B32A32Sint => new(Format.R32G32B32A32Sint, 1, 1, 16, 4),
+ TextureFormat.R10G10B10A2Unorm => new(Format.R10G10B10A2Unorm, 1, 1, 4, 4),
+ TextureFormat.R10G10B10A2Uint => new(Format.R10G10B10A2Uint, 1, 1, 4, 4),
+ TextureFormat.R11G11B10Float => new(Format.R11G11B10Float, 1, 1, 4, 3),
+ _ => FormatInfo.Invalid,
#pragma warning restore IDE0055
};
}
diff --git a/src/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs b/src/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
index 8a9f37bb..b95c684e 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
@@ -8,6 +8,11 @@ namespace Ryujinx.Graphics.Gpu.Image
readonly struct FormatInfo
{
/// <summary>
+ /// An invalid texture format.
+ /// </summary>
+ public static FormatInfo Invalid { get; } = new(0, 0, 0, 0, 0);
+
+ /// <summary>
/// A default, generic RGBA8 texture format.
/// </summary>
public static FormatInfo Default { get; } = new(Format.R8G8B8A8Unorm, 1, 1, 4, 4);
@@ -23,7 +28,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <remarks>
/// Must be 1 for non-compressed formats.
/// </remarks>
- public int BlockWidth { get; }
+ public byte BlockWidth { get; }
/// <summary>
/// The block height for compressed formats.
@@ -31,17 +36,17 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <remarks>
/// Must be 1 for non-compressed formats.
/// </remarks>
- public int BlockHeight { get; }
+ public byte BlockHeight { get; }
/// <summary>
/// The number of bytes occupied by a single pixel in memory of the texture data.
/// </summary>
- public int BytesPerPixel { get; }
+ public byte BytesPerPixel { get; }
/// <summary>
/// The maximum number of components this format has defined (in RGBA order).
/// </summary>
- public int Components { get; }
+ public byte Components { get; }
/// <summary>
/// Whenever or not the texture format is a compressed format. Determined from block size.
@@ -57,10 +62,10 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="bytesPerPixel">The number of bytes occupied by a single pixel in memory of the texture data</param>
public FormatInfo(
Format format,
- int blockWidth,
- int blockHeight,
- int bytesPerPixel,
- int components)
+ byte blockWidth,
+ byte blockHeight,
+ byte bytesPerPixel,
+ byte components)
{
Format = format;
BlockWidth = blockWidth;
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs
index 31abc21e..e9930405 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs
@@ -17,7 +17,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary>
/// For images, indicates the format specified on the shader.
/// </summary>
- public Format Format { get; }
+ public FormatInfo FormatInfo { get; }
/// <summary>
/// Shader texture host set index.
@@ -58,17 +58,17 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Constructs the texture binding information structure.
/// </summary>
/// <param name="target">The shader sampler target type</param>
- /// <param name="format">Format of the image as declared on the shader</param>
+ /// <param name="formatInfo">Format of the image as declared on the shader</param>
/// <param name="set">Shader texture host set index</param>
/// <param name="binding">The shader texture binding point</param>
/// <param name="arrayLength">For array of textures, this indicates the length of the array. A value of one indicates it is not an array</param>
/// <param name="cbufSlot">Constant buffer slot where the texture handle is located</param>
/// <param name="handle">The shader texture handle (read index into the texture constant buffer)</param>
/// <param name="flags">The texture's usage flags, indicating how it is used in the shader</param>
- public TextureBindingInfo(Target target, Format format, int set, int binding, int arrayLength, int cbufSlot, int handle, TextureUsageFlags flags)
+ public TextureBindingInfo(Target target, FormatInfo formatInfo, int set, int binding, int arrayLength, int cbufSlot, int handle, TextureUsageFlags flags)
{
Target = target;
- Format = format;
+ FormatInfo = formatInfo;
Set = set;
Binding = binding;
ArrayLength = arrayLength;
@@ -96,7 +96,7 @@ namespace Ryujinx.Graphics.Gpu.Image
int cbufSlot,
int handle,
TextureUsageFlags flags,
- bool isSamplerOnly) : this(target, 0, set, binding, arrayLength, cbufSlot, handle, flags)
+ bool isSamplerOnly) : this(target, FormatInfo.Invalid, set, binding, arrayLength, cbufSlot, handle, flags)
{
IsSamplerOnly = isSamplerOnly;
}
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs
index 8b9243b1..72bac75e 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs
@@ -659,7 +659,6 @@ namespace Ryujinx.Graphics.Gpu.Image
int length = (isSampler ? samplerPool.MaximumId : texturePool.MaximumId) + 1;
length = Math.Min(length, bindingInfo.ArrayLength);
- Format[] formats = isImage ? new Format[bindingInfo.ArrayLength] : null;
ISampler[] samplers = isImage ? null : new ISampler[bindingInfo.ArrayLength];
ITexture[] textures = new ITexture[bindingInfo.ArrayLength];
@@ -674,7 +673,7 @@ namespace Ryujinx.Graphics.Gpu.Image
}
else
{
- ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(index, out texture);
+ ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(index, bindingInfo.FormatInfo, out texture);
if (texture != null)
{
@@ -697,8 +696,6 @@ namespace Ryujinx.Graphics.Gpu.Image
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
ISampler hostSampler = sampler?.GetHostSampler(texture);
- Format format = bindingInfo.Format;
-
if (hostTexture != null && texture.Target == Target.TextureBuffer)
{
// Ensure that the buffer texture is using the correct buffer as storage.
@@ -706,26 +703,15 @@ namespace Ryujinx.Graphics.Gpu.Image
// to ensure we're not using a old buffer that was already deleted.
if (isImage)
{
- if (format == 0 && texture != null)
- {
- format = texture.Format;
- }
-
- _channel.BufferManager.SetBufferTextureStorage(stage, entry.ImageArray, hostTexture, texture.Range, bindingInfo, index, format);
+ _channel.BufferManager.SetBufferTextureStorage(stage, entry.ImageArray, hostTexture, texture.Range, bindingInfo, index);
}
else
{
- _channel.BufferManager.SetBufferTextureStorage(stage, entry.TextureArray, hostTexture, texture.Range, bindingInfo, index, format);
+ _channel.BufferManager.SetBufferTextureStorage(stage, entry.TextureArray, hostTexture, texture.Range, bindingInfo, index);
}
}
else if (isImage)
{
- if (format == 0 && texture != null)
- {
- format = texture.Format;
- }
-
- formats[index] = format;
textures[index] = hostTexture;
}
else
@@ -737,7 +723,6 @@ namespace Ryujinx.Graphics.Gpu.Image
if (isImage)
{
- entry.ImageArray.SetFormats(0, formats);
entry.ImageArray.SetImages(0, textures);
SetImageArray(stage, bindingInfo, entry.ImageArray);
@@ -863,7 +848,6 @@ namespace Ryujinx.Graphics.Gpu.Image
entry.UpdateData(cachedTextureBuffer, cachedSamplerBuffer, separateSamplerBuffer);
- Format[] formats = isImage ? new Format[bindingInfo.ArrayLength] : null;
ISampler[] samplers = isImage ? null : new ISampler[bindingInfo.ArrayLength];
ITexture[] textures = new ITexture[bindingInfo.ArrayLength];
@@ -883,7 +867,7 @@ namespace Ryujinx.Graphics.Gpu.Image
samplerId = TextureHandle.UnpackSamplerId(packedId);
}
- ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, out Texture texture);
+ ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, bindingInfo.FormatInfo, out Texture texture);
if (texture != null)
{
@@ -916,8 +900,6 @@ namespace Ryujinx.Graphics.Gpu.Image
hostSampler = sampler?.GetHostSampler(texture);
}
- Format format = bindingInfo.Format;
-
if (hostTexture != null && texture.Target == Target.TextureBuffer)
{
// Ensure that the buffer texture is using the correct buffer as storage.
@@ -925,26 +907,15 @@ namespace Ryujinx.Graphics.Gpu.Image
// to ensure we're not using a old buffer that was already deleted.
if (isImage)
{
- if (format == 0 && texture != null)
- {
- format = texture.Format;
- }
-
- _channel.BufferManager.SetBufferTextureStorage(stage, entry.ImageArray, hostTexture, texture.Range, bindingInfo, index, format);
+ _channel.BufferManager.SetBufferTextureStorage(stage, entry.ImageArray, hostTexture, texture.Range, bindingInfo, index);
}
else
{
- _channel.BufferManager.SetBufferTextureStorage(stage, entry.TextureArray, hostTexture, texture.Range, bindingInfo, index, format);
+ _channel.BufferManager.SetBufferTextureStorage(stage, entry.TextureArray, hostTexture, texture.Range, bindingInfo, index);
}
}
else if (isImage)
{
- if (format == 0 && texture != null)
- {
- format = texture.Format;
- }
-
- formats[index] = format;
textures[index] = hostTexture;
}
else
@@ -956,7 +927,6 @@ namespace Ryujinx.Graphics.Gpu.Image
if (isImage)
{
- entry.ImageArray.SetFormats(0, formats);
entry.ImageArray.SetImages(0, textures);
SetImageArray(stage, bindingInfo, entry.ImageArray);
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
index 9f1f60d9..ad018f15 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
@@ -522,7 +522,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// Ensure that the buffer texture is using the correct buffer as storage.
// Buffers are frequently re-created to accommodate larger data, so we need to re-bind
// to ensure we're not using a old buffer that was already deleted.
- _channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, texture.Range, bindingInfo, bindingInfo.Format, false);
+ _channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, texture.Range, bindingInfo, false);
// Cache is not used for buffer texture, it must always rebind.
state.CachedTexture = null;
@@ -616,6 +616,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (!poolModified &&
state.TextureHandle == textureId &&
+ state.ImageFormat == bindingInfo.FormatInfo.Format &&
state.CachedTexture != null &&
state.CachedTexture.InvalidatedSequence == state.InvalidatedSequence)
{
@@ -629,26 +630,22 @@ namespace Ryujinx.Graphics.Gpu.Image
cachedTexture.SignalModified();
}
- Format format = bindingInfo.Format == 0 ? cachedTexture.Format : bindingInfo.Format;
-
- if (state.ImageFormat != format ||
- ((usageFlags & TextureUsageFlags.NeedsScaleValue) != 0 &&
- UpdateScale(state.CachedTexture, usageFlags, scaleIndex, stage)))
+ if ((usageFlags & TextureUsageFlags.NeedsScaleValue) != 0 && UpdateScale(state.CachedTexture, usageFlags, scaleIndex, stage))
{
ITexture hostTextureRebind = state.CachedTexture.GetTargetTexture(bindingInfo.Target);
state.Texture = hostTextureRebind;
- state.ImageFormat = format;
- _context.Renderer.Pipeline.SetImage(stage, bindingInfo.Binding, hostTextureRebind, format);
+ _context.Renderer.Pipeline.SetImage(stage, bindingInfo.Binding, hostTextureRebind);
}
continue;
}
state.TextureHandle = textureId;
+ state.ImageFormat = bindingInfo.FormatInfo.Format;
- ref readonly TextureDescriptor descriptor = ref pool.GetForBinding(textureId, out Texture texture);
+ ref readonly TextureDescriptor descriptor = ref pool.GetForBinding(textureId, bindingInfo.FormatInfo, out Texture texture);
specStateMatches &= specState.MatchesImage(stage, index, descriptor);
@@ -660,14 +657,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// Buffers are frequently re-created to accommodate larger data, so we need to re-bind
// to ensure we're not using a old buffer that was already deleted.
- Format format = bindingInfo.Format;
-
- if (format == 0 && texture != null)
- {
- format = texture.Format;
- }
-
- _channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, texture.Range, bindingInfo, format, true);
+ _channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, texture.Range, bindingInfo, true);
// Cache is not used for buffer texture, it must always rebind.
state.CachedTexture = null;
@@ -689,16 +679,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
state.Texture = hostTexture;
- Format format = bindingInfo.Format;
-
- if (format == 0 && texture != null)
- {
- format = texture.Format;
- }
-
- state.ImageFormat = format;
-
- _context.Renderer.Pipeline.SetImage(stage, bindingInfo.Binding, hostTexture, format);
+ _context.Renderer.Pipeline.SetImage(stage, bindingInfo.Binding, hostTexture);
}
state.CachedTexture = texture;
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
index 3cdeac9c..8bed6363 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
@@ -739,7 +739,8 @@ namespace Ryujinx.Graphics.Gpu.Image
}
return (lhsFormat.Format == Format.R8G8B8A8Unorm && rhsFormat.Format == Format.R32G32B32A32Float) ||
- (lhsFormat.Format == Format.R8Unorm && rhsFormat.Format == Format.R8G8B8A8Unorm);
+ (lhsFormat.Format == Format.R8Unorm && rhsFormat.Format == Format.R8G8B8A8Unorm) ||
+ (lhsFormat.Format == Format.R8Unorm && rhsFormat.Format == Format.R32Uint);
}
/// <summary>
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
index 4ed0a93c..5f43c182 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
@@ -76,6 +76,76 @@ namespace Ryujinx.Graphics.Gpu.Image
private TextureDescriptor _defaultDescriptor;
/// <summary>
+ /// List of textures that shares the same memory region, but have different formats.
+ /// </summary>
+ private class TextureAliasList
+ {
+ /// <summary>
+ /// Alias texture.
+ /// </summary>
+ /// <param name="Format">Texture format</param>
+ /// <param name="Texture">Texture</param>
+ private readonly record struct Alias(Format Format, Texture Texture);
+
+ /// <summary>
+ /// List of texture aliases.
+ /// </summary>
+ private readonly List<Alias> _aliases;
+
+ /// <summary>
+ /// Creates a new instance of the texture alias list.
+ /// </summary>
+ public TextureAliasList()
+ {
+ _aliases = new List<Alias>();
+ }
+
+ /// <summary>
+ /// Adds a new texture alias.
+ /// </summary>
+ /// <param name="format">Alias format</param>
+ /// <param name="texture">Alias texture</param>
+ public void Add(Format format, Texture texture)
+ {
+ _aliases.Add(new Alias(format, texture));
+ texture.IncrementReferenceCount();
+ }
+
+ /// <summary>
+ /// Finds a texture with the requested format, or returns null if not found.
+ /// </summary>
+ /// <param name="format">Format to find</param>
+ /// <returns>Texture with the requested format, or null if not found</returns>
+ public Texture Find(Format format)
+ {
+ foreach (var alias in _aliases)
+ {
+ if (alias.Format == format)
+ {
+ return alias.Texture;
+ }
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Removes all alias textures.
+ /// </summary>
+ public void Destroy()
+ {
+ foreach (var entry in _aliases)
+ {
+ entry.Texture.DecrementReferenceCount();
+ }
+
+ _aliases.Clear();
+ }
+ }
+
+ private readonly Dictionary<Texture, TextureAliasList> _aliasLists;
+
+ /// <summary>
/// Linked list node used on the texture pool cache.
/// </summary>
public LinkedListNode<TexturePool> CacheNode { get; set; }
@@ -95,6 +165,7 @@ namespace Ryujinx.Graphics.Gpu.Image
public TexturePool(GpuContext context, GpuChannel channel, ulong address, int maximumId) : base(context, channel.MemoryManager.Physical, address, maximumId)
{
_channel = channel;
+ _aliasLists = new Dictionary<Texture, TextureAliasList>();
}
/// <summary>
@@ -115,14 +186,13 @@ namespace Ryujinx.Graphics.Gpu.Image
if (texture == null)
{
- TextureInfo info = GetInfo(descriptor, out int layerSize);
-
// The dereference queue can put our texture back on the cache.
if ((texture = ProcessDereferenceQueue(id)) != null)
{
return ref descriptor;
}
+ TextureInfo info = GetInfo(descriptor, out int layerSize);
texture = PhysicalMemory.TextureCache.FindOrCreateTexture(_channel.MemoryManager, TextureSearchFlags.ForSampler, info, layerSize);
// If this happens, then the texture address is invalid, we can't add it to the cache.
@@ -198,6 +268,51 @@ namespace Ryujinx.Graphics.Gpu.Image
}
/// <summary>
+ /// Gets the texture descriptor and texture with the given ID.
+ /// </summary>
+ /// <remarks>
+ /// This method assumes that the pool has been manually synchronized before doing binding.
+ /// </remarks>
+ /// <param name="id">ID of the texture. This is effectively a zero-based index</param>
+ /// <param name="formatInfo">Texture format information</param>
+ /// <param name="texture">The texture with the given ID</param>
+ /// <returns>The texture descriptor with the given ID</returns>
+ public ref readonly TextureDescriptor GetForBinding(int id, FormatInfo formatInfo, out Texture texture)
+ {
+ if ((uint)id >= Items.Length)
+ {
+ texture = null;
+ return ref _defaultDescriptor;
+ }
+
+ ref readonly TextureDescriptor descriptor = ref GetInternal(id, out texture);
+
+ if (texture != null && formatInfo.Format != 0 && texture.Format != formatInfo.Format)
+ {
+ if (!_aliasLists.TryGetValue(texture, out TextureAliasList aliasList))
+ {
+ _aliasLists.Add(texture, aliasList = new TextureAliasList());
+ }
+
+ texture = aliasList.Find(formatInfo.Format);
+
+ if (texture == null)
+ {
+ TextureInfo info = GetInfo(descriptor, out int layerSize);
+ info = ChangeFormat(info, formatInfo);
+ texture = PhysicalMemory.TextureCache.FindOrCreateTexture(_channel.MemoryManager, TextureSearchFlags.ForSampler, info, layerSize);
+
+ if (texture != null)
+ {
+ aliasList.Add(formatInfo.Format, texture);
+ }
+ }
+ }
+
+ return ref descriptor;
+ }
+
+ /// <summary>
/// Checks if the pool was modified, and returns the last sequence number where a modification was detected.
/// </summary>
/// <returns>A number that increments each time a modification is detected</returns>
@@ -234,6 +349,7 @@ namespace Ryujinx.Graphics.Gpu.Image
else
{
texture.DecrementReferenceCount();
+ RemoveAliasList(texture);
}
}
@@ -327,6 +443,8 @@ namespace Ryujinx.Graphics.Gpu.Image
{
texture.DecrementReferenceCount();
}
+
+ RemoveAliasList(texture);
}
return null;
@@ -369,6 +487,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (Interlocked.Exchange(ref Items[id], null) != null)
{
texture.DecrementReferenceCount(this, id);
+ RemoveAliasList(texture);
}
}
}
@@ -623,13 +742,68 @@ namespace Ryujinx.Graphics.Gpu.Image
}
/// <summary>
+ /// Changes the format on the texture information structure, and also adjusts the width for the new format if needed.
+ /// </summary>
+ /// <param name="info">Texture information</param>
+ /// <param name="dstFormat">New format</param>
+ /// <returns>Texture information with the new format</returns>
+ private static TextureInfo ChangeFormat(in TextureInfo info, FormatInfo dstFormat)
+ {
+ int width = info.Width;
+
+ if (info.FormatInfo.BytesPerPixel != dstFormat.BytesPerPixel)
+ {
+ int stride = width * info.FormatInfo.BytesPerPixel;
+ width = stride / dstFormat.BytesPerPixel;
+ }
+
+ return new TextureInfo(
+ info.GpuAddress,
+ width,
+ info.Height,
+ info.DepthOrLayers,
+ info.Levels,
+ info.SamplesInX,
+ info.SamplesInY,
+ info.Stride,
+ info.IsLinear,
+ info.GobBlocksInY,
+ info.GobBlocksInZ,
+ info.GobBlocksInTileX,
+ info.Target,
+ dstFormat,
+ info.DepthStencilMode,
+ info.SwizzleR,
+ info.SwizzleG,
+ info.SwizzleB,
+ info.SwizzleA);
+ }
+
+ /// <summary>
+ /// Removes all aliases for a texture.
+ /// </summary>
+ /// <param name="texture">Texture to have the aliases removed</param>
+ private void RemoveAliasList(Texture texture)
+ {
+ if (_aliasLists.TryGetValue(texture, out TextureAliasList aliasList))
+ {
+ _aliasLists.Remove(texture);
+ aliasList.Destroy();
+ }
+ }
+
+ /// <summary>
/// Decrements the reference count of the texture.
/// This indicates that the texture pool is not using it anymore.
/// </summary>
/// <param name="item">The texture to be deleted</param>
protected override void Delete(Texture item)
{
- item?.DecrementReferenceCount(this);
+ if (item != null)
+ {
+ item.DecrementReferenceCount(this);
+ RemoveAliasList(item);
+ }
}
public override void Dispose()
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
index 26d9501c..409867e0 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
@@ -509,7 +509,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (binding.IsImage)
{
- _context.Renderer.Pipeline.SetImage(binding.Stage, binding.BindingInfo.Binding, binding.Texture, binding.Format);
+ _context.Renderer.Pipeline.SetImage(binding.Stage, binding.BindingInfo.Binding, binding.Texture);
}
else
{
@@ -873,12 +873,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
ITexture texture,
MultiRange range,
TextureBindingInfo bindingInfo,
- Format format,
bool isImage)
{
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(range, BufferStageUtils.TextureBuffer(stage, bindingInfo.Flags));
- _bufferTextures.Add(new BufferTextureBinding(stage, texture, range, bindingInfo, format, isImage));
+ _bufferTextures.Add(new BufferTextureBinding(stage, texture, range, bindingInfo, isImage));
}
/// <summary>
@@ -897,12 +896,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
ITexture texture,
MultiRange range,
TextureBindingInfo bindingInfo,
- int index,
- Format format)
+ int index)
{
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(range, BufferStageUtils.TextureBuffer(stage, bindingInfo.Flags));
- _bufferTextureArrays.Add(new BufferTextureArrayBinding<ITextureArray>(array, texture, range, bindingInfo, index, format));
+ _bufferTextureArrays.Add(new BufferTextureArrayBinding<ITextureArray>(array, texture, range, bindingInfo, index));
}
/// <summary>
@@ -921,12 +919,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
ITexture texture,
MultiRange range,
TextureBindingInfo bindingInfo,
- int index,
- Format format)
+ int index)
{
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(range, BufferStageUtils.TextureBuffer(stage, bindingInfo.Flags));
- _bufferImageArrays.Add(new BufferTextureArrayBinding<IImageArray>(array, texture, range, bindingInfo, index, format));
+ _bufferImageArrays.Add(new BufferTextureArrayBinding<IImageArray>(array, texture, range, bindingInfo, index));
}
/// <summary>
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferTextureArrayBinding.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferTextureArrayBinding.cs
index fa79e4f9..a5338fa5 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/BufferTextureArrayBinding.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferTextureArrayBinding.cs
@@ -35,32 +35,25 @@ namespace Ryujinx.Graphics.Gpu.Memory
public int Index { get; }
/// <summary>
- /// The image format for the binding.
- /// </summary>
- public Format Format { get; }
-
- /// <summary>
/// Create a new buffer texture binding.
/// </summary>
+ /// <param name="array">Array</param>
/// <param name="texture">Buffer texture</param>
/// <param name="range">Physical ranges of memory where the buffer texture data is located</param>
/// <param name="bindingInfo">Binding info</param>
/// <param name="index">Index of the binding on the array</param>
- /// <param name="format">Binding format</param>
public BufferTextureArrayBinding(
T array,
ITexture texture,
MultiRange range,
TextureBindingInfo bindingInfo,
- int index,
- Format format)
+ int index)
{
Array = array;
Texture = texture;
Range = range;
BindingInfo = bindingInfo;
Index = index;
- Format = format;
}
}
}
diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferTextureBinding.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferTextureBinding.cs
index bf0beffa..1a3fde5b 100644
--- a/src/Ryujinx.Graphics.Gpu/Memory/BufferTextureBinding.cs
+++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferTextureBinding.cs
@@ -31,11 +31,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
public TextureBindingInfo BindingInfo { get; }
/// <summary>
- /// The image format for the binding.
- /// </summary>
- public Format Format { get; }
-
- /// <summary>
/// Whether the binding is for an image or a sampler.
/// </summary>
public bool IsImage { get; }
@@ -47,21 +42,18 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="texture">Buffer texture</param>
/// <param name="range">Physical ranges of memory where the buffer texture data is located</param>
/// <param name="bindingInfo">Binding info</param>
- /// <param name="format">Binding format</param>
/// <param name="isImage">Whether the binding is for an image or a sampler</param>
public BufferTextureBinding(
ShaderStage stage,
ITexture texture,
MultiRange range,
TextureBindingInfo bindingInfo,
- Format format,
bool isImage)
{
Stage = stage;
Texture = texture;
Range = range;
BindingInfo = bindingInfo;
- Format = format;
IsImage = isImage;
}
}
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs b/src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs
index 51be00b6..018c5fdc 100644
--- a/src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs
+++ b/src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs
@@ -86,11 +86,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
ImageBindings[i] = stage.Info.Images.Select(descriptor =>
{
Target target = ShaderTexture.GetTarget(descriptor.Type);
- Format format = ShaderTexture.GetFormat(descriptor.Format);
+ FormatInfo formatInfo = ShaderTexture.GetFormatInfo(descriptor.Format);
var result = new TextureBindingInfo(
target,
- format,
+ formatInfo,
descriptor.Set,
descriptor.Binding,
descriptor.ArrayLength,
diff --git a/src/Ryujinx.Graphics.Gpu/Window.cs b/src/Ryujinx.Graphics.Gpu/Window.cs
index 3b236853..59cd4c8a 100644
--- a/src/Ryujinx.Graphics.Gpu/Window.cs
+++ b/src/Ryujinx.Graphics.Gpu/Window.cs
@@ -131,7 +131,7 @@ namespace Ryujinx.Graphics.Gpu
bool isLinear,
int gobBlocksInY,
Format format,
- int bytesPerPixel,
+ byte bytesPerPixel,
ImageCrop crop,
Action<GpuContext, object> acquireCallback,
Action<object> releaseCallback,
diff --git a/src/Ryujinx.Graphics.OpenGL/Image/ImageArray.cs b/src/Ryujinx.Graphics.OpenGL/Image/ImageArray.cs
index 6198823d..3486f29d 100644
--- a/src/Ryujinx.Graphics.OpenGL/Image/ImageArray.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Image/ImageArray.cs
@@ -1,6 +1,5 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL;
-using System;
namespace Ryujinx.Graphics.OpenGL.Image
{
@@ -19,14 +18,6 @@ namespace Ryujinx.Graphics.OpenGL.Image
_images = new TextureRef[size];
}
- public void SetFormats(int index, GAL.Format[] imageFormats)
- {
- for (int i = 0; i < imageFormats.Length; i++)
- {
- _images[index + i].Format = imageFormats[i];
- }
- }
-
public void SetImages(int index, ITexture[] images)
{
for (int i = 0; i < images.Length; i++)
@@ -36,6 +27,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
if (image is TextureBase imageBase)
{
_images[index + i].Handle = imageBase.Handle;
+ _images[index + i].Format = imageBase.Format;
}
else
{
diff --git a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs
index 54f6b3f7..27aacac1 100644
--- a/src/Ryujinx.Graphics.OpenGL/Pipeline.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Pipeline.cs
@@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.OpenGL
private readonly Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount];
- private readonly (TextureBase, Format)[] _images;
+ private readonly TextureBase[] _images;
private TextureBase _unit0Texture;
private Sampler _unit0Sampler;
@@ -78,7 +78,7 @@ namespace Ryujinx.Graphics.OpenGL
_fragmentOutputMap = uint.MaxValue;
_componentMasks = uint.MaxValue;
- _images = new (TextureBase, Format)[SavedImages];
+ _images = new TextureBase[SavedImages];
_tfbs = new BufferHandle[Constants.MaxTransformFeedbackBuffers];
_tfbTargets = new BufferRange[Constants.MaxTransformFeedbackBuffers];
@@ -935,11 +935,11 @@ namespace Ryujinx.Graphics.OpenGL
SetFrontFace(_frontFace = frontFace.Convert());
}
- public void SetImage(ShaderStage stage, int binding, ITexture texture, Format imageFormat)
+ public void SetImage(ShaderStage stage, int binding, ITexture texture)
{
if ((uint)binding < SavedImages)
{
- _images[binding] = (texture as TextureBase, imageFormat);
+ _images[binding] = texture as TextureBase;
}
if (texture == null)
@@ -950,7 +950,7 @@ namespace Ryujinx.Graphics.OpenGL
TextureBase texBase = (TextureBase)texture;
- SizedInternalFormat format = FormatTable.GetImageFormat(imageFormat);
+ SizedInternalFormat format = FormatTable.GetImageFormat(texBase.Format);
if (format != 0)
{
@@ -1622,11 +1622,11 @@ namespace Ryujinx.Graphics.OpenGL
{
for (int i = 0; i < SavedImages; i++)
{
- (TextureBase texBase, Format imageFormat) = _images[i];
+ TextureBase texBase = _images[i];
if (texBase != null)
{
- SizedInternalFormat format = FormatTable.GetImageFormat(imageFormat);
+ SizedInternalFormat format = FormatTable.GetImageFormat(texBase.Format);
if (format != 0)
{
diff --git a/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs b/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs
index 298526d5..3780dc17 100644
--- a/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs
+++ b/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs
@@ -82,7 +82,6 @@ namespace Ryujinx.Graphics.Vulkan
private readonly ImageRef[] _imageRefs;
private readonly TextureBuffer[] _bufferTextureRefs;
private readonly TextureBuffer[] _bufferImageRefs;
- private readonly Format[] _bufferImageFormats;
private ArrayRef<TextureArray>[] _textureArrayRefs;
private ArrayRef<ImageArray>[] _imageArrayRefs;
@@ -141,7 +140,6 @@ namespace Ryujinx.Graphics.Vulkan
_imageRefs = new ImageRef[Constants.MaxImageBindings * 2];
_bufferTextureRefs = new TextureBuffer[Constants.MaxTextureBindings * 2];
_bufferImageRefs = new TextureBuffer[Constants.MaxImageBindings * 2];
- _bufferImageFormats = new Format[Constants.MaxImageBindings * 2];
_textureArrayRefs = Array.Empty<ArrayRef<TextureArray>>();
_imageArrayRefs = Array.Empty<ArrayRef<ImageArray>>();
@@ -391,17 +389,11 @@ namespace Ryujinx.Graphics.Vulkan
_dirty = DirtyFlags.All;
}
- public void SetImage(
- CommandBufferScoped cbs,
- ShaderStage stage,
- int binding,
- ITexture image,
- Format imageFormat)
+ public void SetImage(CommandBufferScoped cbs, ShaderStage stage, int binding, ITexture image)
{
if (image is TextureBuffer imageBuffer)
{
_bufferImageRefs[binding] = imageBuffer;
- _bufferImageFormats[binding] = imageFormat;
}
else if (image is TextureView view)
{
@@ -410,13 +402,12 @@ namespace Ryujinx.Graphics.Vulkan
iRef.View?.ClearUsage(FeedbackLoopHazards);
view?.PrepareForUsage(cbs, stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
- iRef = new(stage, view, view.GetView(imageFormat).GetIdentityImageView());
+ iRef = new(stage, view, view.GetIdentityImageView());
}
else
{
_imageRefs[binding] = default;
_bufferImageRefs[binding] = null;
- _bufferImageFormats[binding] = default;
}
SignalDirty(DirtyFlags.Image);
@@ -923,7 +914,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < count; i++)
{
- bufferImages[i] = _bufferImageRefs[binding + i]?.GetBufferView(cbs, _bufferImageFormats[binding + i], true) ?? default;
+ bufferImages[i] = _bufferImageRefs[binding + i]?.GetBufferView(cbs, true) ?? default;
}
tu.Push<BufferView>(bufferImages[..count]);
diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs b/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs
index c4501ca1..080dde5e 100644
--- a/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs
+++ b/src/Ryujinx.Graphics.Vulkan/Effects/FsrScalingFilter.cs
@@ -154,7 +154,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
_pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(2, buffer.Range) });
- _pipeline.SetImage(ShaderStage.Compute, 0, _intermediaryTexture, FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format));
+ _pipeline.SetImage(ShaderStage.Compute, 0, _intermediaryTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
_pipeline.ComputeBarrier();
diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs b/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs
index 70b3b32a..26314b7b 100644
--- a/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs
+++ b/src/Ryujinx.Graphics.Vulkan/Effects/FxaaPostProcessingEffect.cs
@@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
var dispatchX = BitUtils.DivRoundUp(view.Width, IPostProcessingEffect.LocalGroupSize);
var dispatchY = BitUtils.DivRoundUp(view.Height, IPostProcessingEffect.LocalGroupSize);
- _pipeline.SetImage(ShaderStage.Compute, 0, _texture, FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format));
+ _pipeline.SetImage(ShaderStage.Compute, 0, _texture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
_pipeline.ComputeBarrier();
diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs b/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs
index 6d80f4a4..a8e68f42 100644
--- a/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs
+++ b/src/Ryujinx.Graphics.Vulkan/Effects/SmaaPostProcessingEffect.cs
@@ -219,7 +219,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
buffer.Holder.SetDataUnchecked(buffer.Offset, resolutionBuffer);
_pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(2, buffer.Range) });
- _pipeline.SetImage(ShaderStage.Compute, 0, _edgeOutputTexture, FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format));
+ _pipeline.SetImage(ShaderStage.Compute, 0, _edgeOutputTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
_pipeline.ComputeBarrier();
@@ -229,7 +229,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, _edgeOutputTexture, _samplerLinear);
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 3, _areaTexture, _samplerLinear);
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 4, _searchTexture, _samplerLinear);
- _pipeline.SetImage(ShaderStage.Compute, 0, _blendOutputTexture, FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format));
+ _pipeline.SetImage(ShaderStage.Compute, 0, _blendOutputTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
_pipeline.ComputeBarrier();
@@ -238,7 +238,7 @@ namespace Ryujinx.Graphics.Vulkan.Effects
_pipeline.Specialize(_specConstants);
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 3, _blendOutputTexture, _samplerLinear);
_pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, view, _samplerLinear);
- _pipeline.SetImage(ShaderStage.Compute, 0, _outputTexture, FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format));
+ _pipeline.SetImage(ShaderStage.Compute, 0, _outputTexture.GetView(FormatTable.ConvertRgba8SrgbToUnorm(view.Info.Format)));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
_pipeline.ComputeBarrier();
diff --git a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
index 73aa95c7..b7c42aff 100644
--- a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
+++ b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
@@ -1039,7 +1039,7 @@ namespace Ryujinx.Graphics.Vulkan
var dstView = Create2DLayerView(dst, dstLayer + z, dstLevel + l);
_pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Compute, 0, srcView, null);
- _pipeline.SetImage(ShaderStage.Compute, 0, dstView, dstFormat);
+ _pipeline.SetImage(ShaderStage.Compute, 0, dstView.GetView(dstFormat));
int dispatchX = (Math.Min(srcView.Info.Width, dstView.Info.Width) + 31) / 32;
int dispatchY = (Math.Min(srcView.Info.Height, dstView.Info.Height) + 31) / 32;
@@ -1168,7 +1168,7 @@ namespace Ryujinx.Graphics.Vulkan
var dstView = Create2DLayerView(dst, dstLayer + z, 0);
_pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Compute, 0, srcView, null);
- _pipeline.SetImage(ShaderStage.Compute, 0, dstView, format);
+ _pipeline.SetImage(ShaderStage.Compute, 0, dstView.GetView(format));
_pipeline.DispatchCompute(dispatchX, dispatchY, 1);
diff --git a/src/Ryujinx.Graphics.Vulkan/ImageArray.cs b/src/Ryujinx.Graphics.Vulkan/ImageArray.cs
index 467b0111..019286d2 100644
--- a/src/Ryujinx.Graphics.Vulkan/ImageArray.cs
+++ b/src/Ryujinx.Graphics.Vulkan/ImageArray.cs
@@ -13,7 +13,6 @@ namespace Ryujinx.Graphics.Vulkan
{
public TextureStorage Storage;
public TextureView View;
- public GAL.Format ImageFormat;
}
private readonly TextureRef[] _textureRefs;
@@ -52,16 +51,6 @@ namespace Ryujinx.Graphics.Vulkan
_isBuffer = isBuffer;
}
- public void SetFormats(int index, GAL.Format[] imageFormats)
- {
- for (int i = 0; i < imageFormats.Length; i++)
- {
- _textureRefs[index + i].ImageFormat = imageFormats[i];
- }
-
- SetDirty();
- }
-
public void SetImages(int index, ITexture[] images)
{
for (int i = 0; i < images.Length; i++)
@@ -142,7 +131,7 @@ namespace Ryujinx.Graphics.Vulkan
ref var texture = ref textures[i];
ref var refs = ref _textureRefs[i];
- if (i > 0 && _textureRefs[i - 1].View == refs.View && _textureRefs[i - 1].ImageFormat == refs.ImageFormat)
+ if (i > 0 && _textureRefs[i - 1].View == refs.View)
{
texture = textures[i - 1];
@@ -150,7 +139,7 @@ namespace Ryujinx.Graphics.Vulkan
}
texture.ImageLayout = ImageLayout.General;
- texture.ImageView = refs.View?.GetView(refs.ImageFormat).GetIdentityImageView().Get(cbs).Value ?? default;
+ texture.ImageView = refs.View?.GetIdentityImageView().Get(cbs).Value ?? default;
if (texture.ImageView.Handle == 0)
{
@@ -167,7 +156,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int i = 0; i < bufferTextures.Length; i++)
{
- bufferTextures[i] = _bufferTextureRefs[i]?.GetBufferView(cbs, _textureRefs[i].ImageFormat, true) ?? default;
+ bufferTextures[i] = _bufferTextureRefs[i]?.GetBufferView(cbs, true) ?? default;
}
return bufferTextures;
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
index 20c4b257..86fab760 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
@@ -836,9 +836,9 @@ namespace Ryujinx.Graphics.Vulkan
SignalStateChange();
}
- public void SetImage(ShaderStage stage, int binding, ITexture image, Format imageFormat)
+ public void SetImage(ShaderStage stage, int binding, ITexture image)
{
- _descriptorSetUpdater.SetImage(Cbs, stage, binding, image, imageFormat);
+ _descriptorSetUpdater.SetImage(Cbs, stage, binding, image);
}
public void SetImage(int binding, Auto<DisposableImageView> image)
diff --git a/src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs b/src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs
index e0694b19..bc1a5096 100644
--- a/src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs
+++ b/src/Ryujinx.Graphics.Vulkan/TextureBuffer.cs
@@ -16,7 +16,6 @@ namespace Ryujinx.Graphics.Vulkan
private int _offset;
private int _size;
private Auto<DisposableBufferView> _bufferView;
- private Dictionary<Format, Auto<DisposableBufferView>> _selfManagedViews;
private int _bufferCount;
@@ -80,16 +79,6 @@ namespace Ryujinx.Graphics.Vulkan
private void ReleaseImpl()
{
- if (_selfManagedViews != null)
- {
- foreach (var bufferView in _selfManagedViews.Values)
- {
- bufferView.Dispose();
- }
-
- _selfManagedViews = null;
- }
-
_bufferView?.Dispose();
_bufferView = null;
}
@@ -137,28 +126,5 @@ namespace Ryujinx.Graphics.Vulkan
return _bufferView?.Get(cbs, _offset, _size, write).Value ?? default;
}
-
- public BufferView GetBufferView(CommandBufferScoped cbs, Format format, bool write)
- {
- var vkFormat = FormatTable.GetFormat(format);
- if (vkFormat == VkFormat)
- {
- return GetBufferView(cbs, write);
- }
-
- if (_selfManagedViews != null && _selfManagedViews.TryGetValue(format, out var bufferView))
- {
- return bufferView.Get(cbs, _offset, _size, write).Value;
- }
-
- bufferView = _gd.BufferManager.CreateView(_bufferHandle, vkFormat, _offset, _size, ReleaseImpl);
-
- if (bufferView != null)
- {
- (_selfManagedViews ??= new Dictionary<Format, Auto<DisposableBufferView>>()).Add(format, bufferView);
- }
-
- return bufferView?.Get(cbs, _offset, _size, write).Value ?? default;
- }
}
}
diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
index fd517b1a..4c17e7ae 100644
--- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
+++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/SurfaceFlinger.cs
@@ -412,9 +412,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
Format format = ConvertColorFormat(item.GraphicBuffer.Object.Buffer.Surfaces[0].ColorFormat);
- int bytesPerPixel =
+ byte bytesPerPixel =
format == Format.B5G6R5Unorm ||
- format == Format.R4G4B4A4Unorm ? 2 : 4;
+ format == Format.R4G4B4A4Unorm ? (byte)2 : (byte)4;
int gobBlocksInY = 1 << item.GraphicBuffer.Object.Buffer.Surfaces[0].BlockHeightLog2;