diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs index 726eb459..a7f13893 100644 --- a/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/Ryujinx.Graphics.GAL/IPipeline.cs @@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.GAL void SetIndexBuffer(BufferRange buffer, IndexType type); - void SetImage(int index, ShaderStage stage, ITexture texture); + void SetImage(int index, ShaderStage stage, ITexture texture, Format imageFormat); void SetLogicOpState(bool enable, LogicalOp op); diff --git a/Ryujinx.Graphics.Gpu/Engine/Compute.cs b/Ryujinx.Graphics.Gpu/Engine/Compute.cs index d718d469..1219ef0c 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Compute.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Compute.cs @@ -128,7 +128,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { var descriptor = info.Textures[index]; - Target target = GetTarget(descriptor.Type); + Target target = ShaderTexture.GetTarget(descriptor.Type); if (descriptor.IsBindless) { @@ -148,9 +148,10 @@ namespace Ryujinx.Graphics.Gpu.Engine { var descriptor = info.Images[index]; - Target target = GetTarget(descriptor.Type); + Target target = ShaderTexture.GetTarget(descriptor.Type); + Format format = ShaderTexture.GetFormat(descriptor.Format); - imageBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex, descriptor.Flags); + imageBindings[index] = new TextureBindingInfo(target, format, descriptor.HandleIndex, descriptor.Flags); } TextureManager.SetComputeImages(imageBindings); diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index 7f567071..d4988f35 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -1014,7 +1014,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { var descriptor = info.Textures[index]; - Target target = GetTarget(descriptor.Type); + Target target = ShaderTexture.GetTarget(descriptor.Type); if (descriptor.IsBindless) { @@ -1034,9 +1034,10 @@ namespace Ryujinx.Graphics.Gpu.Engine { var descriptor = info.Images[index]; - Target target = GetTarget(descriptor.Type); + Target target = ShaderTexture.GetTarget(descriptor.Type); + Format format = ShaderTexture.GetFormat(descriptor.Format); - imageBindings[index] = new TextureBindingInfo(target, descriptor.HandleIndex, descriptor.Flags); + imageBindings[index] = new TextureBindingInfo(target, format, descriptor.HandleIndex, descriptor.Flags); } TextureManager.SetGraphicsImages(stage, imageBindings); @@ -1096,53 +1097,6 @@ namespace Ryujinx.Graphics.Gpu.Engine } } - /// - /// Gets texture target from a sampler type. - /// - /// Sampler type - /// Texture target value - private static Target GetTarget(SamplerType type) - { - type &= ~(SamplerType.Indexed | SamplerType.Shadow); - - switch (type) - { - case SamplerType.Texture1D: - return Target.Texture1D; - - case SamplerType.TextureBuffer: - return Target.TextureBuffer; - - case SamplerType.Texture1D | SamplerType.Array: - return Target.Texture1DArray; - - case SamplerType.Texture2D: - return Target.Texture2D; - - case SamplerType.Texture2D | SamplerType.Array: - return Target.Texture2DArray; - - case SamplerType.Texture2D | SamplerType.Multisample: - return Target.Texture2DMultisample; - - case SamplerType.Texture2D | SamplerType.Multisample | SamplerType.Array: - return Target.Texture2DMultisampleArray; - - case SamplerType.Texture3D: - return Target.Texture3D; - - case SamplerType.TextureCube: - return Target.Cubemap; - - case SamplerType.TextureCube | SamplerType.Array: - return Target.CubemapArray; - } - - Logger.Warning?.Print(LogClass.Gpu, $"Invalid sampler type \"{type}\"."); - - return Target.Texture2D; - } - /// /// Issues a texture barrier. /// This waits until previous texture writes from the GPU to finish, before diff --git a/Ryujinx.Graphics.Gpu/Engine/ShaderTexture.cs b/Ryujinx.Graphics.Gpu/Engine/ShaderTexture.cs new file mode 100644 index 00000000..e1e3085b --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/ShaderTexture.cs @@ -0,0 +1,111 @@ +using Ryujinx.Common.Logging; +using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Shader; + +namespace Ryujinx.Graphics.Gpu.Engine +{ + /// + /// Shader texture properties conversion methods. + /// + static class ShaderTexture + { + /// + /// Gets a texture target from a sampler type. + /// + /// Sampler type + /// Texture target value + public static Target GetTarget(SamplerType type) + { + type &= ~(SamplerType.Indexed | SamplerType.Shadow); + + switch (type) + { + case SamplerType.Texture1D: + return Target.Texture1D; + + case SamplerType.TextureBuffer: + return Target.TextureBuffer; + + case SamplerType.Texture1D | SamplerType.Array: + return Target.Texture1DArray; + + case SamplerType.Texture2D: + return Target.Texture2D; + + case SamplerType.Texture2D | SamplerType.Array: + return Target.Texture2DArray; + + case SamplerType.Texture2D | SamplerType.Multisample: + return Target.Texture2DMultisample; + + case SamplerType.Texture2D | SamplerType.Multisample | SamplerType.Array: + return Target.Texture2DMultisampleArray; + + case SamplerType.Texture3D: + return Target.Texture3D; + + case SamplerType.TextureCube: + return Target.Cubemap; + + case SamplerType.TextureCube | SamplerType.Array: + return Target.CubemapArray; + } + + Logger.Warning?.Print(LogClass.Gpu, $"Invalid sampler type \"{type}\"."); + + return Target.Texture2D; + } + + /// + /// Gets a texture format from a shader image format. + /// + /// Shader image format + /// Texture format + public static Format GetFormat(TextureFormat format) + { + return format switch + { + 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 + }; + } + } +} diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index e3c3a30a..6778567c 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -897,19 +897,6 @@ namespace Ryujinx.Graphics.Gpu.Image Info.SamplesInY == info.SamplesInY) ? result : TextureViewCompatibility.Incompatible; } - /// - /// Checks if the view format is compatible with this texture format. - /// In general, the formats are considered compatible if the bytes per pixel values are equal, - /// but there are more complex rules for some formats, like compressed or depth-stencil formats. - /// This follows the host API copy compatibility rules. - /// - /// Texture information of the texture view - /// True if the formats are compatible, false otherwise - private bool ViewFormatCompatible(TextureInfo info) - { - return TextureCompatibility.FormatCompatible(Info.FormatInfo, info.FormatInfo); - } - /// /// Gets a texture of the specified target type from this texture. /// This can be used to get an array texture from a non-array texture and vice-versa. diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs index 175f8863..422b66e2 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingInfo.cs @@ -14,6 +14,11 @@ namespace Ryujinx.Graphics.Gpu.Image /// public Target Target { get; } + /// + /// For images, indicates the format specified on the shader. + /// + public Format Format { get; } + /// /// Shader texture handle. /// This is an index into the texture constant buffer. @@ -47,11 +52,13 @@ 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 /// 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, int handle, TextureUsageFlags flags) + public TextureBindingInfo(Target target, Format format, int handle, TextureUsageFlags flags) { Target = target; + Format = format; Handle = handle; IsBindless = false; @@ -62,6 +69,16 @@ namespace Ryujinx.Graphics.Gpu.Image Flags = flags; } + /// + /// Constructs the texture binding information structure. + /// + /// The shader sampler target type + /// 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, int handle, TextureUsageFlags flags) : this(target, (Format)0, handle, flags) + { + } + /// /// Constructs the bindless texture binding information structure. /// @@ -72,6 +89,7 @@ namespace Ryujinx.Graphics.Gpu.Image public TextureBindingInfo(Target target, int cbufSlot, int cbufOffset, TextureUsageFlags flags) { Target = target; + Format = 0; Handle = 0; IsBindless = true; diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs index be78c827..e7800314 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs @@ -302,7 +302,14 @@ namespace Ryujinx.Graphics.Gpu.Image { _imageState[stageIndex][index].Texture = hostTexture; - _context.Renderer.Pipeline.SetImage(index, stage, hostTexture); + Format format = binding.Format; + + if (format == 0) + { + format = texture.Format; + } + + _context.Renderer.Pipeline.SetImage(index, stage, hostTexture, format); } } } diff --git a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs index 6db10c96..0eaa534b 100644 --- a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs +++ b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs @@ -256,6 +256,7 @@ namespace Ryujinx.Graphics.Gpu.Shader Format.R8G8B8A8Snorm => TextureFormat.R8G8B8A8Snorm, Format.R8G8B8A8Uint => TextureFormat.R8G8B8A8Uint, Format.R8G8B8A8Sint => TextureFormat.R8G8B8A8Sint, + Format.R8G8B8A8Srgb => TextureFormat.R8G8B8A8Unorm, Format.R16G16B16A16Float => TextureFormat.R16G16B16A16Float, Format.R16G16B16A16Unorm => TextureFormat.R16G16B16A16Unorm, Format.R16G16B16A16Snorm => TextureFormat.R16G16B16A16Snorm, diff --git a/Ryujinx.Graphics.OpenGL/FormatTable.cs b/Ryujinx.Graphics.OpenGL/FormatTable.cs index 4200ea7e..4261b495 100644 --- a/Ryujinx.Graphics.OpenGL/FormatTable.cs +++ b/Ryujinx.Graphics.OpenGL/FormatTable.cs @@ -6,11 +6,15 @@ namespace Ryujinx.Graphics.OpenGL { struct FormatTable { - private static FormatInfo[] _table; + private static FormatInfo[] Table; + private static SizedInternalFormat[] TableImage; static FormatTable() { - _table = new FormatInfo[Enum.GetNames(typeof(Format)).Length]; + int tableSize = Enum.GetNames(typeof(Format)).Length; + + Table = new FormatInfo[tableSize]; + TableImage = new SizedInternalFormat[tableSize]; Add(Format.R8Unorm, new FormatInfo(1, true, false, All.R8, PixelFormat.Red, PixelType.UnsignedByte)); Add(Format.R8Snorm, new FormatInfo(1, true, false, All.R8Snorm, PixelFormat.Red, PixelType.Byte)); @@ -168,16 +172,66 @@ namespace Ryujinx.Graphics.OpenGL Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte)); Add(Format.B8G8R8X8Srgb, new FormatInfo(4, false, false, All.Srgb8, PixelFormat.Rgba, PixelType.UnsignedByte)); Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte)); + + Add(Format.R8Unorm, SizedInternalFormat.R8); + Add(Format.R8Uint, SizedInternalFormat.R8ui); + Add(Format.R8Sint, SizedInternalFormat.R8i); + Add(Format.R16Float, SizedInternalFormat.R16f); + Add(Format.R16Unorm, SizedInternalFormat.R16); + Add(Format.R16Snorm, (SizedInternalFormat)All.R16Snorm); + Add(Format.R16Uint, SizedInternalFormat.R16ui); + Add(Format.R16Sint, SizedInternalFormat.R16i); + Add(Format.R32Float, SizedInternalFormat.R32f); + Add(Format.R32Uint, SizedInternalFormat.R32ui); + Add(Format.R32Sint, SizedInternalFormat.R32i); + Add(Format.R8G8Unorm, SizedInternalFormat.Rg8); + Add(Format.R8G8Snorm, (SizedInternalFormat)All.Rg8Snorm); + Add(Format.R8G8Uint, SizedInternalFormat.Rg8ui); + Add(Format.R8G8Sint, SizedInternalFormat.Rg8i); + Add(Format.R16G16Float, SizedInternalFormat.Rg16f); + Add(Format.R16G16Unorm, SizedInternalFormat.Rg16); + Add(Format.R16G16Snorm, (SizedInternalFormat)All.Rg16Snorm); + Add(Format.R16G16Uint, SizedInternalFormat.Rg16ui); + Add(Format.R16G16Sint, SizedInternalFormat.Rg16i); + Add(Format.R32G32Float, SizedInternalFormat.Rg32f); + Add(Format.R32G32Uint, SizedInternalFormat.Rg32ui); + Add(Format.R32G32Sint, SizedInternalFormat.Rg32i); + Add(Format.R8G8B8A8Unorm, SizedInternalFormat.Rgba8); + Add(Format.R8G8B8A8Snorm, (SizedInternalFormat)All.Rgba8Snorm); + Add(Format.R8G8B8A8Uint, SizedInternalFormat.Rgba8ui); + Add(Format.R8G8B8A8Sint, SizedInternalFormat.Rgba8i); + Add(Format.R16G16B16A16Float, SizedInternalFormat.Rgba16f); + Add(Format.R16G16B16A16Unorm, SizedInternalFormat.Rgba16); + Add(Format.R16G16B16A16Snorm, (SizedInternalFormat)All.Rgba16Snorm); + Add(Format.R16G16B16A16Uint, SizedInternalFormat.Rgba16ui); + Add(Format.R16G16B16A16Sint, SizedInternalFormat.Rgba16i); + Add(Format.R32G32B32A32Float, SizedInternalFormat.Rgba32f); + Add(Format.R32G32B32A32Uint, SizedInternalFormat.Rgba32ui); + Add(Format.R32G32B32A32Sint, SizedInternalFormat.Rgba32i); + Add(Format.R8G8B8A8Srgb, SizedInternalFormat.Rgba8); + Add(Format.R10G10B10A2Unorm, (SizedInternalFormat)All.Rgb10A2); + Add(Format.R10G10B10A2Uint, (SizedInternalFormat)All.Rgb10A2ui); + Add(Format.R11G11B10Float, (SizedInternalFormat)All.R11fG11fB10f); } private static void Add(Format format, FormatInfo info) { - _table[(int)format] = info; + Table[(int)format] = info; + } + + private static void Add(Format format, SizedInternalFormat sif) + { + TableImage[(int)format] = sif; } public static FormatInfo GetFormatInfo(Format format) { - return _table[(int)format]; + return Table[(int)format]; + } + + public static SizedInternalFormat GetImageFormat(Format format) + { + return TableImage[(int)format]; } } } diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 52d64df5..2650e9ee 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -693,7 +693,7 @@ namespace Ryujinx.Graphics.OpenGL SetFrontFace(_frontFace = frontFace.Convert()); } - public void SetImage(int index, ShaderStage stage, ITexture texture) + public void SetImage(int index, ShaderStage stage, ITexture texture, Format imageFormat) { int unit = _program.GetImageUnit(stage, index); @@ -701,11 +701,12 @@ namespace Ryujinx.Graphics.OpenGL { TextureBase texBase = (TextureBase)texture; - FormatInfo formatInfo = FormatTable.GetFormatInfo(texBase.Format); + SizedInternalFormat format = FormatTable.GetImageFormat(imageFormat); - SizedInternalFormat format = (SizedInternalFormat)formatInfo.PixelInternalFormat; - - GL.BindImageTexture(unit, texBase.Handle, 0, true, 0, TextureAccess.ReadWrite, format); + if (format != 0) + { + GL.BindImageTexture(unit, texBase.Handle, 0, true, 0, TextureAccess.ReadWrite, format); + } } } diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs index cd82aa02..08279839 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs @@ -345,14 +345,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl string indexedSamplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr); - desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Handle + index * 2); + desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Format, texOp.Handle + index * 2); context.TextureDescriptors.Add(desc); } } else { - desc = new TextureDescriptor(samplerName, texOp.Type, texOp.Handle); + desc = new TextureDescriptor(samplerName, texOp.Type, texOp.Format, texOp.Handle); context.TextureDescriptors.Add(desc); } @@ -371,10 +371,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl if (!images.TryAdd(imageName, texOp)) { - // Ensure that all texture operations share the same format. - // This avoid errors like mismatched formats. - texOp.Format = images[imageName].Format; - continue; } @@ -404,14 +400,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl string indexedSamplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr); - var desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Handle + index * 2); + var desc = new TextureDescriptor(indexedSamplerName, texOp.Type, texOp.Format, texOp.Handle + index * 2); context.TextureDescriptors.Add(desc); } } else { - var desc = new TextureDescriptor(imageName, texOp.Type, texOp.Handle); + var desc = new TextureDescriptor(imageName, texOp.Type, texOp.Format, texOp.Handle); context.ImageDescriptors.Add(desc); } diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs index 465356e6..459b60c4 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs @@ -260,7 +260,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl public static string GetImageName(ShaderStage stage, AstTextureOperation texOp, string indexExpr) { - string suffix = texOp.Handle.ToString("X"); + string suffix = texOp.Handle.ToString("X") + "_" + texOp.Format.ToGlslFormat(); if ((texOp.Type & SamplerType.Indexed) != 0) { diff --git a/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs b/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs index bb935ce7..a3fa3e3a 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs @@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr class AstTextureOperation : AstOperation { public SamplerType Type { get; } - public TextureFormat Format { get; set; } + public TextureFormat Format { get; } public TextureFlags Flags { get; } public int Handle { get; } diff --git a/Ryujinx.Graphics.Shader/TextureDescriptor.cs b/Ryujinx.Graphics.Shader/TextureDescriptor.cs index a9900fb8..7c2bd714 100644 --- a/Ryujinx.Graphics.Shader/TextureDescriptor.cs +++ b/Ryujinx.Graphics.Shader/TextureDescriptor.cs @@ -6,6 +6,8 @@ namespace Ryujinx.Graphics.Shader public SamplerType Type { get; } + public TextureFormat Format { get; } + public int HandleIndex { get; } public bool IsBindless { get; } @@ -15,10 +17,11 @@ namespace Ryujinx.Graphics.Shader public TextureUsageFlags Flags { get; set; } - public TextureDescriptor(string name, SamplerType type, int handleIndex) + public TextureDescriptor(string name, SamplerType type, TextureFormat format, int handleIndex) { Name = name; Type = type; + Format = format; HandleIndex = handleIndex; IsBindless = false; @@ -33,6 +36,7 @@ namespace Ryujinx.Graphics.Shader { Name = name; Type = type; + Format = TextureFormat.Unknown; HandleIndex = 0; IsBindless = true;