diff --git a/src/Ryujinx.Graphics.Gpu/Engine/ShaderTexture.cs b/src/Ryujinx.Graphics.Gpu/Engine/ShaderTexture.cs
index 7bff1c4b8..bdb34180e 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
///
/// Shader image format
/// Texture format
- 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 8a9f37bb0..b3bc08720 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/FormatInfo.cs
@@ -7,6 +7,11 @@ namespace Ryujinx.Graphics.Gpu.Image
///
readonly struct FormatInfo
{
+ ///
+ /// An invalid texture format.
+ ///
+ public static FormatInfo Invalid { get; } = new(0, 0, 0, 0, 0);
+
///
/// A default, generic RGBA8 texture format.
///
diff --git a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
index bc315a75a..da9e5c3a9 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs
@@ -711,120 +711,5 @@ namespace Ryujinx.Graphics.Gpu.Image
return result;
}
-
- ///
- /// Gets the bytes per pixel for a image compatible format.
- ///
- /// Format
- /// Bytes per pixel, or zero if the format is not a image compatible format
- public static int GetImageFormatBytesPerPixel(Format format)
- {
- switch (format)
- {
- case Format.R8Unorm:
- case Format.R8Snorm:
- case Format.R8Uint:
- case Format.R8Sint:
- return 1;
- case Format.R16Float:
- case Format.R16Unorm:
- case Format.R16Snorm:
- case Format.R16Uint:
- case Format.R16Sint:
- case Format.R8G8Unorm:
- case Format.R8G8Snorm:
- case Format.R8G8Uint:
- case Format.R8G8Sint:
- return 2;
- case Format.R32Float:
- case Format.R32Uint:
- case Format.R32Sint:
- case Format.R16G16Float:
- case Format.R16G16Unorm:
- case Format.R16G16Snorm:
- case Format.R16G16Uint:
- case Format.R16G16Sint:
- case Format.R8G8B8A8Unorm:
- case Format.R8G8B8A8Snorm:
- case Format.R8G8B8A8Uint:
- case Format.R8G8B8A8Sint:
- case Format.R10G10B10A2Unorm:
- case Format.R10G10B10A2Uint:
- case Format.R11G11B10Float:
- return 4;
- case Format.R32G32Float:
- case Format.R32G32Uint:
- case Format.R32G32Sint:
- case Format.R16G16B16A16Float:
- case Format.R16G16B16A16Unorm:
- case Format.R16G16B16A16Snorm:
- case Format.R16G16B16A16Uint:
- case Format.R16G16B16A16Sint:
- return 8;
- case Format.R32G32B32A32Float:
- case Format.R32G32B32A32Uint:
- case Format.R32G32B32A32Sint:
- return 16;
- }
-
- return 0;
- }
-
- ///
- /// Gets the amount of components (RGBA) for a image compatible format.
- ///
- /// Format
- /// Number of components (from 1 to 4), or zero if the format is not a image compatible format
- public static int GetImageFormatComponents(Format format)
- {
- switch (format)
- {
- case Format.R8Unorm:
- case Format.R8Snorm:
- case Format.R8Uint:
- case Format.R8Sint:
- case Format.R16Float:
- case Format.R16Unorm:
- case Format.R16Snorm:
- case Format.R16Uint:
- case Format.R16Sint:
- case Format.R32Float:
- case Format.R32Uint:
- case Format.R32Sint:
- return 1;
- case Format.R8G8Unorm:
- case Format.R8G8Snorm:
- case Format.R8G8Uint:
- case Format.R8G8Sint:
- case Format.R16G16Float:
- case Format.R16G16Unorm:
- case Format.R16G16Snorm:
- case Format.R16G16Uint:
- case Format.R16G16Sint:
- case Format.R32G32Float:
- case Format.R32G32Uint:
- case Format.R32G32Sint:
- return 2;
- case Format.R11G11B10Float:
- return 3;
- case Format.R8G8B8A8Unorm:
- case Format.R8G8B8A8Snorm:
- case Format.R8G8B8A8Uint:
- case Format.R8G8B8A8Sint:
- case Format.R10G10B10A2Unorm:
- case Format.R10G10B10A2Uint:
- case Format.R16G16B16A16Float:
- case Format.R16G16B16A16Unorm:
- case Format.R16G16B16A16Snorm:
- case Format.R16G16B16A16Uint:
- case Format.R16G16B16A16Sint:
- case Format.R32G32B32A32Float:
- case Format.R32G32B32A32Uint:
- case Format.R32G32B32A32Sint:
- return 4;
- }
-
- return 0;
- }
}
}
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs
index 31abc21e8..e9930405b 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
///
/// For images, indicates the format specified on the shader.
///
- public Format Format { get; }
+ public FormatInfo FormatInfo { get; }
///
/// Shader texture host set index.
@@ -58,17 +58,17 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Constructs the texture binding information structure.
///
/// The shader sampler target type
- /// Format of the image as declared on the shader
+ /// Format of the image as declared on the shader
/// Shader texture host set index
/// The shader texture binding point
/// For array of textures, this indicates the length of the array. A value of one indicates it is not an array
/// Constant buffer slot where the texture handle is located
/// The shader texture handle (read index into the texture constant buffer)
/// The texture's usage flags, indicating how it is used in the shader
- 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 ca00c296d..72bac75e5 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs
@@ -673,7 +673,7 @@ namespace Ryujinx.Graphics.Gpu.Image
}
else
{
- ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(index, bindingInfo.Format, out texture);
+ ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(index, bindingInfo.FormatInfo, out texture);
if (texture != null)
{
@@ -867,7 +867,7 @@ namespace Ryujinx.Graphics.Gpu.Image
samplerId = TextureHandle.UnpackSamplerId(packedId);
}
- ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, bindingInfo.Format, out Texture texture);
+ ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, bindingInfo.FormatInfo, out Texture texture);
if (texture != null)
{
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
index 945f26b28..ad018f159 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
@@ -616,7 +616,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (!poolModified &&
state.TextureHandle == textureId &&
- state.ImageFormat == bindingInfo.Format &&
+ state.ImageFormat == bindingInfo.FormatInfo.Format &&
state.CachedTexture != null &&
state.CachedTexture.InvalidatedSequence == state.InvalidatedSequence)
{
@@ -643,9 +643,9 @@ namespace Ryujinx.Graphics.Gpu.Image
}
state.TextureHandle = textureId;
- state.ImageFormat = bindingInfo.Format;
+ state.ImageFormat = bindingInfo.FormatInfo.Format;
- ref readonly TextureDescriptor descriptor = ref pool.GetForBinding(textureId, bindingInfo.Format, out Texture texture);
+ ref readonly TextureDescriptor descriptor = ref pool.GetForBinding(textureId, bindingInfo.FormatInfo, out Texture texture);
specStateMatches &= specState.MatchesImage(stage, index, descriptor);
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
index 2da946ef3..5f43c1824 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
@@ -274,9 +274,10 @@ namespace Ryujinx.Graphics.Gpu.Image
/// This method assumes that the pool has been manually synchronized before doing binding.
///
/// ID of the texture. This is effectively a zero-based index
+ /// Texture format information
/// The texture with the given ID
/// The texture descriptor with the given ID
- public ref readonly TextureDescriptor GetForBinding(int id, Format format, out Texture texture)
+ public ref readonly TextureDescriptor GetForBinding(int id, FormatInfo formatInfo, out Texture texture)
{
if ((uint)id >= Items.Length)
{
@@ -286,24 +287,24 @@ namespace Ryujinx.Graphics.Gpu.Image
ref readonly TextureDescriptor descriptor = ref GetInternal(id, out texture);
- if (texture != null && format != 0 && texture.Format != format)
+ 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(format);
+ texture = aliasList.Find(formatInfo.Format);
if (texture == null)
{
TextureInfo info = GetInfo(descriptor, out int layerSize);
- info = ChangeFormat(info, format);
+ info = ChangeFormat(info, formatInfo);
texture = PhysicalMemory.TextureCache.FindOrCreateTexture(_channel.MemoryManager, TextureSearchFlags.ForSampler, info, layerSize);
if (texture != null)
{
- aliasList.Add(format, texture);
+ aliasList.Add(formatInfo.Format, texture);
}
}
}
@@ -746,25 +747,14 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Texture information
/// New format
/// Texture information with the new format
- private static TextureInfo ChangeFormat(in TextureInfo info, Format dstFormat)
+ private static TextureInfo ChangeFormat(in TextureInfo info, FormatInfo dstFormat)
{
- int dstBpp = FormatTable.GetImageFormatBytesPerPixel(dstFormat);
-
- if (dstBpp == 0)
- {
- // We don't support the format. Should never happen in practice.
-
- return info;
- }
-
- FormatInfo dstFormatInfo = new FormatInfo(dstFormat, 1, 1, dstBpp, FormatTable.GetImageFormatComponents(dstFormat));
-
int width = info.Width;
- if (info.FormatInfo.BytesPerPixel != dstBpp)
+ if (info.FormatInfo.BytesPerPixel != dstFormat.BytesPerPixel)
{
int stride = width * info.FormatInfo.BytesPerPixel;
- width = stride / dstBpp;
+ width = stride / dstFormat.BytesPerPixel;
}
return new TextureInfo(
@@ -781,7 +771,7 @@ namespace Ryujinx.Graphics.Gpu.Image
info.GobBlocksInZ,
info.GobBlocksInTileX,
info.Target,
- dstFormatInfo,
+ dstFormat,
info.DepthStencilMode,
info.SwizzleR,
info.SwizzleG,
diff --git a/src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs b/src/Ryujinx.Graphics.Gpu/Shader/CachedShaderBindings.cs
index 51be00b6e..018c5fdc0 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,