Separate new commands, some PR feedback

This commit is contained in:
Gabriel A 2024-05-25 18:05:49 -03:00
parent 91c977741e
commit 989709baf4
16 changed files with 221 additions and 213 deletions

View file

@ -60,7 +60,7 @@ namespace Ryujinx.Graphics.GAL
void SetImage(ShaderStage stage, int binding, ITexture texture, Format imageFormat);
void SetImageArray(ShaderStage stage, int binding, IImageArray array);
void SetImageArray(ShaderStage stage, int setIndex, int binding, IImageArray array);
void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array);
void SetLineParameters(float width, bool smooth);
@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.GAL
void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler);
void SetTextureArray(ShaderStage stage, int binding, ITextureArray array);
void SetTextureArray(ShaderStage stage, int setIndex, int binding, ITextureArray array);
void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array);
void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers);
void SetUniformBuffers(ReadOnlySpan<BufferAssignment> buffers);

View file

@ -124,6 +124,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
Register<SetUniformBuffersCommand>(CommandType.SetUniformBuffers);
Register<SetImageCommand>(CommandType.SetImage);
Register<SetImageArrayCommand>(CommandType.SetImageArray);
Register<SetImageArraySeparateCommand>(CommandType.SetImageArraySeparate);
Register<SetIndexBufferCommand>(CommandType.SetIndexBuffer);
Register<SetLineParametersCommand>(CommandType.SetLineParameters);
Register<SetLogicOpStateCommand>(CommandType.SetLogicOpState);
@ -141,6 +142,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
Register<SetStencilTestCommand>(CommandType.SetStencilTest);
Register<SetTextureAndSamplerCommand>(CommandType.SetTextureAndSampler);
Register<SetTextureArrayCommand>(CommandType.SetTextureArray);
Register<SetTextureArraySeparateCommand>(CommandType.SetTextureArraySeparate);
Register<SetUserClipDistanceCommand>(CommandType.SetUserClipDistance);
Register<SetVertexAttribsCommand>(CommandType.SetVertexAttribs);
Register<SetVertexBuffersCommand>(CommandType.SetVertexBuffers);

View file

@ -84,6 +84,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
SetUniformBuffers,
SetImage,
SetImageArray,
SetImageArraySeparate,
SetIndexBuffer,
SetLineParameters,
SetLogicOpState,
@ -101,6 +102,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
SetStencilTest,
SetTextureAndSampler,
SetTextureArray,
SetTextureArraySeparate,
SetUserClipDistance,
SetVertexAttribs,
SetVertexBuffers,

View file

@ -8,39 +8,19 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
public readonly CommandType CommandType => CommandType.SetImageArray;
private ShaderStage _stage;
private bool _hasSetIndex;
private int _setIndex;
private int _binding;
private TableRef<IImageArray> _array;
public void Set(ShaderStage stage, int binding, TableRef<IImageArray> array)
{
_stage = stage;
_hasSetIndex = false;
_setIndex = 0;
_binding = binding;
_array = array;
}
public void Set(ShaderStage stage, int setIndex, int binding, TableRef<IImageArray> array)
{
_stage = stage;
_hasSetIndex = true;
_setIndex = setIndex;
_binding = binding;
_array = array;
}
public static void Run(ref SetImageArrayCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
if (command._hasSetIndex)
{
renderer.Pipeline.SetImageArray(command._stage, command._setIndex, command._binding, command._array.GetAs<ThreadedImageArray>(threaded)?.Base);
}
else
{
renderer.Pipeline.SetImageArray(command._stage, command._binding, command._array.GetAs<ThreadedImageArray>(threaded)?.Base);
}
renderer.Pipeline.SetImageArray(command._stage, command._binding, command._array.GetAs<ThreadedImageArray>(threaded)?.Base);
}
}
}

View file

@ -0,0 +1,26 @@
using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources;
using Ryujinx.Graphics.Shader;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetImageArraySeparateCommand : IGALCommand, IGALCommand<SetImageArraySeparateCommand>
{
public readonly CommandType CommandType => CommandType.SetImageArraySeparate;
private ShaderStage _stage;
private int _setIndex;
private TableRef<IImageArray> _array;
public void Set(ShaderStage stage, int setIndex, TableRef<IImageArray> array)
{
_stage = stage;
_setIndex = setIndex;
_array = array;
}
public static void Run(ref SetImageArraySeparateCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
renderer.Pipeline.SetImageArraySeparate(command._stage, command._setIndex, command._array.GetAs<ThreadedImageArray>(threaded)?.Base);
}
}
}

