Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vulkan: Partially workaround MoltenVK InvalidResource error #4880

Merged
merged 4 commits into from
May 12, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 28 additions & 1 deletion src/Ryujinx.Graphics.Vulkan/PipelineLayoutFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,28 @@ static class PipelineLayoutFactory
ShaderStageFlags.FragmentBit |
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)
{
int stagesCount = BitOperations.PopCount(stages);
Expand All @@ -34,6 +56,7 @@ public static unsafe DescriptorSetLayout[] Create(VulkanRenderer gd, Device devi
};

int iter = 0;
var activeStages = ActiveStages(stages);

while (stages != 0)
{
Expand Down Expand Up @@ -67,12 +90,16 @@ void Set(DescriptorSetLayoutBinding* bindings, int maxPerStage, DescriptorType t

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
{
Binding = (uint)(start + stage * maxPerStage),
DescriptorType = DescriptorType.StorageBuffer,
DescriptorCount = (uint)maxPerStage,
StageFlags = stageFlags
StageFlags = flags
};
}

Expand Down