Skip to content

Commit

Permalink
Vulkan separate descriptor set fixes (#6895)
Browse files Browse the repository at this point in the history
* Ensure descriptor sets are only re-used when all command buffers using it have completed

* Fix some SPIR-V capabilities

* Set update after bind flag if we exceed limits

* Simpler fix for Intel

* Format whitespace

* Make struct readonly

* Add barriers for extra set arrays too
  • Loading branch information
gdkchan authored Jun 3, 2024
1 parent d7c6474 commit c0f2491
Show file tree
Hide file tree
Showing 24 changed files with 365 additions and 113 deletions.
4 changes: 3 additions & 1 deletion src/Ryujinx.Graphics.GAL/IImageArray.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;

namespace Ryujinx.Graphics.GAL
{
public interface IImageArray
public interface IImageArray : IDisposable
{
void SetFormats(int index, Format[] imageFormats);
void SetImages(int index, ITexture[] images);
Expand Down
4 changes: 3 additions & 1 deletion src/Ryujinx.Graphics.GAL/ITextureArray.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;

namespace Ryujinx.Graphics.GAL
{
public interface ITextureArray
public interface ITextureArray : IDisposable
{
void SetSamplers(int index, ISampler[] samplers);
void SetTextures(int index, ITexture[] textures);
Expand Down
2 changes: 2 additions & 0 deletions src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ void Register<T>(CommandType commandType) where T : unmanaged, IGALCommand, IGAL
Register<CounterEventDisposeCommand>(CommandType.CounterEventDispose);
Register<CounterEventFlushCommand>(CommandType.CounterEventFlush);

Register<ImageArrayDisposeCommand>(CommandType.ImageArrayDispose);
Register<ImageArraySetFormatsCommand>(CommandType.ImageArraySetFormats);
Register<ImageArraySetImagesCommand>(CommandType.ImageArraySetImages);

Expand All @@ -88,6 +89,7 @@ void Register<T>(CommandType commandType) where T : unmanaged, IGALCommand, IGAL
Register<TextureSetDataSliceRegionCommand>(CommandType.TextureSetDataSliceRegion);
Register<TextureSetStorageCommand>(CommandType.TextureSetStorage);

Register<TextureArrayDisposeCommand>(CommandType.TextureArrayDispose);
Register<TextureArraySetSamplersCommand>(CommandType.TextureArraySetSamplers);
Register<TextureArraySetTexturesCommand>(CommandType.TextureArraySetTextures);

Expand Down
2 changes: 2 additions & 0 deletions src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum CommandType : byte
CounterEventDispose,
CounterEventFlush,

ImageArrayDispose,
ImageArraySetFormats,
ImageArraySetImages,

Expand All @@ -48,6 +49,7 @@ enum CommandType : byte
TextureSetDataSliceRegion,
TextureSetStorage,

TextureArrayDispose,
TextureArraySetSamplers,
TextureArraySetTextures,

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources;

namespace Ryujinx.Graphics.GAL.Multithreading.Commands.ImageArray
{
struct ImageArrayDisposeCommand : IGALCommand, IGALCommand<ImageArrayDisposeCommand>
{
public readonly CommandType CommandType => CommandType.ImageArrayDispose;
private TableRef<ThreadedImageArray> _imageArray;

public void Set(TableRef<ThreadedImageArray> imageArray)
{
_imageArray = imageArray;
}

public static void Run(ref ImageArrayDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
command._imageArray.Get(threaded).Base.Dispose();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources;

namespace Ryujinx.Graphics.GAL.Multithreading.Commands.TextureArray
{
struct TextureArrayDisposeCommand : IGALCommand, IGALCommand<TextureArrayDisposeCommand>
{
public readonly CommandType CommandType => CommandType.TextureArrayDispose;
private TableRef<ThreadedTextureArray> _textureArray;

public void Set(TableRef<ThreadedTextureArray> textureArray)
{
_textureArray = textureArray;
}

public static void Run(ref TextureArrayDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
command._textureArray.Get(threaded).Base.Dispose();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ private TableRef<T> Ref<T>(T reference)
return new TableRef<T>(_renderer, reference);
}

public void Dispose()
{
_renderer.New<ImageArrayDisposeCommand>().Set(Ref(this));
_renderer.QueueCommand();
}

public void SetFormats(int index, Format[] imageFormats)
{
_renderer.New<ImageArraySetFormatsCommand>().Set(Ref(this), index, Ref(imageFormats));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ private TableRef<T> Ref<T>(T reference)
return new TableRef<T>(_renderer, reference);
}

public void Dispose()
{
_renderer.New<TextureArrayDisposeCommand>().Set(Ref(this));
_renderer.QueueCommand();
}

public void SetSamplers(int index, ISampler[] samplers)
{
_renderer.New<TextureArraySetSamplersCommand>().Set(Ref(this), index, Ref(samplers.ToArray()));
Expand Down
20 changes: 19 additions & 1 deletion src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,15 @@ private void RemoveLeastUsedEntries()
nextNode = nextNode.Next;
_cacheFromBuffer.Remove(toRemove.Value.Key);
_lruCache.Remove(toRemove);

if (toRemove.Value.Key.IsImage)
{
toRemove.Value.ImageArray.Dispose();
}
else
{
toRemove.Value.TextureArray.Dispose();
}
}
}

Expand All @@ -1124,11 +1133,20 @@ public void RemoveAllWithPool<T>(IPool<T> pool)
{
List<CacheEntryFromPoolKey> keysToRemove = null;

foreach (CacheEntryFromPoolKey key in _cacheFromPool.Keys)
foreach ((CacheEntryFromPoolKey key, CacheEntry entry) in _cacheFromPool)
{
if (key.MatchesPool(pool))
{
(keysToRemove ??= new()).Add(key);

if (key.IsImage)
{
entry.ImageArray.Dispose();
}
else
{
entry.TextureArray.Dispose();
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/Ryujinx.Graphics.OpenGL/Image/ImageArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,9 @@ public void Bind(int baseBinding)
}
}
}

public void Dispose()
{
}
}
}
4 changes: 4 additions & 0 deletions src/Ryujinx.Graphics.OpenGL/Image/TextureArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,9 @@ public void Bind(int baseBinding)
}
}
}

public void Dispose()
{
}
}
}
5 changes: 0 additions & 5 deletions src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,6 @@ public CodeGenContext(
Logger = parameters.Logger;
TargetApi = parameters.TargetApi;

AddCapability(Capability.Shader);
AddCapability(Capability.Float64);

SetMemoryModel(AddressingModel.Logical, MemoryModel.GLSL450);

Delegates = new SpirvDelegates(this);
}

Expand Down
12 changes: 11 additions & 1 deletion src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public static byte[] Generate(StructuredProgramInfo info, CodeGenParameters para

CodeGenContext context = new(info, parameters, instPool, integerPool);

context.AddCapability(Capability.Shader);

context.SetMemoryModel(AddressingModel.Logical, MemoryModel.GLSL450);

context.AddCapability(Capability.GroupNonUniformBallot);
context.AddCapability(Capability.GroupNonUniformShuffle);
context.AddCapability(Capability.GroupNonUniformVote);
Expand All @@ -51,14 +55,20 @@ public static byte[] Generate(StructuredProgramInfo info, CodeGenParameters para
context.AddCapability(Capability.ImageQuery);
context.AddCapability(Capability.SampledBuffer);

if (parameters.HostCapabilities.SupportsShaderFloat64)
{
context.AddCapability(Capability.Float64);
}

if (parameters.Definitions.TransformFeedbackEnabled && parameters.Definitions.LastInVertexPipeline)
{
context.AddCapability(Capability.TransformFeedback);
}

if (parameters.Definitions.Stage == ShaderStage.Fragment)
{
if (context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Input, IoVariable.Layer)))
if (context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Input, IoVariable.Layer)) ||
context.Info.IoDefinitions.Contains(new IoDefinition(StorageKind.Input, IoVariable.PrimitiveId)))
{
context.AddCapability(Capability.Geometry);
}
Expand Down
3 changes: 3 additions & 0 deletions src/Ryujinx.Graphics.Shader/Translation/HostCapabilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class HostCapabilities
public readonly bool SupportsGeometryShaderPassthrough;
public readonly bool SupportsShaderBallot;
public readonly bool SupportsShaderBarrierDivergence;
public readonly bool SupportsShaderFloat64;
public readonly bool SupportsTextureShadowLod;
public readonly bool SupportsViewportMask;

Expand All @@ -18,6 +19,7 @@ public HostCapabilities(
bool supportsGeometryShaderPassthrough,
bool supportsShaderBallot,
bool supportsShaderBarrierDivergence,
bool supportsShaderFloat64,
bool supportsTextureShadowLod,
bool supportsViewportMask)
{
Expand All @@ -27,6 +29,7 @@ public HostCapabilities(
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
SupportsShaderBallot = supportsShaderBallot;
SupportsShaderBarrierDivergence = supportsShaderBarrierDivergence;
SupportsShaderFloat64 = supportsShaderFloat64;
SupportsTextureShadowLod = supportsTextureShadowLod;
SupportsViewportMask = supportsViewportMask;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ private ShaderProgram Generate(
GpuAccessor.QueryHostSupportsGeometryShaderPassthrough(),
GpuAccessor.QueryHostSupportsShaderBallot(),
GpuAccessor.QueryHostSupportsShaderBarrierDivergence(),
GpuAccessor.QueryHostSupportsShaderFloat64(),
GpuAccessor.QueryHostSupportsTextureShadowLod(),
GpuAccessor.QueryHostSupportsViewportMask());

Expand Down
41 changes: 37 additions & 4 deletions src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,9 @@ public void InsertBindingBarriers(CommandBufferScoped cbs)
}
else
{
PipelineStageFlags stageFlags = _textureArrayRefs[segment.Binding].Stage.ConvertToPipelineStageFlags();
_textureArrayRefs[segment.Binding].Array?.QueueWriteToReadBarriers(cbs, stageFlags);
ref var arrayRef = ref _textureArrayRefs[segment.Binding];
PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags();
arrayRef.Array?.QueueWriteToReadBarriers(cbs, stageFlags);
}
}
}
Expand All @@ -311,8 +312,40 @@ public void InsertBindingBarriers(CommandBufferScoped cbs)
}
else
{
PipelineStageFlags stageFlags = _imageArrayRefs[segment.Binding].Stage.ConvertToPipelineStageFlags();
_imageArrayRefs[segment.Binding].Array?.QueueWriteToReadBarriers(cbs, stageFlags);
ref var arrayRef = ref _imageArrayRefs[segment.Binding];
PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags();
arrayRef.Array?.QueueWriteToReadBarriers(cbs, stageFlags);
}
}
}

for (int setIndex = PipelineBase.DescriptorSetLayouts; setIndex < _program.BindingSegments.Length; setIndex++)
{
var bindingSegments = _program.BindingSegments[setIndex];

if (bindingSegments.Length == 0)
{
continue;
}

ResourceBindingSegment segment = bindingSegments[0];

if (segment.IsArray)
{
if (segment.Type == ResourceType.Texture ||
segment.Type == ResourceType.Sampler ||
segment.Type == ResourceType.TextureAndSampler ||
segment.Type == ResourceType.BufferTexture)
{
ref var arrayRef = ref _textureArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts];
PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags();
arrayRef.Array?.QueueWriteToReadBarriers(cbs, stageFlags);
}
else if (segment.Type == ResourceType.Image || segment.Type == ResourceType.BufferImage)
{
ref var arrayRef = ref _imageArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts];
PipelineStageFlags stageFlags = arrayRef.Stage.ConvertToPipelineStageFlags();
arrayRef.Array?.QueueWriteToReadBarriers(cbs, stageFlags);
}
}
}
Expand Down
Loading

0 comments on commit c0f2491

Please sign in to comment.