View file

@ -8,39 +8,19 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
public readonly CommandType CommandType => CommandType.SetTextureArray;
private ShaderStage _stage;
private bool _hasSetIndex;
private int _setIndex;
private int _binding;
private TableRef<ITextureArray> _array;
public void Set(ShaderStage stage, int binding, TableRef<ITextureArray> array)
{
_stage = stage;
_hasSetIndex = false;
_setIndex = 0;
_binding = binding;
_array = array;
}
public void Set(ShaderStage stage, int setIndex, int binding, TableRef<ITextureArray> array)
{
_stage = stage;
_hasSetIndex = true;
_setIndex = setIndex;
_binding = binding;
_array = array;
}
public static void Run(ref SetTextureArrayCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
if (command._hasSetIndex)
{
renderer.Pipeline.SetTextureArray(command._stage, command._setIndex, command._binding, command._array.GetAs<ThreadedTextureArray>(threaded)?.Base);
}
else
{
renderer.Pipeline.SetTextureArray(command._stage, command._binding, command._array.GetAs<ThreadedTextureArray>(threaded)?.Base);
}
renderer.Pipeline.SetTextureArray(command._stage, command._binding, command._array.GetAs<ThreadedTextureArray>(threaded)?.Base);
}
}
}

View file

@ -0,0 +1,26 @@
using Ryujinx.Graphics.GAL.Multithreading.Model;
using Ryujinx.Graphics.GAL.Multithreading.Resources;
using Ryujinx.Graphics.Shader;
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
{
struct SetTextureArraySeparateCommand : IGALCommand, IGALCommand<SetTextureArraySeparateCommand>
{
public readonly CommandType CommandType => CommandType.SetTextureArraySeparate;
private ShaderStage _stage;
private int _setIndex;
private TableRef<ITextureArray> _array;
public void Set(ShaderStage stage, int setIndex, TableRef<ITextureArray> array)
{
_stage = stage;
_setIndex = setIndex;
_array = array;
}
public static void Run(ref SetTextureArraySeparateCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
renderer.Pipeline.SetTextureArraySeparate(command._stage, command._setIndex, command._array.GetAs<ThreadedTextureArray>(threaded)?.Base);
}
}
}

View file

@ -189,9 +189,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_renderer.QueueCommand();
}
public void SetImageArray(ShaderStage stage, int setIndex, int binding, IImageArray array)
public void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array)
{
_renderer.New<SetImageArrayCommand>().Set(stage, setIndex, binding, Ref(array));
_renderer.New<SetImageArraySeparateCommand>().Set(stage, setIndex, Ref(array));
_renderer.QueueCommand();
}
@ -303,9 +303,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_renderer.QueueCommand();
}
public void SetTextureArray(ShaderStage stage, int setIndex, int binding, ITextureArray array)
public void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array)
{
_renderer.New<SetTextureArrayCommand>().Set(stage, setIndex, binding, Ref(array));
_renderer.New<SetTextureArraySeparateCommand>().Set(stage, setIndex, Ref(array));
_renderer.QueueCommand();
}

View file

