Separate new commands, some PR feedback
This commit is contained in:
parent
91c977741e
commit
989709baf4
16 changed files with 221 additions and 213 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue