language feature: Extension Members: Graphics related, enums

This commit is contained in:
GreemDev 2025-07-02 02:04:47 -05:00
parent 99cbfc3822
commit 2075c1a543
24 changed files with 249 additions and 247 deletions

View file

@ -16,19 +16,18 @@ namespace Ryujinx.Graphics.GAL
public static class TargetExtensions public static class TargetExtensions
{ {
public static bool IsMultisample(this Target target) extension(Target target)
{ {
return target is Target.Texture2DMultisample or Target.Texture2DMultisampleArray; public bool IsMultisample => target is Target.Texture2DMultisample or Target.Texture2DMultisampleArray;
}
public static bool HasDepthOrLayers(this Target target) public bool HasDepthOrLayers =>
{ target is
return target is Target.Texture3D or Target.Texture3D or
Target.Texture1DArray or Target.Texture1DArray or
Target.Texture2DArray or Target.Texture2DArray or
Target.Texture2DMultisampleArray or Target.Texture2DMultisampleArray or
Target.Cubemap or Target.Cubemap or
Target.CubemapArray; Target.CubemapArray;
} }
} }
} }

View file

@ -1251,7 +1251,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewTargetCompatible(Info, info, ref caps)); result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewTargetCompatible(Info, info, ref caps));
bool bothMs = Info.Target.IsMultisample() && info.Target.IsMultisample(); bool bothMs = Info.Target.IsMultisample && info.Target.IsMultisample;
if (bothMs && (Info.SamplesInX != info.SamplesInX || Info.SamplesInY != info.SamplesInY)) if (bothMs && (Info.SamplesInX != info.SamplesInX || Info.SamplesInY != info.SamplesInY))
{ {
result = TextureViewCompatibility.Incompatible; result = TextureViewCompatibility.Incompatible;

View file

@ -388,7 +388,7 @@ namespace Ryujinx.Graphics.Gpu.Image
return stride == rhs.Stride ? TextureViewCompatibility.CopyOnly : TextureViewCompatibility.LayoutIncompatible; return stride == rhs.Stride ? TextureViewCompatibility.CopyOnly : TextureViewCompatibility.LayoutIncompatible;
} }
else if (lhs.Target.IsMultisample() != rhs.Target.IsMultisample() && alignedWidthMatches && lhsAlignedSize.Height == rhsAlignedSize.Height) else if (lhs.Target.IsMultisample != rhs.Target.IsMultisample && alignedWidthMatches && lhsAlignedSize.Height == rhsAlignedSize.Height)
{ {
// Copy between multisample and non-multisample textures with mismatching size is allowed, // Copy between multisample and non-multisample textures with mismatching size is allowed,
// as long aligned size matches. // as long aligned size matches.

View file

@ -139,7 +139,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_allOffsets = size.AllOffsets; _allOffsets = size.AllOffsets;
_sliceSizes = size.SliceSizes; _sliceSizes = size.SliceSizes;
if (Storage.Target.HasDepthOrLayers() && Storage.Info.GetSlices() > GranularLayerThreshold) if (Storage.Target.HasDepthOrLayers && Storage.Info.GetSlices() > GranularLayerThreshold)
{ {
_hasLayerViews = true; _hasLayerViews = true;
_hasMipViews = true; _hasMipViews = true;

View file

@ -116,13 +116,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
{ {
TextureView destinationView = (TextureView)destination; TextureView destinationView = (TextureView)destination;
bool srcIsMultisample = Target.IsMultisample(); bool srcIsMultisample = Target.IsMultisample;
bool dstIsMultisample = destinationView.Target.IsMultisample(); bool dstIsMultisample = destinationView.Target.IsMultisample;
if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil()) if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil())
{ {
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer); int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
CopyWithBlitForDepthMS(destinationView, 0, firstLayer, layers); CopyWithBlitForDepthMultisample(destinationView, 0, firstLayer, layers);
} }
else if (!dstIsMultisample && srcIsMultisample) else if (!dstIsMultisample && srcIsMultisample)
{ {
@ -172,12 +172,12 @@ namespace Ryujinx.Graphics.OpenGL.Image
{ {
TextureView destinationView = (TextureView)destination; TextureView destinationView = (TextureView)destination;
bool srcIsMultisample = Target.IsMultisample(); bool srcIsMultisample = Target.IsMultisample;
bool dstIsMultisample = destinationView.Target.IsMultisample(); bool dstIsMultisample = destinationView.Target.IsMultisample;
if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil()) if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil())
{ {
CopyWithBlitForDepthMS(destinationView, srcLayer, dstLayer, 1); CopyWithBlitForDepthMultisample(destinationView, srcLayer, dstLayer, 1);
} }
else if (!dstIsMultisample && srcIsMultisample) else if (!dstIsMultisample && srcIsMultisample)
{ {
@ -204,7 +204,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
} }
} }
private void CopyWithBlitForDepthMS(TextureView destinationView, int srcLayer, int dstLayer, int layers) private void CopyWithBlitForDepthMultisample(TextureView destinationView, int srcLayer, int dstLayer, int layers)
{ {
// This is currently used for multisample <-> non-multisample copies. // This is currently used for multisample <-> non-multisample copies.
// We can't do that with compute because it's not possible to write depth textures on compute. // We can't do that with compute because it's not possible to write depth textures on compute.
@ -216,9 +216,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
Extents2D srcRegion = new(0, 0, Width, Height); Extents2D srcRegion = new(0, 0, Width, Height);
Extents2D dstRegion = new(0, 0, destinationView.Width, destinationView.Height); Extents2D dstRegion = new(0, 0, destinationView.Width, destinationView.Height);
if (destinationView.Target.IsMultisample()) if (destinationView.Target.IsMultisample)
{ {
TextureView intermmediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast( TextureView intermediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
Info.Target, Info.Target,
Info.BlockWidth, Info.BlockWidth,
Info.BlockHeight, Info.BlockHeight,
@ -230,8 +230,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
1, 1,
1); 1);
_renderer.TextureCopy.Copy(this, intermmediate, srcRegion, dstRegion, false); _renderer.TextureCopy.Copy(this, intermediate, srcRegion, dstRegion, false);
_renderer.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1); _renderer.TextureCopy.Copy(intermediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
} }
else else
{ {
@ -242,7 +242,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
_ => Target, _ => Target,
}; };
TextureView intermmediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast( TextureView intermediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
target, target,
Info.BlockWidth, Info.BlockWidth,
Info.BlockHeight, Info.BlockHeight,
@ -254,8 +254,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
1, 1,
1); 1);
_renderer.TextureCopy.Copy(this, intermmediate, srcRegion, srcRegion, false); _renderer.TextureCopy.Copy(this, intermediate, srcRegion, srcRegion, false);
_renderer.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1); _renderer.TextureCopy.Copy(intermediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
} }
} }
@ -305,14 +305,12 @@ namespace Ryujinx.Graphics.OpenGL.Image
{ {
return PinnedSpan<byte>.UnsafeFromSpan(_renderer.PersistentBuffers.Default.GetTextureData(this, size, layer, level)); return PinnedSpan<byte>.UnsafeFromSpan(_renderer.PersistentBuffers.Default.GetTextureData(this, size, layer, level));
} }
else
{
nint target = _renderer.PersistentBuffers.Default.GetHostArray(size);
int offset = WriteTo2D(target, layer, level); nint target = _renderer.PersistentBuffers.Default.GetHostArray(size);
return new PinnedSpan<byte>((byte*)target.ToPointer() + offset, size); int offset = WriteTo2D(target, layer, level);
}
return new PinnedSpan<byte>((byte*)target.ToPointer() + offset, size);
} }
public void CopyTo(BufferRange range, int layer, int level, int stride) public void CopyTo(BufferRange range, int layer, int level, int stride)

View file

@ -19,20 +19,18 @@ namespace Ryujinx.Graphics.Shader
static class AttributeTypeExtensions static class AttributeTypeExtensions
{ {
public static AggregateType ToAggregateType(this AttributeType type) extension(AttributeType type)
{ {
return (type & ~AttributeType.AnyPacked) switch public AggregateType Aggregate =>
(type & ~AttributeType.AnyPacked) switch
{ {
AttributeType.Float => AggregateType.FP32, AttributeType.Float => AggregateType.FP32,
AttributeType.Sint => AggregateType.S32, AttributeType.Sint => AggregateType.S32,
AttributeType.Uint => AggregateType.U32, AttributeType.Uint => AggregateType.U32,
_ => throw new ArgumentException($"Invalid attribute type \"{type}\"."), _ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
}; };
}
public AggregateType AsAggregate(bool supportsScaledFormats) => (type & ~AttributeType.AnyPacked) switch
public static AggregateType ToAggregateType(this AttributeType type, bool supportsScaledFormats)
{
return (type & ~AttributeType.AnyPacked) switch
{ {
AttributeType.Float => AggregateType.FP32, AttributeType.Float => AggregateType.FP32,
AttributeType.Sint => AggregateType.S32, AttributeType.Sint => AggregateType.S32,

View file

@ -123,8 +123,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
tessCw = !tessCw; tessCw = !tessCw;
} }
string patchType = context.Definitions.TessPatchType.ToGlsl(); string patchType = context.Definitions.TessPatchType.Glsl;
string spacing = context.Definitions.TessSpacing.ToGlsl(); string spacing = context.Definitions.TessSpacing.Glsl;
string windingOrder = tessCw ? "cw" : "ccw"; string windingOrder = tessCw ? "cw" : "ccw";
context.AppendLine($"layout ({patchType}, {spacing}, {windingOrder}) in;"); context.AppendLine($"layout ({patchType}, {spacing}, {windingOrder}) in;");
@ -351,7 +351,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
arrayDecl = "[]"; arrayDecl = "[]";
} }
string samplerTypeName = definition.Separate ? definition.Type.ToGlslTextureType() : definition.Type.ToGlslSamplerType(); string samplerTypeName = definition.Separate ? definition.Type.GlslTextureTypeName : definition.Type.GlslSamplerTypeName;
string layout = string.Empty; string layout = string.Empty;
@ -379,7 +379,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
arrayDecl = "[]"; arrayDecl = "[]";
} }
string imageTypeName = definition.Type.ToGlslImageType(definition.Format.GetComponentType()); string imageTypeName = definition.Type.GetGlslImageTypeName(definition.Format.GetComponentType());
if (definition.Flags.HasFlag(TextureUsageFlags.ImageCoherent)) if (definition.Flags.HasFlag(TextureUsageFlags.ImageCoherent))
{ {

View file

@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
texCallBuilder.Append('('); texCallBuilder.Append('(');
texCallBuilder.Append(imageName); texCallBuilder.Append(imageName);
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount + (isArray ? 1 : 0); int pCount = coordsCount + (isArray ? 1 : 0);
@ -162,7 +162,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
AstTextureOperation texOp = (AstTextureOperation)operation; AstTextureOperation texOp = (AstTextureOperation)operation;
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int coordsIndex = 0; int coordsIndex = 0;
string samplerName = GetSamplerName(context, texOp, ref coordsIndex); string samplerName = GetSamplerName(context, texOp, ref coordsIndex);
@ -264,7 +264,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
texCall += "(" + samplerName; texCall += "(" + samplerName;
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount; int pCount = coordsCount;
@ -658,7 +658,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
samplerName = $"{samplerName}[{GetSourceExpr(context, texOp.GetSource(srcIndex++), AggregateType.S32)}]"; samplerName = $"{samplerName}[{GetSourceExpr(context, texOp.GetSource(srcIndex++), AggregateType.S32)}]";
} }
name = $"{texOp.Type.ToGlslSamplerType()}({name}, {samplerName})"; name = $"{texOp.Type.GlslSamplerTypeName}({name}, {samplerName})";
} }
return name; return name;