@ -961,11 +961,17 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
/// <summary>
/// Updates a texture array binding on the host.
/// </summary>
/// <param name="stage">Shader stage where the array is used</param>
/// <param name="bindingInfo">Array binding information</param>
/// <param name="array">Texture array</param>
private void SetTextureArray(ShaderStage stage, in TextureBindingInfo bindingInfo, ITextureArray array)
{
if (bindingInfo.Set >= _context.Capabilities.ExtraSetBaseIndex)
{
_context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Set, bindingInfo.Binding, array);
_context.Renderer.Pipeline.SetTextureArraySeparate(stage, bindingInfo.Set, array);
}
else
{
@ -973,11 +979,17 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
/// <summary>
/// Updates a image array binding on the host.
/// </summary>
/// <param name="stage">Shader stage where the array is used</param>
/// <param name="bindingInfo">Array binding information</param>
/// <param name="array">Image array</param>
private void SetImageArray(ShaderStage stage, in TextureBindingInfo bindingInfo, IImageArray array)
{
if (bindingInfo.Set >= _context.Capabilities.ExtraSetBaseIndex)
{
_context.Renderer.Pipeline.SetImageArray(stage, bindingInfo.Set, bindingInfo.Binding, array);
_context.Renderer.Pipeline.SetImageArraySeparate(stage, bindingInfo.Set, array);
}
else
{

View file

@ -10,13 +10,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
class ShaderInfoBuilder
{
private const int TotalSets = 4;
private const int UniformSetIndex = 0;
private const int StorageSetIndex = 1;
private const int TextureSetIndex = 2;
private const int ImageSetIndex = 3;
private const ResourceStages SupportBufferStages =
ResourceStages.Compute |
ResourceStages.Vertex |
@ -52,17 +45,27 @@ namespace Ryujinx.Graphics.Gpu.Shader
_fragmentOutputMap = -1;
_resourceDescriptors = new List<ResourceDescriptor>[TotalSets];
_resourceUsages = new List<ResourceUsage>[TotalSets];
int uniformSetIndex = context.Capabilities.UniformBufferSetIndex;
int storageSetIndex = context.Capabilities.StorageBufferSetIndex;
int textureSetIndex = context.Capabilities.TextureSetIndex;
int imageSetIndex = context.Capabilities.ImageSetIndex;
for (int index = 0; index < TotalSets; index++)
int totalSets = Math.Max(uniformSetIndex, storageSetIndex);
totalSets = Math.Max(totalSets, textureSetIndex);
totalSets = Math.Max(totalSets, imageSetIndex);
totalSets++;
_resourceDescriptors = new List<ResourceDescriptor>[totalSets];
_resourceUsages = new List<ResourceUsage>[totalSets];
for (int index = 0; index < totalSets; index++)
{
_resourceDescriptors[index] = new();
_resourceUsages[index] = new();
}
AddDescriptor(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1);
AddUsage(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1);
AddDescriptor(SupportBufferStages, ResourceType.UniformBuffer, uniformSetIndex, 0, 1);
AddUsage(SupportBufferStages, ResourceType.UniformBuffer, uniformSetIndex, 0, 1);
ResourceReservationCounts rrc = new(!context.Capabilities.SupportsTransformFeedback && tfEnabled, vertexAsCompute);
@ -74,12 +77,20 @@ namespace Ryujinx.Graphics.Gpu.Shader
// TODO: Handle that better? Maybe we should only set the binding that are really needed on each shader.
ResourceStages stages = vertexAsCompute ? ResourceStages.Compute | ResourceStages.Vertex : VtgStages;
PopulateDescriptorAndUsages(stages, ResourceType.UniformBuffer, UniformSetIndex, 1, rrc.ReservedConstantBuffers - 1);
PopulateDescriptorAndUsages(stages, ResourceType.StorageBuffer, StorageSetIndex, 0, rrc.ReservedStorageBuffers);
PopulateDescriptorAndUsages(stages, ResourceType.BufferTexture, TextureSetIndex, 0, rrc.ReservedTextures);
PopulateDescriptorAndUsages(stages, ResourceType.BufferImage, ImageSetIndex, 0, rrc.ReservedImages);
PopulateDescriptorAndUsages(stages, ResourceType.UniformBuffer, uniformSetIndex, 1, rrc.ReservedConstantBuffers - 1);
PopulateDescriptorAndUsages(stages, ResourceType.StorageBuffer, storageSetIndex, 0, rrc.ReservedStorageBuffers);
PopulateDescriptorAndUsages(stages, ResourceType.BufferTexture, textureSetIndex, 0, rrc.ReservedTextures);
PopulateDescriptorAndUsages(stages, ResourceType.BufferImage, imageSetIndex, 0, rrc.ReservedImages);
}
/// <summary>
/// Populates descriptors and usages for vertex as compute and transform feedback emulation reserved resources.
/// </summary>
/// <param name="stages">Shader stages where the resources are used</param>
/// <param name="type">Resource type</param>
/// <param name="setIndex">Resource set index where the resources are used</param>
/// <param name="start">First binding number</param>
/// <param name="count">Amount of bindings</param>
private void PopulateDescriptorAndUsages(ResourceStages stages, ResourceType type, int setIndex, int start, int count)
{
AddDescriptor(stages, type, setIndex, start, count);
@ -128,10 +139,15 @@ namespace Ryujinx.Graphics.Gpu.Shader
int textureBinding = _reservedTextures + stageIndex * texturesPerStage * 2;
int imageBinding = _reservedImages + stageIndex * imagesPerStage * 2;
AddDescriptor(stages, ResourceType.UniformBuffer, UniformSetIndex, uniformBinding, uniformsPerStage);
AddDescriptor(stages, ResourceType.StorageBuffer, StorageSetIndex, storageBinding, storagesPerStage);
AddDualDescriptor(stages, ResourceType.TextureAndSampler, ResourceType.BufferTexture, TextureSetIndex, textureBinding, texturesPerStage);
AddDualDescriptor(stages, ResourceType.Image, ResourceType.BufferImage, ImageSetIndex, imageBinding, imagesPerStage);
int uniformSetIndex = _context.Capabilities.UniformBufferSetIndex;
int storageSetIndex = _context.Capabilities.StorageBufferSetIndex;
int textureSetIndex = _context.Capabilities.TextureSetIndex;
int imageSetIndex = _context.Capabilities.ImageSetIndex;
AddDescriptor(stages, ResourceType.UniformBuffer, uniformSetIndex, uniformBinding, uniformsPerStage);
AddDescriptor(stages, ResourceType.StorageBuffer, storageSetIndex, storageBinding, storagesPerStage);
AddDualDescriptor(stages, ResourceType.TextureAndSampler, ResourceType.BufferTexture, textureSetIndex, textureBinding, texturesPerStage);
AddDualDescriptor(stages, ResourceType.Image, ResourceType.BufferImage, imageSetIndex, imageBinding, imagesPerStage);
AddArrayDescriptors(info.Textures, stages, isImage: false);
AddArrayDescriptors(info.Images, stages, isImage: true);
@ -242,6 +258,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
}
/// <summary>
/// Gets the list of resource descriptors for a given set index. A new list will be created if needed.
/// </summary>
/// <param name="setIndex">Resource set index</param>
/// <returns>List of resource descriptors</returns>
private List<ResourceDescriptor> GetDescriptors(int setIndex)
{
if (_resourceDescriptors.Length <= setIndex)
@ -258,6 +279,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
return _resourceDescriptors[setIndex];
}
/// <summary>
/// Gets the list of resource usages for a given set index. A new list will be created if needed.
/// </summary>
/// <param name="setIndex">Resource set index</param>
/// <returns>List of resource usages</returns>
private List<ResourceUsage> GetUsages(int setIndex)
{
if (_resourceUsages.Length <= setIndex)
@ -274,6 +300,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
return _resourceUsages[setIndex];
}
/// <summary>
/// Gets a resource type from a texture descriptor.
/// </summary>
/// <param name="texture">Texture descriptor</param>
/// <param name="isImage">Whether the texture is a image texture (writable) or not (sampled)</param>
/// <returns>Resource type</returns>
private static ResourceType GetTextureResourceType(TextureDescriptor texture, bool isImage)
{
bool isBuffer = (texture.Type & SamplerType.Mask) == SamplerType.TextureBuffer;

View file

@ -963,7 +963,7 @@ namespace Ryujinx.Graphics.OpenGL
(array as ImageArray).Bind(binding);
}
public void SetImageArray(ShaderStage stage, int setIndex, int binding, IImageArray array)
public void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array)
{
throw new NotSupportedException("OpenGL does not support descriptor sets.");
}
@ -1317,7 +1317,7 @@ namespace Ryujinx.Graphics.OpenGL
(array as TextureArray).Bind(binding);
}
public void SetTextureArray(ShaderStage stage, int setIndex, int binding, ITextureArray array)
public void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array)
{
throw new NotSupportedException("OpenGL does not support descriptor sets.");
}

