Logical simplifications in RDNA3 Vulkan
This commit is contained in:
parent
9a57ac5921
commit
7a11f9f1b1
@ -35,7 +35,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
queue,
|
queue,
|
||||||
queueLock,
|
queueLock,
|
||||||
_gd.QueueFamilyIndex,
|
_gd.QueueFamilyIndex,
|
||||||
_gd.IsQualcommProprietary,
|
concurrentFenceWaitUnsupported: false,
|
||||||
isLight: true);
|
isLight: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,16 +324,12 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_gd.IsTBDR)
|
if (_gd.IsTBDR)
|
||||||
{
|
|
||||||
if (!_gd.IsMoltenVk)
|
|
||||||
{
|
{
|
||||||
if (!anyIsNonAttachment)
|
if (!anyIsNonAttachment)
|
||||||
{
|
{
|
||||||
// This case is a feedback loop. To prevent this from causing an absolute performance disaster,
|
// This case is a feedback loop. To prevent this from causing an absolute performance disaster,
|
||||||
// remove the barriers entirely.
|
// remove the barriers entirely.
|
||||||
// If this is not here, there will be a lot of single draw render passes.
|
// If this is not here, there will be a lot of single draw render passes.
|
||||||
// TODO: explicit handling for feedback loops, likely outside this class.
|
|
||||||
|
|
||||||
_queuedBarrierCount -= _imageBarriers.Count;
|
_queuedBarrierCount -= _imageBarriers.Count;
|
||||||
_imageBarriers.Clear();
|
_imageBarriers.Clear();
|
||||||
}
|
}
|
||||||
@ -345,7 +341,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
inRenderPass = false;
|
inRenderPass = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Generic pipeline memory barriers will work for desktop GPUs.
|
// Generic pipeline memory barriers will work for desktop GPUs.
|
||||||
@ -354,7 +349,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
{
|
{
|
||||||
_memoryBarriers.Add(new BarrierWithStageFlags<MemoryBarrier, int>(
|
_memoryBarriers.Add(new BarrierWithStageFlags<MemoryBarrier, int>(
|
||||||
barrier.Flags,
|
barrier.Flags,
|
||||||
new MemoryBarrier()
|
new MemoryBarrier
|
||||||
{
|
{
|
||||||
SType = StructureType.MemoryBarrier,
|
SType = StructureType.MemoryBarrier,
|
||||||
SrcAccessMask = barrier.Barrier.SrcAccessMask,
|
SrcAccessMask = barrier.Barrier.SrcAccessMask,
|
||||||
@ -375,7 +370,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
allFlags |= barrier.Flags.Dest;
|
allFlags |= barrier.Flags.Dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allFlags.HasFlag(PipelineStageFlags.DrawIndirectBit) || !_gd.SupportsRenderPassBarrier(allFlags))
|
if (allFlags.HasFlag(PipelineStageFlags.DrawIndirectBit))
|
||||||
{
|
{
|
||||||
endRenderPass();
|
endRenderPass();
|
||||||
inRenderPass = false;
|
inRenderPass = false;
|
||||||
|
@ -698,16 +698,9 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Texture))
|
if (_dirty.HasFlag(DirtyFlags.Texture))
|
||||||
{
|
|
||||||
if (program.UpdateTexturesWithoutTemplate)
|
|
||||||
{
|
|
||||||
UpdateAndBindTexturesWithoutTemplate(cbs, program, pbp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, program, PipelineBase.TextureSetIndex, pbp);
|
UpdateAndBind(cbs, program, PipelineBase.TextureSetIndex, pbp);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Image))
|
if (_dirty.HasFlag(DirtyFlags.Image))
|
||||||
{
|
{
|
||||||
@ -940,86 +933,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
_gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan<uint>.Empty);
|
_gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan<uint>.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateAndBindTexturesWithoutTemplate(CommandBufferScoped cbs, ShaderCollection program, PipelineBindPoint pbp)
|
|
||||||
{
|
|
||||||
int setIndex = PipelineBase.TextureSetIndex;
|
|
||||||
var bindingSegments = program.BindingSegments[setIndex];
|
|
||||||
|
|
||||||
if (bindingSegments.Length == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_updateDescriptorCacheCbIndex)
|
|
||||||
{
|
|
||||||
_updateDescriptorCacheCbIndex = false;
|
|
||||||
program.UpdateDescriptorCacheCommandBufferIndex(cbs.CommandBufferIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dsc = program.GetNewDescriptorSetCollection(setIndex, out _).Get(cbs);
|
|
||||||
|
|
||||||
foreach (ResourceBindingSegment segment in bindingSegments)
|
|
||||||
{
|
|
||||||
int binding = segment.Binding;
|
|
||||||
int count = segment.Count;
|
|
||||||
|
|
||||||
if (!segment.IsArray)
|
|
||||||
{
|
|
||||||
if (segment.Type != ResourceType.BufferTexture)
|
|
||||||
{
|
|
||||||
Span<DescriptorImageInfo> textures = _textures;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
ref var texture = ref textures[i];
|
|
||||||
ref var refs = ref _textureRefs[binding + i];
|
|
||||||
|
|
||||||
texture.ImageView = refs.ImageView?.Get(cbs).Value ?? default;
|
|
||||||
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
|
|
||||||
|
|
||||||
if (texture.ImageView.Handle == 0)
|
|
||||||
{
|
|
||||||
texture.ImageView = _dummyTexture.GetImageView().Get(cbs).Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (texture.Sampler.Handle == 0)
|
|
||||||
{
|
|
||||||
texture.Sampler = _dummySampler.GetSampler().Get(cbs).Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dsc.UpdateImages(0, binding, textures[..count], DescriptorType.CombinedImageSampler);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Span<BufferView> bufferTextures = _bufferTextures;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
bufferTextures[i] = _bufferTextureRefs[binding + i]?.GetBufferView(cbs, false) ?? default;
|
|
||||||
}
|
|
||||||
|
|
||||||
dsc.UpdateBufferImages(0, binding, bufferTextures[..count], DescriptorType.UniformTexelBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (segment.Type != ResourceType.BufferTexture)
|
|
||||||
{
|
|
||||||
dsc.UpdateImages(0, binding, _textureArrayRefs[binding].Array.GetImageInfos(_gd, cbs, _dummyTexture, _dummySampler), DescriptorType.CombinedImageSampler);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dsc.UpdateBufferImages(0, binding, _textureArrayRefs[binding].Array.GetBufferViews(cbs), DescriptorType.UniformTexelBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var sets = dsc.GetSets();
|
|
||||||
|
|
||||||
_gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan<uint>.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void UpdateAndBindUniformBufferPd(CommandBufferScoped cbs)
|
private void UpdateAndBindUniformBufferPd(CommandBufferScoped cbs)
|
||||||
{
|
{
|
||||||
|
@ -970,13 +970,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
{
|
{
|
||||||
_newState.RasterizerDiscardEnable = discard;
|
_newState.RasterizerDiscardEnable = discard;
|
||||||
SignalStateChange();
|
SignalStateChange();
|
||||||
|
|
||||||
if (!discard && Gd.IsQualcommProprietary)
|
|
||||||
{
|
|
||||||
// On Adreno, enabling rasterizer discard somehow corrupts the viewport state.
|
|
||||||
// Force it to be updated on next use to work around this bug.
|
|
||||||
DynamicState.ForceAllDirty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask)
|
public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask)
|
||||||
@ -1241,7 +1234,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
|
|
||||||
int vbSize = vertexBuffer.Buffer.Size;
|
int vbSize = vertexBuffer.Buffer.Size;
|
||||||
|
|
||||||
if (Gd.Vendor == Vendor.Amd && !Gd.IsMoltenVk && vertexBuffer.Stride > 0)
|
if (vertexBuffer.Stride > 0)
|
||||||
{
|
{
|
||||||
// AMD has a bug where if offset + stride * count is greater than
|
// AMD has a bug where if offset + stride * count is greater than
|
||||||
// the size, then the last attribute will have the wrong value.
|
// the size, then the last attribute will have the wrong value.
|
||||||
|
@ -49,7 +49,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (componentMask != 0xf || Gd.IsQualcommProprietary)
|
if (componentMask != 0xf)
|
||||||
{
|
{
|
||||||
// We can't use CmdClearAttachments if not writing all components,
|
// We can't use CmdClearAttachments if not writing all components,
|
||||||
// because on Vulkan, the pipeline state does not affect clears.
|
// because on Vulkan, the pipeline state does not affect clears.
|
||||||
@ -90,7 +90,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((stencilMask != 0 && stencilMask != 0xff) || Gd.IsQualcommProprietary)
|
if (stencilMask != 0 && stencilMask != 0xff)
|
||||||
{
|
{
|
||||||
// We can't use CmdClearAttachments if not clearing all (mask is all ones, 0xFF) or none (mask is 0) of the stencil bits,
|
// We can't use CmdClearAttachments if not clearing all (mask is all ones, 0xFF) or none (mask is 0) of the stencil bits,
|
||||||
// because on Vulkan, the pipeline state does not affect clears.
|
// because on Vulkan, the pipeline state does not affect clears.
|
||||||
|
@ -19,22 +19,10 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
DescriptorSetLayout[] layouts = new DescriptorSetLayout[setDescriptors.Count];
|
DescriptorSetLayout[] layouts = new DescriptorSetLayout[setDescriptors.Count];
|
||||||
bool[] updateAfterBindFlags = new bool[setDescriptors.Count];
|
bool[] updateAfterBindFlags = new bool[setDescriptors.Count];
|
||||||
|
|
||||||
bool isMoltenVk = gd.IsMoltenVk;
|
|
||||||
|
|
||||||
for (int setIndex = 0; setIndex < setDescriptors.Count; setIndex++)
|
for (int setIndex = 0; setIndex < setDescriptors.Count; setIndex++)
|
||||||
{
|
{
|
||||||
ResourceDescriptorCollection rdc = setDescriptors[setIndex];
|
ResourceDescriptorCollection rdc = setDescriptors[setIndex];
|
||||||
|
|
||||||
ResourceStages activeStages = ResourceStages.None;
|
|
||||||
|
|
||||||
if (isMoltenVk)
|
|
||||||
{
|
|
||||||
for (int descIndex = 0; descIndex < rdc.Descriptors.Count; descIndex++)
|
|
||||||
{
|
|
||||||
activeStages |= rdc.Descriptors[descIndex].Stages;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DescriptorSetLayoutBinding[] layoutBindings = new DescriptorSetLayoutBinding[rdc.Descriptors.Count];
|
DescriptorSetLayoutBinding[] layoutBindings = new DescriptorSetLayoutBinding[rdc.Descriptors.Count];
|
||||||
|
|
||||||
bool hasArray = false;
|
bool hasArray = false;
|
||||||
@ -44,13 +32,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
ResourceDescriptor descriptor = rdc.Descriptors[descIndex];
|
ResourceDescriptor descriptor = rdc.Descriptors[descIndex];
|
||||||
ResourceStages stages = descriptor.Stages;
|
ResourceStages stages = descriptor.Stages;
|
||||||
|
|
||||||
if (descriptor.Type == ResourceType.StorageBuffer && isMoltenVk)
|
|
||||||
{
|
|
||||||
// There's a bug on MoltenVK where using the same buffer across different stages
|
|
||||||
// causes invalid resource errors, allow the binding on all active stages as workaround.
|
|
||||||
stages = activeStages;
|
|
||||||
}
|
|
||||||
|
|
||||||
layoutBindings[descIndex] = new DescriptorSetLayoutBinding
|
layoutBindings[descIndex] = new DescriptorSetLayoutBinding
|
||||||
{
|
{
|
||||||
Binding = (uint)descriptor.Binding,
|
Binding = (uint)descriptor.Binding,
|
||||||
@ -74,15 +55,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
flags = DescriptorSetLayoutCreateFlags.PushDescriptorBitKhr;
|
flags = DescriptorSetLayoutCreateFlags.PushDescriptorBitKhr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gd.Vendor == Vendor.Intel && hasArray)
|
|
||||||
{
|
|
||||||
// Some vendors (like Intel) have low per-stage limits.
|
|
||||||
// We must set the flag if we exceed those limits.
|
|
||||||
flags |= DescriptorSetLayoutCreateFlags.UpdateAfterBindPoolBit;
|
|
||||||
|
|
||||||
updateAfterBindFlags[setIndex] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var descriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo
|
var descriptorSetLayoutCreateInfo = new DescriptorSetLayoutCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.DescriptorSetLayoutCreateInfo,
|
SType = StructureType.DescriptorSetLayoutCreateInfo,
|
||||||
|
@ -393,15 +393,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
|
|
||||||
Pipeline pipelineHandle = default;
|
Pipeline pipelineHandle = default;
|
||||||
|
|
||||||
bool isMoltenVk = gd.IsMoltenVk;
|
|
||||||
|
|
||||||
if (isMoltenVk)
|
|
||||||
{
|
|
||||||
UpdateVertexAttributeDescriptions(gd);
|
|
||||||
}
|
|
||||||
|
|
||||||
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
|
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
|
||||||
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0])
|
|
||||||
fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0])
|
fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0])
|
||||||
fixed (PipelineColorBlendAttachmentState* pColorBlendAttachmentState = &Internal.ColorBlendAttachmentState[0])
|
fixed (PipelineColorBlendAttachmentState* pColorBlendAttachmentState = &Internal.ColorBlendAttachmentState[0])
|
||||||
{
|
{
|
||||||
@ -409,7 +401,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
{
|
{
|
||||||
SType = StructureType.PipelineVertexInputStateCreateInfo,
|
SType = StructureType.PipelineVertexInputStateCreateInfo,
|
||||||
VertexAttributeDescriptionCount = VertexAttributeDescriptionsCount,
|
VertexAttributeDescriptionCount = VertexAttributeDescriptionsCount,
|
||||||
PVertexAttributeDescriptions = isMoltenVk ? pVertexAttributeDescriptions2 : pVertexAttributeDescriptions,
|
PVertexAttributeDescriptions = pVertexAttributeDescriptions,
|
||||||
VertexBindingDescriptionCount = VertexBindingDescriptionsCount,
|
VertexBindingDescriptionCount = VertexBindingDescriptionsCount,
|
||||||
PVertexBindingDescriptions = pVertexBindingDescriptions,
|
PVertexBindingDescriptions = pVertexBindingDescriptions,
|
||||||
};
|
};
|
||||||
@ -519,27 +511,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
Back = stencilBack,
|
Back = stencilBack,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint blendEnables = 0;
|
|
||||||
|
|
||||||
if (gd.IsMoltenVk && Internal.AttachmentIntegerFormatMask != 0)
|
|
||||||
{
|
|
||||||
// Blend can't be enabled for integer formats, so let's make sure it is disabled.
|
|
||||||
uint attachmentIntegerFormatMask = Internal.AttachmentIntegerFormatMask;
|
|
||||||
|
|
||||||
while (attachmentIntegerFormatMask != 0)
|
|
||||||
{
|
|
||||||
int i = BitOperations.TrailingZeroCount(attachmentIntegerFormatMask);
|
|
||||||
|
|
||||||
if (Internal.ColorBlendAttachmentState[i].BlendEnable)
|
|
||||||
{
|
|
||||||
blendEnables |= 1u << i;
|
|
||||||
}
|
|
||||||
|
|
||||||
Internal.ColorBlendAttachmentState[i].BlendEnable = false;
|
|
||||||
attachmentIntegerFormatMask &= ~(1u << i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vendors other than NVIDIA have a bug where it enables logical operations even for float formats,
|
// Vendors other than NVIDIA have a bug where it enables logical operations even for float formats,
|
||||||
// so we need to force disable them here.
|
// so we need to force disable them here.
|
||||||
bool logicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed);
|
bool logicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed);
|
||||||
@ -650,15 +621,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore previous blend enable values if we changed it.
|
|
||||||
while (blendEnables != 0)
|
|
||||||
{
|
|
||||||
int i = BitOperations.TrailingZeroCount(blendEnables);
|
|
||||||
|
|
||||||
Internal.ColorBlendAttachmentState[i].BlendEnable = true;
|
|
||||||
blendEnables &= ~(1u << i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline = new Auto<DisposablePipeline>(new DisposablePipeline(gd.Api, device, pipelineHandle));
|
pipeline = new Auto<DisposablePipeline>(new DisposablePipeline(gd.Api, device, pipelineHandle));
|
||||||
|
@ -23,8 +23,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
public bool IsCompute { get; }
|
public bool IsCompute { get; }
|
||||||
public bool HasTessellationControlShader => (Stages & (1u << 3)) != 0;
|
public bool HasTessellationControlShader => (Stages & (1u << 3)) != 0;
|
||||||
|
|
||||||
public bool UpdateTexturesWithoutTemplate { get; }
|
|
||||||
|
|
||||||
public uint Stages { get; }
|
public uint Stages { get; }
|
||||||
|
|
||||||
public PipelineStageFlags IncoherentBufferWriteStages { get; }
|
public PipelineStageFlags IncoherentBufferWriteStages { get; }
|
||||||
@ -118,7 +116,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
VulkanConfiguration.UsePushDescriptors &&
|
VulkanConfiguration.UsePushDescriptors &&
|
||||||
_gd.Capabilities.SupportsPushDescriptors &&
|
_gd.Capabilities.SupportsPushDescriptors &&
|
||||||
!IsCompute &&
|
!IsCompute &&
|
||||||
!HasPushDescriptorsBug(gd) &&
|
|
||||||
CanUsePushDescriptors(gd, resourceLayout, IsCompute);
|
CanUsePushDescriptors(gd, resourceLayout, IsCompute);
|
||||||
|
|
||||||
ReadOnlyCollection<ResourceDescriptorCollection> sets = usePushDescriptors ?
|
ReadOnlyCollection<ResourceDescriptorCollection> sets = usePushDescriptors ?
|
||||||
@ -136,9 +133,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
Templates = BuildTemplates(usePushDescriptors);
|
Templates = BuildTemplates(usePushDescriptors);
|
||||||
(IncoherentBufferWriteStages, IncoherentTextureWriteStages) = BuildIncoherentStages(resourceLayout.SetUsages);
|
(IncoherentBufferWriteStages, IncoherentTextureWriteStages) = BuildIncoherentStages(resourceLayout.SetUsages);
|
||||||
|
|
||||||
// Updating buffer texture bindings using template updates crashes the Adreno driver on Windows.
|
|
||||||
UpdateTexturesWithoutTemplate = gd.IsQualcommProprietary && usesBufferTextures;
|
|
||||||
|
|
||||||
_compileTask = Task.CompletedTask;
|
_compileTask = Task.CompletedTask;
|
||||||
_firstBackgroundUse = false;
|
_firstBackgroundUse = false;
|
||||||
}
|
}
|
||||||
@ -157,12 +151,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
_firstBackgroundUse = !fromCache;
|
_firstBackgroundUse = !fromCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool HasPushDescriptorsBug(VulkanRenderer gd)
|
|
||||||
{
|
|
||||||
// Those GPUs/drivers do not work properly with push descriptors, so we must force disable them.
|
|
||||||
return gd.IsNvidiaPreTuring || (gd.IsIntelArc && gd.IsIntelWindows);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool CanUsePushDescriptors(VulkanRenderer gd, ResourceLayout layout, bool isCompute)
|
private static bool CanUsePushDescriptors(VulkanRenderer gd, ResourceLayout layout, bool isCompute)
|
||||||
{
|
{
|
||||||
// If binding 3 is immediately used, use an alternate set of reserved bindings.
|
// If binding 3 is immediately used, use an alternate set of reserved bindings.
|
||||||
|
@ -99,7 +99,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
|
|
||||||
// This flag causes mipmapped texture arrays to break on AMD GCN, so for that copy dependencies are forced for aliasing as cube.
|
// This flag causes mipmapped texture arrays to break on AMD GCN, so for that copy dependencies are forced for aliasing as cube.
|
||||||
bool isCube = info.Target == Target.Cubemap || info.Target == Target.CubemapArray;
|
bool isCube = info.Target == Target.Cubemap || info.Target == Target.CubemapArray;
|
||||||
bool cubeCompatible = gd.IsAmdGcn ? isCube : (info.Width == info.Height && layers >= 6);
|
bool cubeCompatible = info.Width == info.Height && layers >= 6;
|
||||||
|
|
||||||
if (type == ImageType.Type2D && cubeCompatible)
|
if (type == ImageType.Type2D && cubeCompatible)
|
||||||
{
|
{
|
||||||
|
@ -87,12 +87,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
|
|
||||||
internal Vendor Vendor { get; private set; }
|
internal Vendor Vendor { get; private set; }
|
||||||
internal bool IsAmdWindows { get; private set; }
|
internal bool IsAmdWindows { get; private set; }
|
||||||
internal bool IsIntelWindows { get; private set; }
|
|
||||||
internal bool IsAmdGcn { get; private set; }
|
|
||||||
internal bool IsNvidiaPreTuring { get; private set; }
|
|
||||||
internal bool IsIntelArc { get; private set; }
|
|
||||||
internal bool IsQualcommProprietary { get; private set; }
|
|
||||||
internal bool IsMoltenVk { get; private set; }
|
|
||||||
internal bool IsTBDR { get; private set; }
|
internal bool IsTBDR { get; private set; }
|
||||||
internal bool IsSharedMemory { get; private set; }
|
internal bool IsSharedMemory { get; private set; }
|
||||||
|
|
||||||
@ -350,7 +344,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
Vendor = VendorUtils.FromId(properties.VendorID);
|
Vendor = VendorUtils.FromId(properties.VendorID);
|
||||||
|
|
||||||
IsAmdWindows = Vendor == Vendor.Amd && OperatingSystem.IsWindows();
|
IsAmdWindows = Vendor == Vendor.Amd && OperatingSystem.IsWindows();
|
||||||
IsIntelWindows = Vendor == Vendor.Intel && OperatingSystem.IsWindows();
|
|
||||||
IsTBDR =
|
IsTBDR =
|
||||||
Vendor == Vendor.Apple ||
|
Vendor == Vendor.Apple ||
|
||||||
Vendor == Vendor.Qualcomm ||
|
Vendor == Vendor.Qualcomm ||
|
||||||
@ -369,28 +362,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
|
|
||||||
GpuVersion = $"Vulkan v{ParseStandardVulkanVersion(properties.ApiVersion)}, Driver v{ParseDriverVersion(ref properties)}";
|
GpuVersion = $"Vulkan v{ParseStandardVulkanVersion(properties.ApiVersion)}, Driver v{ParseDriverVersion(ref properties)}";
|
||||||
|
|
||||||
IsAmdGcn = !IsMoltenVk && Vendor == Vendor.Amd && VendorUtils.AmdGcnRegex().IsMatch(GpuRenderer);
|
|
||||||
|
|
||||||
if (Vendor == Vendor.Nvidia)
|
|
||||||
{
|
|
||||||
var match = VendorUtils.NvidiaConsumerClassRegex().Match(GpuRenderer);
|
|
||||||
|
|
||||||
if (match != null && int.TryParse(match.Groups[2].Value, out int gpuNumber))
|
|
||||||
{
|
|
||||||
IsNvidiaPreTuring = gpuNumber < 2000;
|
|
||||||
}
|
|
||||||
else if (GpuRenderer.Contains("TITAN") && !GpuRenderer.Contains("RTX"))
|
|
||||||
{
|
|
||||||
IsNvidiaPreTuring = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Vendor == Vendor.Intel)
|
|
||||||
{
|
|
||||||
IsIntelArc = GpuRenderer.StartsWith("Intel(R) Arc(TM)");
|
|
||||||
}
|
|
||||||
|
|
||||||
IsQualcommProprietary = hasDriverProperties && driverProperties.DriverID == DriverId.QualcommProprietary;
|
|
||||||
|
|
||||||
ulong minResourceAlignment = Math.Max(
|
ulong minResourceAlignment = Math.Max(
|
||||||
Math.Max(
|
Math.Max(
|
||||||
properties.Limits.MinStorageBufferOffsetAlignment,
|
properties.Limits.MinStorageBufferOffsetAlignment,
|
||||||
@ -419,9 +390,9 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
features2.Features.ShaderStorageImageMultisample,
|
features2.Features.ShaderStorageImageMultisample,
|
||||||
_physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName),
|
_physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName),
|
||||||
_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName),
|
_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName),
|
||||||
features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue
|
features2.Features.MultiViewport, // Workaround for AMD on MoltenVK issue
|
||||||
featuresRobustness2.NullDescriptor || IsMoltenVk,
|
featuresRobustness2.NullDescriptor,
|
||||||
supportsPushDescriptors && !IsMoltenVk,
|
supportsPushDescriptors,
|
||||||
propertiesPushDescriptor.MaxPushDescriptors,
|
propertiesPushDescriptor.MaxPushDescriptors,
|
||||||
featuresPrimitiveTopologyListRestart.PrimitiveTopologyListRestart,
|
featuresPrimitiveTopologyListRestart.PrimitiveTopologyListRestart,
|
||||||
featuresPrimitiveTopologyListRestart.PrimitiveTopologyPatchListRestart,
|
featuresPrimitiveTopologyListRestart.PrimitiveTopologyPatchListRestart,
|
||||||
@ -450,7 +421,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExternalMemoryHost hostMemoryApi);
|
Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExternalMemoryHost hostMemoryApi);
|
||||||
HostMemoryAllocator = new HostMemoryAllocator(MemoryAllocator, Api, hostMemoryApi, _device);
|
HostMemoryAllocator = new HostMemoryAllocator(MemoryAllocator, Api, hostMemoryApi, _device);
|
||||||
|
|
||||||
CommandBufferPool = new CommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex, IsQualcommProprietary);
|
CommandBufferPool = new CommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex, false);
|
||||||
|
|
||||||
PipelineLayoutCache = new PipelineLayoutCache();
|
PipelineLayoutCache = new PipelineLayoutCache();
|
||||||
|
|
||||||
@ -728,10 +699,10 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
api: TargetApi.Vulkan,
|
api: TargetApi.Vulkan,
|
||||||
GpuVendor,
|
GpuVendor,
|
||||||
memoryType: memoryType,
|
memoryType: memoryType,
|
||||||
hasFrontFacingBug: IsIntelWindows,
|
hasFrontFacingBug: false,
|
||||||
hasVectorIndexingBug: IsQualcommProprietary,
|
hasVectorIndexingBug: false,
|
||||||
needsFragmentOutputSpecialization: IsMoltenVk,
|
needsFragmentOutputSpecialization: false,
|
||||||
reduceShaderPrecision: IsMoltenVk,
|
reduceShaderPrecision: false,
|
||||||
supportsAstcCompression: features2.Features.TextureCompressionAstcLdr && supportsAstcFormats,
|
supportsAstcCompression: features2.Features.TextureCompressionAstcLdr && supportsAstcFormats,
|
||||||
supportsBc123Compression: supportsBc123CompressionFormat,
|
supportsBc123Compression: supportsBc123CompressionFormat,
|
||||||
supportsBc45Compression: supportsBc45CompressionFormat,
|
supportsBc45Compression: supportsBc45CompressionFormat,
|
||||||
@ -754,14 +725,14 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
supportsImageLoadFormatted: features2.Features.ShaderStorageImageReadWithoutFormat,
|
supportsImageLoadFormatted: features2.Features.ShaderStorageImageReadWithoutFormat,
|
||||||
supportsLayerVertexTessellation: featuresVk12.ShaderOutputLayer,
|
supportsLayerVertexTessellation: featuresVk12.ShaderOutputLayer,
|
||||||
supportsMismatchingViewFormat: true,
|
supportsMismatchingViewFormat: true,
|
||||||
supportsCubemapView: !IsAmdGcn,
|
supportsCubemapView: true,
|
||||||
supportsNonConstantTextureOffset: false,
|
supportsNonConstantTextureOffset: false,
|
||||||
supportsQuads: false,
|
supportsQuads: false,
|
||||||
supportsSeparateSampler: true,
|
supportsSeparateSampler: true,
|
||||||
supportsShaderBallot: false,
|
supportsShaderBallot: false,
|
||||||
supportsShaderBarrierDivergence: Vendor != Vendor.Intel,
|
supportsShaderBarrierDivergence: Vendor != Vendor.Intel,
|
||||||
supportsShaderFloat64: Capabilities.SupportsShaderFloat64,
|
supportsShaderFloat64: Capabilities.SupportsShaderFloat64,
|
||||||
supportsTextureGatherOffsets: features2.Features.ShaderImageGatherExtended && !IsMoltenVk,
|
supportsTextureGatherOffsets: features2.Features.ShaderImageGatherExtended,
|
||||||
supportsTextureShadowLod: false,
|
supportsTextureShadowLod: false,
|
||||||
supportsVertexStoreAndAtomics: features2.Features.VertexPipelineStoresAndAtomics,
|
supportsVertexStoreAndAtomics: features2.Features.VertexPipelineStoresAndAtomics,
|
||||||
supportsViewportIndexVertexTessellation: featuresVk12.ShaderOutputViewportIndex,
|
supportsViewportIndexVertexTessellation: featuresVk12.ShaderOutputViewportIndex,
|
||||||
@ -784,7 +755,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
shaderSubgroupSize: (int)Capabilities.SubgroupSize,
|
shaderSubgroupSize: (int)Capabilities.SubgroupSize,
|
||||||
storageBufferOffsetAlignment: (int)limits.MinStorageBufferOffsetAlignment,
|
storageBufferOffsetAlignment: (int)limits.MinStorageBufferOffsetAlignment,
|
||||||
textureBufferOffsetAlignment: (int)limits.MinTexelBufferOffsetAlignment,
|
textureBufferOffsetAlignment: (int)limits.MinTexelBufferOffsetAlignment,
|
||||||
gatherBiasPrecision: IsIntelWindows || IsAmdWindows ? (int)Capabilities.SubTexelPrecisionBits : 0,
|
gatherBiasPrecision: IsAmdWindows ? (int)Capabilities.SubTexelPrecisionBits : 0,
|
||||||
maximumGpuMemory: GetTotalGPUMemory());
|
maximumGpuMemory: GetTotalGPUMemory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,8 +881,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (Vendor != Vendor.Nvidia)
|
|
||||||
{
|
|
||||||
// Vulkan requires that vertex attributes are globally aligned by their component size,
|
// Vulkan requires that vertex attributes are globally aligned by their component size,
|
||||||
// so buffer strides that don't divide by the largest scalar element are invalid.
|
// so buffer strides that don't divide by the largest scalar element are invalid.
|
||||||
// Guest applications do this, NVIDIA GPUs are OK with it, others are not.
|
// Guest applications do this, NVIDIA GPUs are OK with it, others are not.
|
||||||
@ -921,11 +891,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
alignment = 1;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PreFrame()
|
public void PreFrame()
|
||||||
{
|
{
|
||||||
SyncManager.Cleanup();
|
SyncManager.Cleanup();
|
||||||
@ -1001,11 +966,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan
|
|||||||
ScreenCaptured?.Invoke(this, bitmap);
|
ScreenCaptured?.Invoke(this, bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SupportsRenderPassBarrier(PipelineStageFlags flags)
|
|
||||||
{
|
|
||||||
return !(IsMoltenVk || IsQualcommProprietary);
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe void Dispose()
|
public unsafe void Dispose()
|
||||||
{
|
{
|
||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user