From 7a11f9f1b19cc4ce5ac8e1032df11fbf49f8e0ec Mon Sep 17 00:00:00 2001 From: Evan Husted Date: Mon, 6 Jan 2025 00:54:48 -0600 Subject: [PATCH] Logical simplifications in RDNA3 Vulkan --- .../BackgroundResources.cs | 2 +- .../BarrierBatch.cs | 35 ++++---- .../DescriptorSetUpdater.cs | 89 +------------------ .../PipelineBase.cs | 9 +- .../PipelineFull.cs | 4 +- .../PipelineLayoutFactory.cs | 28 ------ .../PipelineState.cs | 40 +-------- .../ShaderCollection.cs | 12 --- .../TextureStorage.cs | 2 +- .../VulkanRenderer.cs | 74 ++++----------- 10 files changed, 39 insertions(+), 256 deletions(-) diff --git a/src/Ryujinx.Graphics.Rdna3Vulkan/BackgroundResources.cs b/src/Ryujinx.Graphics.Rdna3Vulkan/BackgroundResources.cs index 6c9d479f1..28f9e65ed 100644 --- a/src/Ryujinx.Graphics.Rdna3Vulkan/BackgroundResources.cs +++ b/src/Ryujinx.Graphics.Rdna3Vulkan/BackgroundResources.cs @@ -35,7 +35,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan queue, queueLock, _gd.QueueFamilyIndex, - _gd.IsQualcommProprietary, + concurrentFenceWaitUnsupported: false, isLight: true); } } diff --git a/src/Ryujinx.Graphics.Rdna3Vulkan/BarrierBatch.cs b/src/Ryujinx.Graphics.Rdna3Vulkan/BarrierBatch.cs index 058022232..f940b1d39 100644 --- a/src/Ryujinx.Graphics.Rdna3Vulkan/BarrierBatch.cs +++ b/src/Ryujinx.Graphics.Rdna3Vulkan/BarrierBatch.cs @@ -325,25 +325,20 @@ namespace Ryujinx.Graphics.Rdna3Vulkan 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, - // remove the barriers entirely. - // 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; - _imageBarriers.Clear(); - } - else - { - // TBDR GPUs are sensitive to barriers, so we need to end the pass to ensure the data is available. - // Metal already has hazard tracking so MVK doesn't need this. - endRenderPass(); - inRenderPass = false; - } + // This case is a feedback loop. To prevent this from causing an absolute performance disaster, + // remove the barriers entirely. + // If this is not here, there will be a lot of single draw render passes. + _queuedBarrierCount -= _imageBarriers.Count; + _imageBarriers.Clear(); + } + else + { + // TBDR GPUs are sensitive to barriers, so we need to end the pass to ensure the data is available. + // Metal already has hazard tracking so MVK doesn't need this. + endRenderPass(); + inRenderPass = false; } } else @@ -354,7 +349,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan { _memoryBarriers.Add(new BarrierWithStageFlags( barrier.Flags, - new MemoryBarrier() + new MemoryBarrier { SType = StructureType.MemoryBarrier, SrcAccessMask = barrier.Barrier.SrcAccessMask, @@ -375,7 +370,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan allFlags |= barrier.Flags.Dest; } - if (allFlags.HasFlag(PipelineStageFlags.DrawIndirectBit) || !_gd.SupportsRenderPassBarrier(allFlags)) + if (allFlags.HasFlag(PipelineStageFlags.DrawIndirectBit)) { endRenderPass(); inRenderPass = false; diff --git a/src/Ryujinx.Graphics.Rdna3Vulkan/DescriptorSetUpdater.cs b/src/Ryujinx.Graphics.Rdna3Vulkan/DescriptorSetUpdater.cs index ed7098a93..fd1a246f9 100644 --- a/src/Ryujinx.Graphics.Rdna3Vulkan/DescriptorSetUpdater.cs +++ b/src/Ryujinx.Graphics.Rdna3Vulkan/DescriptorSetUpdater.cs @@ -699,14 +699,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan 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)) @@ -940,86 +933,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan _gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan.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 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 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.Empty); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] private void UpdateAndBindUniformBufferPd(CommandBufferScoped cbs) { diff --git a/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineBase.cs index 9aff2aeac..11496dade 100644 --- a/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineBase.cs @@ -970,13 +970,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan { _newState.RasterizerDiscardEnable = discard; 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 componentMask) @@ -1241,7 +1234,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan 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 // the size, then the last attribute will have the wrong value. diff --git a/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineFull.cs b/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineFull.cs index 248a89c3a..157423ca3 100644 --- a/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineFull.cs +++ b/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineFull.cs @@ -49,7 +49,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan return; } - if (componentMask != 0xf || Gd.IsQualcommProprietary) + if (componentMask != 0xf) { // We can't use CmdClearAttachments if not writing all components, // because on Vulkan, the pipeline state does not affect clears. @@ -90,7 +90,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan 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, // because on Vulkan, the pipeline state does not affect clears. diff --git a/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineLayoutFactory.cs b/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineLayoutFactory.cs index 04411940e..94783428a 100644 --- a/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineLayoutFactory.cs +++ b/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineLayoutFactory.cs @@ -19,22 +19,10 @@ namespace Ryujinx.Graphics.Rdna3Vulkan DescriptorSetLayout[] layouts = new DescriptorSetLayout[setDescriptors.Count]; bool[] updateAfterBindFlags = new bool[setDescriptors.Count]; - bool isMoltenVk = gd.IsMoltenVk; - for (int setIndex = 0; setIndex < setDescriptors.Count; 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]; bool hasArray = false; @@ -44,13 +32,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan ResourceDescriptor descriptor = rdc.Descriptors[descIndex]; 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 { Binding = (uint)descriptor.Binding, @@ -74,15 +55,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan 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 { SType = StructureType.DescriptorSetLayoutCreateInfo, diff --git a/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineState.cs index b683c6334..a0b8707d2 100644 --- a/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Rdna3Vulkan/PipelineState.cs @@ -393,15 +393,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan Pipeline pipelineHandle = default; - bool isMoltenVk = gd.IsMoltenVk; - - if (isMoltenVk) - { - UpdateVertexAttributeDescriptions(gd); - } - fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0]) - fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions2 = &_vertexAttributeDescriptions2[0]) fixed (VertexInputBindingDescription* pVertexBindingDescriptions = &Internal.VertexBindingDescriptions[0]) fixed (PipelineColorBlendAttachmentState* pColorBlendAttachmentState = &Internal.ColorBlendAttachmentState[0]) { @@ -409,7 +401,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan { SType = StructureType.PipelineVertexInputStateCreateInfo, VertexAttributeDescriptionCount = VertexAttributeDescriptionsCount, - PVertexAttributeDescriptions = isMoltenVk ? pVertexAttributeDescriptions2 : pVertexAttributeDescriptions, + PVertexAttributeDescriptions = pVertexAttributeDescriptions, VertexBindingDescriptionCount = VertexBindingDescriptionsCount, PVertexBindingDescriptions = pVertexBindingDescriptions, }; @@ -519,27 +511,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan 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, // so we need to force disable them here. bool logicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed); @@ -650,15 +621,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan 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(new DisposablePipeline(gd.Api, device, pipelineHandle)); diff --git a/src/Ryujinx.Graphics.Rdna3Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Rdna3Vulkan/ShaderCollection.cs index f103f5009..92bf002e0 100644 --- a/src/Ryujinx.Graphics.Rdna3Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Rdna3Vulkan/ShaderCollection.cs @@ -23,8 +23,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan public bool IsCompute { get; } public bool HasTessellationControlShader => (Stages & (1u << 3)) != 0; - public bool UpdateTexturesWithoutTemplate { get; } - public uint Stages { get; } public PipelineStageFlags IncoherentBufferWriteStages { get; } @@ -118,7 +116,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan VulkanConfiguration.UsePushDescriptors && _gd.Capabilities.SupportsPushDescriptors && !IsCompute && - !HasPushDescriptorsBug(gd) && CanUsePushDescriptors(gd, resourceLayout, IsCompute); ReadOnlyCollection sets = usePushDescriptors ? @@ -136,9 +133,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan Templates = BuildTemplates(usePushDescriptors); (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; _firstBackgroundUse = false; } @@ -157,12 +151,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan _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) { // If binding 3 is immediately used, use an alternate set of reserved bindings. diff --git a/src/Ryujinx.Graphics.Rdna3Vulkan/TextureStorage.cs b/src/Ryujinx.Graphics.Rdna3Vulkan/TextureStorage.cs index 794190817..c7c2b21e0 100644 --- a/src/Ryujinx.Graphics.Rdna3Vulkan/TextureStorage.cs +++ b/src/Ryujinx.Graphics.Rdna3Vulkan/TextureStorage.cs @@ -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. 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) { diff --git a/src/Ryujinx.Graphics.Rdna3Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Rdna3Vulkan/VulkanRenderer.cs index 6ffe1f59b..4be2d7885 100644 --- a/src/Ryujinx.Graphics.Rdna3Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Rdna3Vulkan/VulkanRenderer.cs @@ -87,12 +87,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan internal Vendor Vendor { 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 IsSharedMemory { get; private set; } @@ -350,7 +344,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan Vendor = VendorUtils.FromId(properties.VendorID); IsAmdWindows = Vendor == Vendor.Amd && OperatingSystem.IsWindows(); - IsIntelWindows = Vendor == Vendor.Intel && OperatingSystem.IsWindows(); IsTBDR = Vendor == Vendor.Apple || Vendor == Vendor.Qualcomm || @@ -369,28 +362,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan 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( Math.Max( properties.Limits.MinStorageBufferOffsetAlignment, @@ -419,9 +390,9 @@ namespace Ryujinx.Graphics.Rdna3Vulkan features2.Features.ShaderStorageImageMultisample, _physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName), _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName), - features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue - featuresRobustness2.NullDescriptor || IsMoltenVk, - supportsPushDescriptors && !IsMoltenVk, + features2.Features.MultiViewport, // Workaround for AMD on MoltenVK issue + featuresRobustness2.NullDescriptor, + supportsPushDescriptors, propertiesPushDescriptor.MaxPushDescriptors, featuresPrimitiveTopologyListRestart.PrimitiveTopologyListRestart, featuresPrimitiveTopologyListRestart.PrimitiveTopologyPatchListRestart, @@ -450,7 +421,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExternalMemoryHost hostMemoryApi); 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(); @@ -728,10 +699,10 @@ namespace Ryujinx.Graphics.Rdna3Vulkan api: TargetApi.Vulkan, GpuVendor, memoryType: memoryType, - hasFrontFacingBug: IsIntelWindows, - hasVectorIndexingBug: IsQualcommProprietary, - needsFragmentOutputSpecialization: IsMoltenVk, - reduceShaderPrecision: IsMoltenVk, + hasFrontFacingBug: false, + hasVectorIndexingBug: false, + needsFragmentOutputSpecialization: false, + reduceShaderPrecision: false, supportsAstcCompression: features2.Features.TextureCompressionAstcLdr && supportsAstcFormats, supportsBc123Compression: supportsBc123CompressionFormat, supportsBc45Compression: supportsBc45CompressionFormat, @@ -754,14 +725,14 @@ namespace Ryujinx.Graphics.Rdna3Vulkan supportsImageLoadFormatted: features2.Features.ShaderStorageImageReadWithoutFormat, supportsLayerVertexTessellation: featuresVk12.ShaderOutputLayer, supportsMismatchingViewFormat: true, - supportsCubemapView: !IsAmdGcn, + supportsCubemapView: true, supportsNonConstantTextureOffset: false, supportsQuads: false, supportsSeparateSampler: true, supportsShaderBallot: false, supportsShaderBarrierDivergence: Vendor != Vendor.Intel, supportsShaderFloat64: Capabilities.SupportsShaderFloat64, - supportsTextureGatherOffsets: features2.Features.ShaderImageGatherExtended && !IsMoltenVk, + supportsTextureGatherOffsets: features2.Features.ShaderImageGatherExtended, supportsTextureShadowLod: false, supportsVertexStoreAndAtomics: features2.Features.VertexPipelineStoresAndAtomics, supportsViewportIndexVertexTessellation: featuresVk12.ShaderOutputViewportIndex, @@ -784,7 +755,7 @@ namespace Ryujinx.Graphics.Rdna3Vulkan shaderSubgroupSize: (int)Capabilities.SubgroupSize, storageBufferOffsetAlignment: (int)limits.MinStorageBufferOffsetAlignment, textureBufferOffsetAlignment: (int)limits.MinTexelBufferOffsetAlignment, - gatherBiasPrecision: IsIntelWindows || IsAmdWindows ? (int)Capabilities.SubTexelPrecisionBits : 0, + gatherBiasPrecision: IsAmdWindows ? (int)Capabilities.SubTexelPrecisionBits : 0, maximumGpuMemory: GetTotalGPUMemory()); } @@ -910,20 +881,14 @@ namespace Ryujinx.Graphics.Rdna3Vulkan return true; } - else if (Vendor != Vendor.Nvidia) - { - // 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. - // Guest applications do this, NVIDIA GPUs are OK with it, others are not. + + // 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. + // Guest applications do this, NVIDIA GPUs are OK with it, others are not. - alignment = attrScalarAlignment; + alignment = attrScalarAlignment; - return true; - } - - alignment = 1; - - return false; + return true; } public void PreFrame() @@ -1001,11 +966,6 @@ namespace Ryujinx.Graphics.Rdna3Vulkan ScreenCaptured?.Invoke(this, bitmap); } - public bool SupportsRenderPassBarrier(PipelineStageFlags flags) - { - return !(IsMoltenVk || IsQualcommProprietary); - } - public unsafe void Dispose() { if (!_initialized)