View file

@ -1,41 +1,4 @@
using System;
namespace Ryujinx.Graphics.Shader
{
public readonly struct SetBindingPair : IEquatable<SetBindingPair>
{
public readonly int SetIndex;
public readonly int Binding;
public SetBindingPair(int setIndex, int binding)
{
SetIndex = setIndex;
Binding = binding;
}
public override bool Equals(object obj)
{
return obj is SetBindingPair other && Equals(other);
}
public bool Equals(SetBindingPair other)
{
return SetIndex == other.SetIndex && Binding == other.Binding;
}
public override int GetHashCode()
{
return (((ulong)(uint)SetIndex << 32) | (uint)Binding).GetHashCode();
}
public static bool operator ==(SetBindingPair left, SetBindingPair right)
{
return left.Equals(right);
}
public static bool operator !=(SetBindingPair left, SetBindingPair right)
{
return !(left == right);
}
}
public readonly record struct SetBindingPair(int SetIndex, int Binding);
}

View file

@ -69,31 +69,7 @@ namespace Ryujinx.Graphics.Vulkan
}
}
private record struct ArrayRef<T>
{
public ShaderStage Stage;
public T Array;
public ArrayRef(ShaderStage stage, T array)
{
Stage = stage;
Array = array;
}
}
private record struct ArrayExtraRef<T>
{
public ShaderStage Stage;
public T Array;
public int Binding;
public ArrayExtraRef(ShaderStage stage, T array, int binding)
{
Stage = stage;
Array = array;
Binding = binding;
}
}
private readonly record struct ArrayRef<T>(ShaderStage Stage, T Array);
private readonly VulkanRenderer _gd;
private readonly Device _device;
@ -111,8 +87,8 @@ namespace Ryujinx.Graphics.Vulkan
private ArrayRef<TextureArray>[] _textureArrayRefs;
private ArrayRef<ImageArray>[] _imageArrayRefs;
private ArrayExtraRef<TextureArray>[] _textureArrayExtraRefs;
private ArrayExtraRef<ImageArray>[] _imageArrayExtraRefs;
private ArrayRef<TextureArray>[] _textureArrayExtraRefs;
private ArrayRef<ImageArray>[] _imageArrayExtraRefs;
private readonly DescriptorBufferInfo[] _uniformBuffers;
private readonly DescriptorBufferInfo[] _storageBuffers;
@ -169,8 +145,8 @@ namespace Ryujinx.Graphics.Vulkan
_textureArrayRefs = Array.Empty<ArrayRef<TextureArray>>();
_imageArrayRefs = Array.Empty<ArrayRef<ImageArray>>();
_textureArrayExtraRefs = Array.Empty<ArrayExtraRef<TextureArray>>();
_imageArrayExtraRefs = Array.Empty<ArrayExtraRef<ImageArray>>();
_textureArrayExtraRefs = Array.Empty<ArrayRef<TextureArray>>();
_imageArrayExtraRefs = Array.Empty<ArrayRef<ImageArray>>();
_uniformBuffers = new DescriptorBufferInfo[Constants.MaxUniformBufferBindings];
_storageBuffers = new DescriptorBufferInfo[Constants.MaxStorageBufferBindings];
@ -515,48 +491,39 @@ namespace Ryujinx.Graphics.Vulkan
public void SetTextureArray(CommandBufferScoped cbs, ShaderStage stage, int binding, ITextureArray array)
{
if (_textureArrayRefs.Length <= binding)
{
Array.Resize(ref _textureArrayRefs, binding + ArrayGrowthSize);
}
ref ArrayRef<TextureArray> arrayRef = ref GetArrayRef(ref _textureArrayRefs, binding, ArrayGrowthSize);
if (_textureArrayRefs[binding].Stage != stage || _textureArrayRefs[binding].Array != array)
if (arrayRef.Stage != stage || arrayRef.Array != array)
{
if (_textureArrayRefs[binding].Array != null)
{
_textureArrayRefs[binding].Array.Bound = false;
}
arrayRef.Array?.DecrementBindCount();
if (array is TextureArray textureArray)
{
textureArray.Bound = true;
textureArray.IncrementBindCount();
textureArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
}
_textureArrayRefs[binding] = new ArrayRef<TextureArray>(stage, array as TextureArray);
arrayRef = new ArrayRef<TextureArray>(stage, array as TextureArray);
SignalDirty(DirtyFlags.Texture);
}
}
public void SetTextureArray(CommandBufferScoped cbs, ShaderStage stage, int setIndex, int binding, ITextureArray array)
public void SetTextureArraySeparate(CommandBufferScoped cbs, ShaderStage stage, int setIndex, ITextureArray array)
{
ref ArrayExtraRef<TextureArray> arrayRef = ref GetExtraArrayRef(ref _textureArrayExtraRefs, setIndex, binding);
ref ArrayRef<TextureArray> arrayRef = ref GetArrayRef(ref _textureArrayExtraRefs, setIndex - PipelineBase.DescriptorSetLayouts);
if (arrayRef.Stage != stage || arrayRef.Array != array)
{
if (arrayRef.Array != null)
{
arrayRef.Array.Bound = false;
}
arrayRef.Array?.DecrementBindCount();
if (array is TextureArray textureArray)
{
textureArray.Bound = true;
textureArray.IncrementBindCount();
textureArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
}
arrayRef = new ArrayExtraRef<TextureArray>(stage, array as TextureArray, binding);
arrayRef = new ArrayRef<TextureArray>(stage, array as TextureArray);
SignalDirty(DirtyFlags.Texture);
}
@ -564,66 +531,54 @@ namespace Ryujinx.Graphics.Vulkan
public void SetImageArray(CommandBufferScoped cbs, ShaderStage stage, int binding, IImageArray array)
{
if (_imageArrayRefs.Length <= binding)
{
Array.Resize(ref _imageArrayRefs, binding + ArrayGrowthSize);
}
if (_imageArrayRefs[binding].Stage != stage || _imageArrayRefs[binding].Array != array)
{
if (_imageArrayRefs[binding].Array != null)
{
_imageArrayRefs[binding].Array.Bound = false;
}
if (array is ImageArray imageArray)
{
imageArray.Bound = true;
imageArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
}
_imageArrayRefs[binding] = new ArrayRef<ImageArray>(stage, array as ImageArray);
SignalDirty(DirtyFlags.Image);
}
}
public void SetImageArray(CommandBufferScoped cbs, ShaderStage stage, int setIndex, int binding, IImageArray array)
{
ref ArrayExtraRef<ImageArray> arrayRef = ref GetExtraArrayRef(ref _imageArrayExtraRefs, setIndex, binding);
ref ArrayRef<ImageArray> arrayRef = ref GetArrayRef(ref _imageArrayRefs, binding, ArrayGrowthSize);
if (arrayRef.Stage != stage || arrayRef.Array != array)
{
if (arrayRef.Array != null)
{
arrayRef.Array.Bound = false;
}
arrayRef.Array?.DecrementBindCount();
if (array is ImageArray imageArray)
{
imageArray.Bound = true;
imageArray.IncrementBindCount();
imageArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
}
arrayRef = new ArrayExtraRef<ImageArray>(stage, array as ImageArray, binding);
arrayRef = new ArrayRef<ImageArray>(stage, array as ImageArray);
SignalDirty(DirtyFlags.Image);
}
}
private static ref ArrayExtraRef<T> GetExtraArrayRef<T>(ref ArrayExtraRef<T>[] array, int setIndex, int binding)
public void SetImageArraySeparate(CommandBufferScoped cbs, ShaderStage stage, int setIndex, IImageArray array)
{
setIndex -= PipelineBase.DescriptorSetLayouts;
ref ArrayRef<ImageArray> arrayRef = ref GetArrayRef(ref _imageArrayExtraRefs, setIndex - PipelineBase.DescriptorSetLayouts);
ArgumentOutOfRangeException.ThrowIfNegative(setIndex);
ArgumentOutOfRangeException.ThrowIfNegative(binding);
if (array.Length <= setIndex)
if (arrayRef.Stage != stage || arrayRef.Array != array)
{
Array.Resize(ref array, setIndex + 1);
arrayRef.Array?.DecrementBindCount();
if (array is ImageArray imageArray)
{
imageArray.IncrementBindCount();
imageArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
}
arrayRef = new ArrayRef<ImageArray>(stage, array as ImageArray);
SignalDirty(DirtyFlags.Image);
}
}
private static ref ArrayRef<T> GetArrayRef<T>(ref ArrayRef<T>[] array, int index, int growthSize = 1)
{
ArgumentOutOfRangeException.ThrowIfNegative(index);
if (array.Length <= index)
{
Array.Resize(ref array, index + growthSize);
}
return ref array[setIndex];
return ref array[index];
}
public void SetUniformBuffers(CommandBuffer commandBuffer, ReadOnlySpan<BufferAssignment> buffers)

View file

@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Vulkan
private readonly bool _isBuffer;
public bool Bound;
private int _bindCount;
public ImageArray(VulkanRenderer gd, int size, bool isBuffer)
{
@ -101,7 +101,10 @@ namespace Ryujinx.Graphics.Vulkan
_storages = null;
_cachedDescriptorSets = null;
_gd.PipelineInternal.ForceImageDirty();
if (_bindCount != 0)
{
_gd.PipelineInternal.ForceImageDirty();
}
}
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
@ -225,5 +228,20 @@ namespace Ryujinx.Graphics.Vulkan
return sets;
}
public void IncrementBindCount()
{
_bindCount++;
}
public void DecrementBindCount()
{
int newBindCount = --_bindCount;
if (newBindCount < 0)
{
throw new Exception("huh?");
}
}
}
}

