Vulkan: Partially workaround MoltenVK InvalidResource error (#4880)

* Add MVK stage flags workaround

* Actually do the workaround

* Remove GS on VS stuff

* Address feedback
This commit is contained in:
riperiperi 2023-05-12 02:06:15 +01:00 committed by GitHub
parent 95c06de4c1
commit 5fda543f84
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -12,6 +12,28 @@ namespace Ryujinx.Graphics.Vulkan
ShaderStageFlags.FragmentBit | ShaderStageFlags.FragmentBit |
ShaderStageFlags.ComputeBit; ShaderStageFlags.ComputeBit;
private static ShaderStageFlags ActiveStages(uint stages)
{
ShaderStageFlags stageFlags = 0;
while (stages != 0)
{
int stage = BitOperations.TrailingZeroCount(stages);
stages &= ~(1u << stage);
stageFlags |= stage switch
{
1 => ShaderStageFlags.FragmentBit,
2 => ShaderStageFlags.GeometryBit,
3 => ShaderStageFlags.TessellationControlBit,
4 => ShaderStageFlags.TessellationEvaluationBit,
_ => ShaderStageFlags.VertexBit | ShaderStageFlags.ComputeBit
};
}
return stageFlags;
}
public static unsafe DescriptorSetLayout[] Create(VulkanRenderer gd, Device device, uint stages, bool usePd, out PipelineLayout layout) public static unsafe DescriptorSetLayout[] Create(VulkanRenderer gd, Device device, uint stages, bool usePd, out PipelineLayout layout)
{ {
int stagesCount = BitOperations.PopCount(stages); int stagesCount = BitOperations.PopCount(stages);
@ -34,6 +56,7 @@ namespace Ryujinx.Graphics.Vulkan
}; };
int iter = 0; int iter = 0;
var activeStages = ActiveStages(stages);
while (stages != 0) while (stages != 0)
{ {
@ -67,12 +90,16 @@ namespace Ryujinx.Graphics.Vulkan
void SetStorage(DescriptorSetLayoutBinding* bindings, int maxPerStage, int start = 0) void SetStorage(DescriptorSetLayoutBinding* bindings, int maxPerStage, int start = 0)
{ {
// 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.
var flags = gd.IsMoltenVk ? activeStages : stageFlags;
bindings[start + iter] = new DescriptorSetLayoutBinding bindings[start + iter] = new DescriptorSetLayoutBinding
{ {
Binding = (uint)(start + stage * maxPerStage), Binding = (uint)(start + stage * maxPerStage),
DescriptorType = DescriptorType.StorageBuffer, DescriptorType = DescriptorType.StorageBuffer,
DescriptorCount = (uint)maxPerStage, DescriptorCount = (uint)maxPerStage,
StageFlags = stageFlags StageFlags = flags
}; };
} }