View file

@ -385,7 +385,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static void DeclarePerVertexBlock(CodeGenContext context) private static void DeclarePerVertexBlock(CodeGenContext context)
{ {
if (context.Definitions.Stage.IsVtg()) if (context.Definitions.Stage.IsVtg)
{ {
if (context.Definitions.Stage != ShaderStage.Vertex) if (context.Definitions.Stage != ShaderStage.Vertex)
{ {

View file

@ -615,7 +615,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
image = context.AccessChain(imagePointerType, image, textureIndex); image = context.AccessChain(imagePointerType, image, textureIndex);
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount + (isArray ? 1 : 0); int pCount = coordsCount + (isArray ? 1 : 0);
@ -693,7 +693,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
image = context.Load(declaration.ImageType, image); image = context.Load(declaration.ImageType, image);
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount + (isArray ? 1 : 0); int pCount = coordsCount + (isArray ? 1 : 0);
@ -750,7 +750,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
image = context.Load(declaration.ImageType, image); image = context.Load(declaration.ImageType, image);
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount + (isArray ? 1 : 0); int pCount = coordsCount + (isArray ? 1 : 0);
@ -840,7 +840,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()]; SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()];
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex); SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
int pCount = texOp.Type.GetDimensions(); int pCount = texOp.Type.Dimensions;
SpvInstruction pCoords; SpvInstruction pCoords;
@ -1164,7 +1164,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()]; SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()];
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex); SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount; int pCount = coordsCount;
@ -1463,7 +1463,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SamplerType type = context.SamplersTypes[texOp.GetTextureSetAndBinding()]; SamplerType type = context.SamplersTypes[texOp.GetTextureSetAndBinding()];
bool hasLod = !type.HasFlag(SamplerType.Multisample) && type != SamplerType.TextureBuffer; bool hasLod = !type.HasFlag(SamplerType.Multisample) && type != SamplerType.TextureBuffer;
int dimensions = (type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : type.GetDimensions(); int dimensions = (type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : type.Dimensions;
if (type.HasFlag(SamplerType.Array)) if (type.HasFlag(SamplerType.Array))
{ {
@ -1486,7 +1486,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (dimensions != 1) if (dimensions != 1)
{ {
result = context.CompositeExtract(context.TypeS32(), result, (SpvLiteralInteger)texOp.Index); result = context.CompositeExtract(context.TypeS32(), result, texOp.Index);
} }
return new OperationResult(AggregateType.S32, result); return new OperationResult(AggregateType.S32, result);

View file

@ -457,7 +457,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
case AttributeConsts.ClipDistance5: case AttributeConsts.ClipDistance5:
case AttributeConsts.ClipDistance6: case AttributeConsts.ClipDistance6:
case AttributeConsts.ClipDistance7: case AttributeConsts.ClipDistance7:
if (definitions.Stage.IsVtg()) if (definitions.Stage.IsVtg)
{ {
context.SetClipDistanceWritten((attr - AttributeConsts.ClipDistance0) / 4); context.SetClipDistanceWritten((attr - AttributeConsts.ClipDistance0) / 4);
} }

View file

@ -228,7 +228,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
sourcesList.Add(context.Copy(GetSrcReg(context, srcC))); sourcesList.Add(context.Copy(GetSrcReg(context, srcC)));
} }
int coordsCount = type.GetDimensions(); int coordsCount = type.Dimensions;
for (int index = 0; index < coordsCount; index++) for (int index = 0; index < coordsCount; index++)
{ {
@ -335,7 +335,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr))); sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr)));
} }
int coordsCount = type.GetDimensions(); int coordsCount = type.Dimensions;
for (int index = 0; index < coordsCount; index++) for (int index = 0; index < coordsCount; index++)
{ {
@ -507,7 +507,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
sourcesList.Add(context.Copy(GetSrcReg(context, srcC))); sourcesList.Add(context.Copy(GetSrcReg(context, srcC)));
} }
int coordsCount = type.GetDimensions(); int coordsCount = type.Dimensions;
for (int index = 0; index < coordsCount; index++) for (int index = 0; index < coordsCount; index++)
{ {
@ -612,7 +612,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr))); sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr)));
} }
int coordsCount = type.GetDimensions(); int coordsCount = type.Dimensions;
for (int index = 0; index < coordsCount; index++) for (int index = 0; index < coordsCount; index++)
{ {

View file

@ -227,7 +227,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
} }
int coordsCount = type.GetDimensions(); int coordsCount = type.Dimensions;
for (int index = 0; index < coordsCount; index++) for (int index = 0; index < coordsCount; index++)
{ {
@ -558,7 +558,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if ((flags & TextureFlags.Offset) != 0) if ((flags & TextureFlags.Offset) != 0)
{ {
AddTextureOffset(type.GetDimensions(), 4, 4); AddTextureOffset(type.Dimensions, 4, 4);
} }
} }
else if (texsType == TexsType.Tld4s) else if (texsType == TexsType.Tld4s)
@ -583,7 +583,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (tld4sOp.Aoffi) if (tld4sOp.Aoffi)
{ {
AddTextureOffset(type.GetDimensions(), 8, 6); AddTextureOffset(type.Dimensions, 8, 6);
flags |= TextureFlags.Offset; flags |= TextureFlags.Offset;
} }
@ -714,7 +714,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
flags |= TextureFlags.Bindless; flags |= TextureFlags.Bindless;
} }
int coordsCount = type.GetDimensions(); int coordsCount = type.Dimensions;
for (int index = 0; index < coordsCount; index++) for (int index = 0; index < coordsCount; index++)
{ {
@ -847,7 +847,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
SamplerType type = ConvertSamplerType(dimensions); SamplerType type = ConvertSamplerType(dimensions);
int coordsCount = type.GetDimensions(); int coordsCount = type.Dimensions;
bool isArray = bool isArray =
dimensions is TexDim.Array1d or dimensions is TexDim.Array1d or
@ -942,26 +942,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
return; return;
} }
Operand Ra()
{
if (srcA > RegisterConsts.RegisterZeroIndex)
{
return Const(0);
}
return context.Copy(Register(srcA++, RegisterType.Gpr));
}
Operand Rb()
{
if (srcB > RegisterConsts.RegisterZeroIndex)
{
return Const(0);
}
return context.Copy(Register(srcB++, RegisterType.Gpr));
}
TextureFlags flags = TextureFlags.Derivatives; TextureFlags flags = TextureFlags.Derivatives;
List<Operand> sourcesList = []; List<Operand> sourcesList = [];
@ -975,7 +955,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
SamplerType type = ConvertSamplerType(dimensions); SamplerType type = ConvertSamplerType(dimensions);
int coordsCount = type.GetDimensions(); int coordsCount = type.Dimensions;
for (int index = 0; index < coordsCount; index++) for (int index = 0; index < coordsCount; index++)
{ {
@ -1051,6 +1031,28 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
EmitTextureSample(context, type, flags, imm, componentMask, dests, sources); EmitTextureSample(context, type, flags, imm, componentMask, dests, sources);
return;
Operand Ra()
{
if (srcA > RegisterConsts.RegisterZeroIndex)
{
return Const(0);
}
return context.Copy(Register(srcA++, RegisterType.Gpr));
}
Operand Rb()
{
if (srcB > RegisterConsts.RegisterZeroIndex)
{
return Const(0);
}
return context.Copy(Register(srcB++, RegisterType.Gpr));
}
} }
private static void EmitTxq( private static void EmitTxq(

View file

@ -22,9 +22,9 @@ namespace Ryujinx.Graphics.Shader
static class SamplerTypeExtensions static class SamplerTypeExtensions
{ {
public static int GetDimensions(this SamplerType type) extension(SamplerType type)
{ {
return (type & SamplerType.Mask) switch public int Dimensions => (type & SamplerType.Mask) switch
{ {
SamplerType.Texture1D => 1, SamplerType.Texture1D => 1,
SamplerType.TextureBuffer => 1, SamplerType.TextureBuffer => 1,
@ -33,127 +33,136 @@ namespace Ryujinx.Graphics.Shader
SamplerType.TextureCube => 3, SamplerType.TextureCube => 3,
_ => throw new ArgumentException($"Invalid sampler type \"{type}\"."), _ => throw new ArgumentException($"Invalid sampler type \"{type}\"."),
}; };
}
public static string ToShortSamplerType(this SamplerType type) public string ShortTypeName
{
string typeName = (type & SamplerType.Mask) switch
{ {
SamplerType.Texture1D => "1d", get
SamplerType.TextureBuffer => "b", {
SamplerType.Texture2D => "2d", string typeName = (type & SamplerType.Mask) switch
SamplerType.Texture3D => "3d", {
SamplerType.TextureCube => "cube", SamplerType.Texture1D => "1d",
_ => throw new ArgumentException($"Invalid sampler type \"{type}\"."), SamplerType.TextureBuffer => "b",
}; SamplerType.Texture2D => "2d",
SamplerType.Texture3D => "3d",
SamplerType.TextureCube => "cube",
_ => throw new ArgumentException($"Invalid sampler type \"{type}\"."),
};
if ((type & SamplerType.Multisample) != 0) if ((type & SamplerType.Multisample) != 0)
{ {
typeName += "ms"; typeName += "ms";
}
if ((type & SamplerType.Array) != 0)
{
typeName += "a";
}
if ((type & SamplerType.Shadow) != 0)
{
typeName += "s";
}
return typeName;
}
} }
if ((type & SamplerType.Array) != 0) public string GlslSamplerTypeName
{ {
typeName += "a"; get
{
string typeName = (type & SamplerType.Mask) switch
{
SamplerType.None => "sampler",
SamplerType.Texture1D => "sampler1D",
SamplerType.TextureBuffer => "samplerBuffer",
SamplerType.Texture2D => "sampler2D",
SamplerType.Texture3D => "sampler3D",
SamplerType.TextureCube => "samplerCube",
_ => throw new ArgumentException($"Invalid sampler type \"{type}\"."),
};
if ((type & SamplerType.Multisample) != 0)
{
typeName += "MS";
}
if ((type & SamplerType.Array) != 0)
{
typeName += "Array";
}
if ((type & SamplerType.Shadow) != 0)
{
typeName += "Shadow";
}
return typeName;
}
} }
if ((type & SamplerType.Shadow) != 0) public string GlslTextureTypeName
{ {
typeName += "s"; get
{
string typeName = (type & SamplerType.Mask) switch
{
SamplerType.Texture1D => "texture1D",
SamplerType.TextureBuffer => "textureBuffer",
SamplerType.Texture2D => "texture2D",
SamplerType.Texture3D => "texture3D",
SamplerType.TextureCube => "textureCube",
_ => throw new ArgumentException($"Invalid texture type \"{type}\"."),
};
if ((type & SamplerType.Multisample) != 0)
{
typeName += "MS";
}
if ((type & SamplerType.Array) != 0)
{
typeName += "Array";
}
return typeName;
}
} }
return typeName; public string GetGlslImageTypeName(AggregateType componentType)
}
public static string ToGlslSamplerType(this SamplerType type)
{
string typeName = (type & SamplerType.Mask) switch
{ {
SamplerType.None => "sampler", string typeName = (type & SamplerType.Mask) switch
SamplerType.Texture1D => "sampler1D", {
SamplerType.TextureBuffer => "samplerBuffer", SamplerType.Texture1D => "image1D",
SamplerType.Texture2D => "sampler2D", SamplerType.TextureBuffer => "imageBuffer",
SamplerType.Texture3D => "sampler3D", SamplerType.Texture2D => "image2D",
SamplerType.TextureCube => "samplerCube", SamplerType.Texture3D => "image3D",
_ => throw new ArgumentException($"Invalid sampler type \"{type}\"."), SamplerType.TextureCube => "imageCube",
}; _ => throw new ArgumentException($"Invalid sampler type \"{type}\"."),
};
if ((type & SamplerType.Multisample) != 0) if ((type & SamplerType.Multisample) != 0)
{ {
typeName += "MS"; typeName += "MS";
}
if ((type & SamplerType.Array) != 0)
{
typeName += "Array";
}
switch (componentType)
{
case AggregateType.U32:
typeName = 'u' + typeName;
break;
case AggregateType.S32:
typeName = 'i' + typeName;
break;
}
return typeName;
} }
if ((type & SamplerType.Array) != 0)
{
typeName += "Array";
}
if ((type & SamplerType.Shadow) != 0)
{
typeName += "Shadow";
}
return typeName;
}
public static string ToGlslTextureType(this SamplerType type)
{
string typeName = (type & SamplerType.Mask) switch
{
SamplerType.Texture1D => "texture1D",
SamplerType.TextureBuffer => "textureBuffer",
SamplerType.Texture2D => "texture2D",
SamplerType.Texture3D => "texture3D",
SamplerType.TextureCube => "textureCube",
_ => throw new ArgumentException($"Invalid texture type \"{type}\"."),
};
if ((type & SamplerType.Multisample) != 0)
{
typeName += "MS";
}
if ((type & SamplerType.Array) != 0)
{
typeName += "Array";
}
return typeName;
}
public static string ToGlslImageType(this SamplerType type, AggregateType componentType)
{
string typeName = (type & SamplerType.Mask) switch
{
SamplerType.Texture1D => "image1D",
SamplerType.TextureBuffer => "imageBuffer",
SamplerType.Texture2D => "image2D",
SamplerType.Texture3D => "image3D",
SamplerType.TextureCube => "imageCube",
_ => throw new ArgumentException($"Invalid sampler type \"{type}\"."),
};
if ((type & SamplerType.Multisample) != 0)
{
typeName += "MS";
}
if ((type & SamplerType.Array) != 0)
{
typeName += "Array";
}
switch (componentType)
{
case AggregateType.U32:
typeName = 'u' + typeName;
break;
case AggregateType.S32:
typeName = 'i' + typeName;
break;
}
return typeName;
} }
} }
} }