View file

@ -751,14 +751,12 @@ namespace Ryujinx.Graphics.Vulkan
_vertexBufferUpdater.Commit(Cbs);
}
#pragma warning disable CA1822 // Mark member as static
public void SetAlphaTest(bool enable, float reference, CompareOp op)
{
// This is currently handled using shader specialization, as Vulkan does not support alpha test.
// In the future, we may want to use this to write the reference value into the support buffer,
// to avoid creating one version of the shader per reference value used.
}
#pragma warning restore CA1822
public void SetBlendState(AdvancedBlendDescriptor blend)
{
@ -903,9 +901,9 @@ namespace Ryujinx.Graphics.Vulkan
_descriptorSetUpdater.SetImageArray(Cbs, stage, binding, array);
}
public void SetImageArray(ShaderStage stage, int setIndex, int binding, IImageArray array)
public void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array)
{
_descriptorSetUpdater.SetImageArray(Cbs, stage, setIndex, binding, array);
_descriptorSetUpdater.SetImageArraySeparate(Cbs, stage, setIndex, array);
}
public void SetIndexBuffer(BufferRange buffer, IndexType type)
@ -950,7 +948,6 @@ namespace Ryujinx.Graphics.Vulkan
// TODO: Default levels (likely needs emulation on shaders?)
}
#pragma warning disable CA1822 // Mark member as static
public void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin)
{
// TODO.
@ -960,7 +957,6 @@ namespace Ryujinx.Graphics.Vulkan
{
// TODO.
}
#pragma warning restore CA1822
public void SetPrimitiveRestart(bool enable, int index)
{
@ -1161,9 +1157,9 @@ namespace Ryujinx.Graphics.Vulkan
_descriptorSetUpdater.SetTextureArray(Cbs, stage, binding, array);
}
public void SetTextureArray(ShaderStage stage, int setIndex, int binding, ITextureArray array)
public void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array)
{
_descriptorSetUpdater.SetTextureArray(Cbs, stage, setIndex, binding, array);
_descriptorSetUpdater.SetTextureArraySeparate(Cbs, stage, setIndex, array);
}
public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
@ -1196,12 +1192,10 @@ namespace Ryujinx.Graphics.Vulkan
_descriptorSetUpdater.SetUniformBuffers(CommandBuffer, buffers);
}
#pragma warning disable CA1822 // Mark member as static
public void SetUserClipDistance(int index, bool enableClip)
{
// TODO.
}
#pragma warning restore CA1822
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
{

View file

@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Vulkan
private readonly bool _isBuffer;
public bool Bound;
private int _bindCount;
public TextureArray(VulkanRenderer gd, int size, bool isBuffer)
{
@ -110,7 +110,10 @@ namespace Ryujinx.Graphics.Vulkan
_storages = null;
_cachedDescriptorSets = null;
_gd.PipelineInternal.ForceTextureDirty();
if (_bindCount != 0)
{
_gd.PipelineInternal.ForceTextureDirty();
}
}
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
@ -241,5 +244,20 @@ namespace Ryujinx.Graphics.Vulkan
return sets;
}
public void IncrementBindCount()
{
_bindCount++;
}
public void DecrementBindCount()
{
int newBindCount = --_bindCount;
if (newBindCount < 0)
{
throw new Exception("huh?");
}
}
}
}