mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-01-12 21:59:12 +00:00
Work around unsized array MoltenVK bug, disable bindless if not supported
This commit is contained in:
parent
764849b05e
commit
deb2c9a981
10 changed files with 87 additions and 27 deletions
|
@ -8,6 +8,7 @@ namespace Ryujinx.Graphics.GAL
|
|||
public readonly string VendorName;
|
||||
|
||||
public readonly bool HasFrontFacingBug;
|
||||
public readonly bool HasUnsizedDescriptorArrayBug;
|
||||
public readonly bool HasVectorIndexingBug;
|
||||
public readonly bool NeedsFragmentOutputSpecialization;
|
||||
public readonly bool ReduceShaderPrecision;
|
||||
|
@ -24,6 +25,7 @@ namespace Ryujinx.Graphics.GAL
|
|||
public readonly bool SupportsScaledVertexFormats;
|
||||
public readonly bool SupportsSnormBufferTextureFormat;
|
||||
public readonly bool Supports5BitComponentFormat;
|
||||
public readonly bool SupportsBindlessTextures;
|
||||
public readonly bool SupportsBlendEquationAdvanced;
|
||||
public readonly bool SupportsFragmentShaderInterlock;
|
||||
public readonly bool SupportsFragmentShaderOrderingIntel;
|
||||
|
@ -64,6 +66,7 @@ namespace Ryujinx.Graphics.GAL
|
|||
TargetApi api,
|
||||
string vendorName,
|
||||
bool hasFrontFacingBug,
|
||||
bool hasUnsizedDescriptorArrayBug,
|
||||
bool hasVectorIndexingBug,
|
||||
bool needsFragmentOutputSpecialization,
|
||||
bool reduceShaderPrecision,
|
||||
|
@ -79,6 +82,7 @@ namespace Ryujinx.Graphics.GAL
|
|||
bool supportsScaledVertexFormats,
|
||||
bool supportsSnormBufferTextureFormat,
|
||||
bool supports5BitComponentFormat,
|
||||
bool supportsBindlessTextures,
|
||||
bool supportsBlendEquationAdvanced,
|
||||
bool supportsFragmentShaderInterlock,
|
||||
bool supportsFragmentShaderOrderingIntel,
|
||||
|
@ -115,6 +119,7 @@ namespace Ryujinx.Graphics.GAL
|
|||
Api = api;
|
||||
VendorName = vendorName;
|
||||
HasFrontFacingBug = hasFrontFacingBug;
|
||||
HasUnsizedDescriptorArrayBug = hasUnsizedDescriptorArrayBug;
|
||||
HasVectorIndexingBug = hasVectorIndexingBug;
|
||||
NeedsFragmentOutputSpecialization = needsFragmentOutputSpecialization;
|
||||
ReduceShaderPrecision = reduceShaderPrecision;
|
||||
|
@ -130,6 +135,7 @@ namespace Ryujinx.Graphics.GAL
|
|||
SupportsScaledVertexFormats = supportsScaledVertexFormats;
|
||||
SupportsSnormBufferTextureFormat = supportsSnormBufferTextureFormat;
|
||||
Supports5BitComponentFormat = supports5BitComponentFormat;
|
||||
SupportsBindlessTextures = supportsBindlessTextures;
|
||||
SupportsBlendEquationAdvanced = supportsBlendEquationAdvanced;
|
||||
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
|
||||
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
|
||||
|
|
|
@ -157,6 +157,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
public bool QueryHostHasFrontFacingBug() => _context.Capabilities.HasFrontFacingBug;
|
||||
|
||||
public bool QueryHostHasUnsizedDescriptorArrayBug() => _context.Capabilities.HasUnsizedDescriptorArrayBug;
|
||||
|
||||
public bool QueryHostHasVectorIndexingBug() => _context.Capabilities.HasVectorIndexingBug;
|
||||
|
||||
public int QueryHostStorageBufferOffsetAlignment() => _context.Capabilities.StorageBufferOffsetAlignment;
|
||||
|
@ -165,6 +167,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
public bool QueryHostSupportsBgraFormat() => _context.Capabilities.SupportsBgraFormat;
|
||||
|
||||
public bool QueryHostSupportsBindlessTextures() => _context.Capabilities.SupportsBindlessTextures;
|
||||
|
||||
public bool QueryHostSupportsFragmentShaderInterlock() => _context.Capabilities.SupportsFragmentShaderInterlock;
|
||||
|
||||
public bool QueryHostSupportsFragmentShaderOrderingIntel() => _context.Capabilities.SupportsFragmentShaderOrderingIntel;
|
||||
|
|
|
@ -134,6 +134,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
api: TargetApi.OpenGL,
|
||||
vendorName: GpuVendor,
|
||||
hasFrontFacingBug: intelWindows,
|
||||
hasUnsizedDescriptorArrayBug: false,
|
||||
hasVectorIndexingBug: amdWindows,
|
||||
needsFragmentOutputSpecialization: false,
|
||||
reduceShaderPrecision: false,
|
||||
|
@ -148,6 +149,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
supportsR4G4B4A4Format: true,
|
||||
supportsSnormBufferTextureFormat: false,
|
||||
supports5BitComponentFormat: true,
|
||||
supportsBindlessTextures: HwCapabilities.SupportsArbBindlessTexture,
|
||||
supportsBlendEquationAdvanced: HwCapabilities.SupportsBlendEquationAdvanced,
|
||||
supportsFragmentShaderInterlock: HwCapabilities.SupportsFragmentShaderInterlock,
|
||||
supportsFragmentShaderOrderingIntel: HwCapabilities.SupportsFragmentShaderOrdering,
|
||||
|
|
|
@ -190,7 +190,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
if (sampler.ArraySize == 0)
|
||||
{
|
||||
var sampledImageArrayType = context.TypeRuntimeArray(imageTypeForSampler);
|
||||
var sampledImageArrayType = context.HostCapabilities.HasUnsizedDescriptorArrayBug
|
||||
? context.TypeArray(imageTypeForSampler, context.Constant(context.TypeU32(), 1))
|
||||
: context.TypeRuntimeArray(imageTypeForSampler);
|
||||
sampledImageArrayPointerType = context.TypePointer(StorageClass.UniformConstant, sampledImageArrayType);
|
||||
}
|
||||
else if (sampler.ArraySize != 1)
|
||||
|
@ -241,7 +243,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
if (image.ArraySize == 0)
|
||||
{
|
||||
var imageArrayType = context.TypeRuntimeArray(imageType);
|
||||
var imageArrayType = context.HostCapabilities.HasUnsizedDescriptorArrayBug
|
||||
? context.TypeArray(imageType, context.Constant(context.TypeU32(), 1))
|
||||
: context.TypeRuntimeArray(imageType);
|
||||
imageArrayPointerType = context.TypePointer(StorageClass.UniformConstant, imageArrayType);
|
||||
}
|
||||
else if (image.ArraySize != 1)
|
||||
|
|
|
@ -195,6 +195,15 @@ namespace Ryujinx.Graphics.Shader
|
|||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries host about the presence of the unsized descriptor array bug.
|
||||
/// </summary>
|
||||
/// <returns>True if the bug is present on the host device used, false otherwise</returns>
|
||||
bool QueryHostHasUnsizedDescriptorArrayBug()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries host about the presence of the vector indexing bug.
|
||||
/// </summary>
|
||||
|
@ -231,6 +240,15 @@ namespace Ryujinx.Graphics.Shader
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries host support for accessing bindless textures.
|
||||
/// </summary>
|
||||
/// <returns>True if bindless textures are supported, false otherwise</returns>
|
||||
bool QueryHostSupportsBindlessTextures()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries host support for fragment shader ordering critical sections on the shader code.
|
||||
/// </summary>
|
||||
|
|
|
@ -3,6 +3,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
class HostCapabilities
|
||||
{
|
||||
public readonly bool ReducedPrecision;
|
||||
public readonly bool HasUnsizedDescriptorArrayBug;
|
||||
public readonly bool SupportsFragmentShaderInterlock;
|
||||
public readonly bool SupportsFragmentShaderOrderingIntel;
|
||||
public readonly bool SupportsGeometryShaderPassthrough;
|
||||
|
@ -13,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
|
||||
public HostCapabilities(
|
||||
bool reducedPrecision,
|
||||
bool hasUnsizedDescriptorArrayBug,
|
||||
bool supportsFragmentShaderInterlock,
|
||||
bool supportsFragmentShaderOrderingIntel,
|
||||
bool supportsGeometryShaderPassthrough,
|
||||
|
@ -22,6 +24,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
bool supportsViewportMask)
|
||||
{
|
||||
ReducedPrecision = reducedPrecision;
|
||||
HasUnsizedDescriptorArrayBug = hasUnsizedDescriptorArrayBug;
|
||||
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
|
||||
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
|
||||
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
|
||||
|
|
|
@ -195,12 +195,14 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
private void AddBindlessDefinition(int set, int binding, string name, SamplerType samplerType)
|
||||
{
|
||||
TextureDefinition definition = new(set, binding, name, samplerType, TextureFormat.Unknown, TextureUsageFlags.None, 0);
|
||||
|
||||
Properties.AddOrUpdateTexture(definition, samplerType & ~(SamplerType.Separate | SamplerType.Shadow));
|
||||
}
|
||||
|
||||
private void AddBindlessSeparateDefinition(int set, int binding, string name, SamplerType samplerType)
|
||||
{
|
||||
samplerType = (samplerType & ~SamplerType.Shadow) | SamplerType.Separate;
|
||||
|
||||
AddBindlessDefinition(set, binding, name, samplerType);
|
||||
}
|
||||
|
||||
|
@ -212,6 +214,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
binding = _gpuAccessor.QueryBindingConstantBuffer(slot);
|
||||
_cbSlotToBindingMap[slot] = binding;
|
||||
string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
AddNewConstantBuffer(binding, $"{_stagePrefix}_c{slotNumber}");
|
||||
}
|
||||
|
||||
|
@ -234,6 +237,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
binding = _gpuAccessor.QueryBindingStorageBuffer(slot);
|
||||
_sbSlotToBindingMap[slot] = binding;
|
||||
string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
AddNewStorageBuffer(binding, $"{_stagePrefix}_s{slotNumber}");
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||
ref context.BindlessTextureFlags,
|
||||
ref context.BindlessIndexedBuffersMask,
|
||||
context.BindlessTexturesAllowed,
|
||||
context.GpuAccessor.QueryTextureBufferIndex());
|
||||
context.GpuAccessor.QueryTextureBufferIndex(),
|
||||
context.GpuAccessor.QueryHostSupportsBindlessTextures());
|
||||
|
||||
if (prevNode != node)
|
||||
{
|
||||
|
@ -787,7 +788,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||
ref BindlessTextureFlags bindlessTextureFlags,
|
||||
ref uint bindlessIndexedBuffersMask,
|
||||
bool bindlessTexturesAllowed,
|
||||
int textureBufferIndex)
|
||||
int textureBufferIndex,
|
||||
bool supportsBindlessTextures)
|
||||
{
|
||||
if (node.Value is not TextureOperation texOp)
|
||||
{
|
||||
|
@ -797,35 +799,36 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||
// If it's already bindless, then we have nothing to do.
|
||||
if (texOp.Flags.HasFlag(TextureFlags.Bindless))
|
||||
{
|
||||
resourceManager.EnsureBindlessBinding(targetApi, texOp.Type, texOp.Inst.IsImage());
|
||||
|
||||
if (IsIndexedAccess(resourceManager, texOp, ref bindlessTextureFlags, ref bindlessIndexedBuffersMask, textureBufferIndex))
|
||||
if (SupportsBindlessAccess(texOp.Type, supportsBindlessTextures))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
resourceManager.EnsureBindlessBinding(targetApi, texOp.Type, texOp.Inst.IsImage());
|
||||
|
||||
if (bindlessTexturesAllowed)
|
||||
{
|
||||
bindlessTextureFlags |= BindlessTextureFlags.BindlessFull;
|
||||
return node;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set any destination operand to zero and remove the texture access.
|
||||
// This is a case where bindless elimination failed, and we assume
|
||||
// it's too risky to try using full bindless emulation.
|
||||
|
||||
for (int destIndex = 0; destIndex < texOp.DestsCount; destIndex++)
|
||||
if (IsIndexedAccess(resourceManager, texOp, ref bindlessTextureFlags, ref bindlessIndexedBuffersMask, textureBufferIndex))
|
||||
{
|
||||
Operand dest = texOp.GetDest(destIndex);
|
||||
node.List.AddBefore(node, new Operation(Instruction.Copy, dest, Const(0)));
|
||||
return node;
|
||||
}
|
||||
|
||||
LinkedListNode<INode> prevNode = node.Previous;
|
||||
node.List.Remove(node);
|
||||
|
||||
return prevNode;
|
||||
if (bindlessTexturesAllowed)
|
||||
{
|
||||
bindlessTextureFlags |= BindlessTextureFlags.BindlessFull;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
// Set any destination operand to zero and remove the texture access.
|
||||
// This is a case where bindless elimination failed, and we assume
|
||||
// it's too risky or not possible to try using full bindless emulation.
|
||||
|
||||
for (int destIndex = 0; destIndex < texOp.DestsCount; destIndex++)
|
||||
{
|
||||
Operand dest = texOp.GetDest(destIndex);
|
||||
node.List.AddBefore(node, new Operation(Instruction.Copy, dest, Const(0)));
|
||||
}
|
||||
|
||||
LinkedListNode<INode> prevNode = node.Previous;
|
||||
node.List.Remove(node);
|
||||
|
||||
return prevNode;
|
||||
}
|
||||
|
||||
// If the index is within the host API limits, then we don't need to make it bindless.
|
||||
|
@ -866,6 +869,17 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||
return node;
|
||||
}
|
||||
|
||||
private static bool SupportsBindlessAccess(SamplerType type, bool supportsBindlessTextures)
|
||||
{
|
||||
// TODO: Support bindless buffer texture access.
|
||||
if ((type & SamplerType.Mask) == SamplerType.TextureBuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return supportsBindlessTextures;
|
||||
}
|
||||
|
||||
private static bool IsIndexedAccess(
|
||||
ResourceManager resourceManager,
|
||||
TextureOperation texOp,
|
||||
|
|
|
@ -371,6 +371,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
|
||||
var hostCapabilities = new HostCapabilities(
|
||||
GpuAccessor.QueryHostReducedPrecision(),
|
||||
GpuAccessor.QueryHostHasUnsizedDescriptorArrayBug(),
|
||||
GpuAccessor.QueryHostSupportsFragmentShaderInterlock(),
|
||||
GpuAccessor.QueryHostSupportsFragmentShaderOrderingIntel(),
|
||||
GpuAccessor.QueryHostSupportsGeometryShaderPassthrough(),
|
||||
|
|
|
@ -572,10 +572,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
var limits = _physicalDevice.PhysicalDeviceProperties.Limits;
|
||||
|
||||
bool supportsDescriptorIndexing = _physicalDevice.IsDeviceExtensionPresent("VK_EXT_descriptor_indexing");
|
||||
|
||||
return new Capabilities(
|
||||
api: TargetApi.Vulkan,
|
||||
GpuVendor,
|
||||
hasFrontFacingBug: IsIntelWindows,
|
||||
hasUnsizedDescriptorArrayBug: IsMoltenVk,
|
||||
hasVectorIndexingBug: Vendor == Vendor.Qualcomm,
|
||||
needsFragmentOutputSpecialization: IsMoltenVk,
|
||||
reduceShaderPrecision: IsMoltenVk,
|
||||
|
@ -590,6 +593,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
supportsR4G4B4A4Format: supportsR4G4B4A4Format,
|
||||
supportsSnormBufferTextureFormat: true,
|
||||
supports5BitComponentFormat: supports5BitComponentFormat,
|
||||
supportsBindlessTextures: supportsDescriptorIndexing,
|
||||
supportsBlendEquationAdvanced: Capabilities.SupportsBlendEquationAdvanced,
|
||||
supportsFragmentShaderInterlock: Capabilities.SupportsFragmentShaderInterlock,
|
||||
supportsFragmentShaderOrderingIntel: false,
|
||||
|
|
Loading…
Reference in a new issue