View file

@ -14,27 +14,23 @@ namespace Ryujinx.Graphics.Shader
public static class ShaderStageExtensions public static class ShaderStageExtensions
{ {
/// <summary> extension(ShaderStage shaderStage)
/// Checks if the shader stage supports render scale.
/// </summary>
/// <param name="stage">Shader stage</param>
/// <returns>True if the shader stage supports render scale, false otherwise</returns>
public static bool SupportsRenderScale(this ShaderStage stage)
{ {
return stage is ShaderStage.Vertex or ShaderStage.Fragment or ShaderStage.Compute; /// <summary>
} /// Checks if the shader stage supports render scale.
/// </summary>
/// <summary> public bool SupportsRenderScale =>
/// Checks if the shader stage is vertex, tessellation or geometry. shaderStage is ShaderStage.Vertex or ShaderStage.Fragment or ShaderStage.Compute;
/// </summary>
/// <param name="stage">Shader stage</param> /// <summary>
/// <returns>True if the shader stage is vertex, tessellation or geometry, false otherwise</returns> /// Checks if the shader stage is vertex, tessellation or geometry.
public static bool IsVtg(this ShaderStage stage) /// </summary>
{ public bool IsVtg =>
return stage is ShaderStage.Vertex or shaderStage is ShaderStage.Vertex or
ShaderStage.TessellationControl or ShaderStage.TessellationControl or
ShaderStage.TessellationEvaluation or ShaderStage.TessellationEvaluation or
ShaderStage.Geometry; ShaderStage.Geometry;
} }
} }
} }

View file

@ -9,9 +9,9 @@ namespace Ryujinx.Graphics.Shader
static class TessPatchTypeExtensions static class TessPatchTypeExtensions
{ {
public static string ToGlsl(this TessPatchType type) extension(TessPatchType patchType)
{ {
return type switch public string Glsl => patchType switch
{ {
TessPatchType.Isolines => "isolines", TessPatchType.Isolines => "isolines",
TessPatchType.Quads => "quads", TessPatchType.Quads => "quads",

View file

@ -9,9 +9,9 @@ namespace Ryujinx.Graphics.Shader
static class TessSpacingExtensions static class TessSpacingExtensions
{ {
public static string ToGlsl(this TessSpacing spacing) extension(TessSpacing spacing)
{ {
return spacing switch public string Glsl => spacing switch
{ {
TessSpacing.FractionalEventSpacing => "fractional_even_spacing", TessSpacing.FractionalEventSpacing => "fractional_even_spacing",
TessSpacing.FractionalOddSpacing => "fractional_odd_spacing", TessSpacing.FractionalOddSpacing => "fractional_odd_spacing",

View file

@ -39,8 +39,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// Set any destination variables to zero. // Set any destination variables to zero.
string typeName = texOp.Inst.IsImage() string typeName = texOp.Inst.IsImage()
? texOp.Type.ToGlslImageType(texOp.Format.GetComponentType()) ? texOp.Type.GetGlslImageTypeName(texOp.Format.GetComponentType())
: texOp.Type.ToGlslTextureType(); : texOp.Type.GlslTextureTypeName;
gpuAccessor.Log($"Failed to find handle source for bindless access of type \"{typeName}\"."); gpuAccessor.Log($"Failed to find handle source for bindless access of type \"{typeName}\".");

View file

@ -273,7 +273,7 @@ namespace Ryujinx.Graphics.Shader.Translation
bool coherent, bool coherent,
bool separate) bool separate)
{ {
var dimensions = type == SamplerType.None ? 0 : type.GetDimensions(); var dimensions = type == SamplerType.None ? 0 : type.Dimensions;
var dict = isImage ? _usedImages : _usedTextures; var dict = isImage ? _usedImages : _usedTextures;
var usageFlags = TextureUsageFlags.None; var usageFlags = TextureUsageFlags.None;
@ -282,7 +282,7 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
usageFlags |= TextureUsageFlags.NeedsScaleValue; usageFlags |= TextureUsageFlags.NeedsScaleValue;
var canScale = _stage.SupportsRenderScale() && arrayLength == 1 && !write && dimensions == 2; var canScale = _stage.SupportsRenderScale && arrayLength == 1 && !write && dimensions == 2;
if (!canScale) if (!canScale)
{ {
@ -355,7 +355,7 @@ namespace Ryujinx.Graphics.Shader.Translation
if (arrayLength != 1 && type != SamplerType.None) if (arrayLength != 1 && type != SamplerType.None)
{ {
prefix += type.ToShortSamplerType(); prefix += type.ShortTypeName;
} }
if (isImage) if (isImage)
@ -433,8 +433,8 @@ namespace Ryujinx.Graphics.Shader.Translation
{ {
selectedMeta.UsageFlags |= TextureUsageFlags.NeedsScaleValue; selectedMeta.UsageFlags |= TextureUsageFlags.NeedsScaleValue;
var dimensions = type.GetDimensions(); var dimensions = type.Dimensions;
var canScale = _stage.SupportsRenderScale() && selectedInfo.ArrayLength == 1 && dimensions == 2; var canScale = _stage.SupportsRenderScale && selectedInfo.ArrayLength == 1 && dimensions == 2;
if (!canScale) if (!canScale)
{ {

View file

@ -293,7 +293,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public AggregateType GetFragmentOutputColorType(int location) public AggregateType GetFragmentOutputColorType(int location)
{ {
return AggregateType.Vector4 | _graphicsState.FragmentOutputTypes[location].ToAggregateType(); return AggregateType.Vector4 | _graphicsState.FragmentOutputTypes[location].Aggregate;
} }
public AggregateType GetUserDefinedType(int location, bool isOutput) public AggregateType GetUserDefinedType(int location, bool isOutput)
@ -307,7 +307,7 @@ namespace Ryujinx.Graphics.Shader.Translation
if (Stage == ShaderStage.Vertex && !isOutput) if (Stage == ShaderStage.Vertex && !isOutput)
{ {
type |= _graphicsState.AttributeTypes[location].ToAggregateType(SupportsScaledVertexFormats); type |= _graphicsState.AttributeTypes[location].AsAggregate(SupportsScaledVertexFormats);
} }
else else
{ {

View file

@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
(intCoords || isImage) && (intCoords || isImage) &&
!isBindless && !isBindless &&
!isIndexed && !isIndexed &&
stage.SupportsRenderScale() && stage.SupportsRenderScale &&
TypeSupportsScale(texOp.Type)) TypeSupportsScale(texOp.Type))
{ {
int functionId = hfm.GetOrCreateFunctionId(HelperFunctionName.TexelFetchScale); int functionId = hfm.GetOrCreateFunctionId(HelperFunctionName.TexelFetchScale);
@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
? resourceManager.GetTextureDescriptors(includeArrays: false).Length + resourceManager.FindImageDescriptorIndex(texOp.Binding) ? resourceManager.GetTextureDescriptors(includeArrays: false).Length + resourceManager.FindImageDescriptorIndex(texOp.Binding)
: resourceManager.FindTextureDescriptorIndex(texOp.Binding); : resourceManager.FindTextureDescriptorIndex(texOp.Binding);
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int coordsIndex = isBindless ? 1 : 0; int coordsIndex = isBindless ? 1 : 0;
for (int index = 0; index < coordsCount; index++) for (int index = 0; index < coordsCount; index++)
@ -103,7 +103,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
texOp.Index < 2 && texOp.Index < 2 &&
!isBindless && !isBindless &&
!isIndexed && !isIndexed &&
stage.SupportsRenderScale() && stage.SupportsRenderScale &&
TypeSupportsScale(texOp.Type)) TypeSupportsScale(texOp.Type))
{ {
int functionId = hfm.GetOrCreateFunctionId(HelperFunctionName.TextureSizeUnscale); int functionId = hfm.GetOrCreateFunctionId(HelperFunctionName.TextureSizeUnscale);
@ -168,7 +168,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
return node; return node;
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int normCoordsCount = (texOp.Type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : coordsCount; int normCoordsCount = (texOp.Type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : coordsCount;
@ -226,7 +226,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
bool isIndexed = resourceManager.IsArrayOfTexturesOrImages(texOp.Binding, isImage: false); bool isIndexed = resourceManager.IsArrayOfTexturesOrImages(texOp.Binding, isImage: false);
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int coordsIndex = isBindless || isIndexed ? 1 : 0; int coordsIndex = isBindless || isIndexed ? 1 : 0;
int normCoordsCount = (texOp.Type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : coordsCount; int normCoordsCount = (texOp.Type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : coordsCount;
@ -315,7 +315,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0; bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0;
bool isShadow = (texOp.Type & SamplerType.Shadow) != 0; bool isShadow = (texOp.Type & SamplerType.Shadow) != 0;
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int offsetsCount; int offsetsCount;

View file

@ -407,10 +407,10 @@ namespace Ryujinx.Graphics.Vulkan
if (dstIsDepthOrStencil) if (dstIsDepthOrStencil)
{ {
_pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit); _pipeline.SetProgram(src.Info.Target.IsMultisample ? _programDepthBlitMs : _programDepthBlit);
_pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always)); _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always));
} }
else if (src.Info.Target.IsMultisample()) else if (src.Info.Target.IsMultisample)
{ {
_pipeline.SetProgram(_programColorBlitMs); _pipeline.SetProgram(_programColorBlitMs);
} }
@ -567,12 +567,12 @@ namespace Ryujinx.Graphics.Vulkan
if (isDepth) if (isDepth)
{ {
_pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit); _pipeline.SetProgram(src.Info.Target.IsMultisample ? _programDepthBlitMs : _programDepthBlit);
_pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always)); _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, CompareOp.Always));
} }
else else
{ {
_pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programStencilBlitMs : _programStencilBlit); _pipeline.SetProgram(src.Info.Target.IsMultisample ? _programStencilBlitMs : _programStencilBlit);
_pipeline.SetStencilTest(CreateStencilTestDescriptor(true)); _pipeline.SetStencilTest(CreateStencilTestDescriptor(true));
} }

View file

@ -77,7 +77,7 @@ namespace Ryujinx.Graphics.Vulkan
_device = device; _device = device;
_info = info; _info = info;
bool isMsImageStorageSupported = gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample(); bool isMsImageStorageSupported = gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample;
VkFormat format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format, isMsImageStorageSupported); VkFormat format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format, isMsImageStorageSupported);
uint levels = (uint)info.Levels; uint levels = (uint)info.Levels;

View file

@ -61,7 +61,7 @@ namespace Ryujinx.Graphics.Vulkan
gd.Textures.Add(this); gd.Textures.Add(this);
bool isMsImageStorageSupported = gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample(); bool isMsImageStorageSupported = gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample;
VkFormat format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format, isMsImageStorageSupported); VkFormat format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format, isMsImageStorageSupported);
ImageUsageFlags usage = TextureStorage.GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, false); ImageUsageFlags usage = TextureStorage.GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, false);
@ -128,7 +128,7 @@ namespace Ryujinx.Graphics.Vulkan
ImageUsageFlags shaderUsage = ImageUsageFlags.SampledBit; ImageUsageFlags shaderUsage = ImageUsageFlags.SampledBit;
if (info.Format.IsImageCompatible() && (_gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample())) if (info.Format.IsImageCompatible() && (_gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample))
{ {
shaderUsage |= ImageUsageFlags.StorageBit; shaderUsage |= ImageUsageFlags.StorageBit;
} }
@ -225,12 +225,12 @@ namespace Ryujinx.Graphics.Vulkan
Image srcImage = src.GetImage().Get(cbs).Value; Image srcImage = src.GetImage().Get(cbs).Value;
Image dstImage = dst.GetImage().Get(cbs).Value; Image dstImage = dst.GetImage().Get(cbs).Value;
if (!dst.Info.Target.IsMultisample() && Info.Target.IsMultisample()) if (!dst.Info.Target.IsMultisample && Info.Target.IsMultisample)
{ {
int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer); int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer);
_gd.HelperShader.CopyMSToNonMS(_gd, cbs, src, dst, 0, firstLayer, layers); _gd.HelperShader.CopyMSToNonMS(_gd, cbs, src, dst, 0, firstLayer, layers);
} }
else if (dst.Info.Target.IsMultisample() && !Info.Target.IsMultisample()) else if (dst.Info.Target.IsMultisample && !Info.Target.IsMultisample)
{ {
int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer); int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer);
_gd.HelperShader.CopyNonMSToMS(_gd, cbs, src, dst, 0, firstLayer, layers); _gd.HelperShader.CopyNonMSToMS(_gd, cbs, src, dst, 0, firstLayer, layers);
@ -285,11 +285,11 @@ namespace Ryujinx.Graphics.Vulkan
Image srcImage = src.GetImage().Get(cbs).Value; Image srcImage = src.GetImage().Get(cbs).Value;
Image dstImage = dst.GetImage().Get(cbs).Value; Image dstImage = dst.GetImage().Get(cbs).Value;
if (!dst.Info.Target.IsMultisample() && Info.Target.IsMultisample()) if (!dst.Info.Target.IsMultisample && Info.Target.IsMultisample)
{ {
_gd.HelperShader.CopyMSToNonMS(_gd, cbs, src, dst, srcLayer, dstLayer, 1); _gd.HelperShader.CopyMSToNonMS(_gd, cbs, src, dst, srcLayer, dstLayer, 1);
} }
else if (dst.Info.Target.IsMultisample() && !Info.Target.IsMultisample()) else if (dst.Info.Target.IsMultisample && !Info.Target.IsMultisample)
{ {
_gd.HelperShader.CopyNonMSToMS(_gd, cbs, src, dst, srcLayer, dstLayer, 1); _gd.HelperShader.CopyNonMSToMS(_gd, cbs, src, dst, srcLayer, dstLayer, 1);
} }