diff --git a/src/SharpEmu.Libs/Gpu/Pipelines/ShaderPipelineCache.cs b/src/SharpEmu.Libs/Gpu/Pipelines/ShaderPipelineCache.cs index dd1c64d..0ee85c1 100644 --- a/src/SharpEmu.Libs/Gpu/Pipelines/ShaderPipelineCache.cs +++ b/src/SharpEmu.Libs/Gpu/Pipelines/ShaderPipelineCache.cs @@ -111,6 +111,9 @@ internal sealed partial class ShaderPipelineCache : IShaderPipelineProvider pixelOutputs = ResolveBoundTargets(context, out var outputModes, out var outputMappings); pixelInfo = PixelStageInputResolver.Resolve(_context, pixelSource.Registered, shaderInterface, outputModes, outputMappings, inputCount); + // SPI_PS_INPUT_CNTL can map an input to any parameter export, beyond the input count; + // the vertex program must declare every location the pixel program reads. + attributeCount = Math.Max(attributeCount, ReadVertexOutputCount(pixelProgram, pixelInfo)); } ShaderProgram vertexProgram; @@ -204,6 +207,32 @@ internal sealed partial class ShaderPipelineCache : IShaderPipelineProvider shaderInterface.VertexOutputControl, clipSpace); } + // One past the highest parameter location the pixel program reads, resolved as its translator does. + private static uint ReadVertexOutputCount(Gen5ShaderProgram pixelProgram, PixelInputInfo info) + { + var attributes = pixelProgram.Instructions + .Select(static instruction => instruction.Control) + .OfType() + .Select(static control => control.Attribute) + .Distinct() + .Order() + .ToArray(); + if (attributes.Length == 0) + { + return 0; + } + + var controls = new uint[32]; + for (var index = 0u; index < (uint)controls.Length; index++) + { + controls[index] = index < info.InputCount && index < (uint)info.InterpolatorSettings.Length + ? info.InterpolatorSettings[index] + : index; + } + + return Gen5PixelInputMapping.ResolveLocations(controls, attributes).Max() + 1; + } + private static uint InterpolatedAttributeCount(Gen5ShaderProgram program) { var maxAttribute = -1; diff --git a/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Pipelines.cs b/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Pipelines.cs index 3c69911..bf72db4 100644 --- a/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Pipelines.cs +++ b/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Pipelines.cs @@ -769,7 +769,8 @@ internal static unsafe partial class VulkanVideoPresenter Layout = layout, }; var graphicsStart = Stopwatch.GetTimestamp(); - Check(_vk.CreateGraphicsPipelines(_device, _pipelineCache, 1, &pipelineInfo, null, out var pipeline), "vkCreateGraphicsPipelines(rendering)"); + Check(_vk.CreateGraphicsPipelines(_device, _pipelineCache, 1, &pipelineInfo, null, out var pipeline), + $"vkCreateGraphicsPipelines(rendering vs=0x{description.VertexStage.Hash:X16} ps=0x{description.PixelStage?.Hash ?? 0:X16})"); ReportPipelineCreation( (long)Stopwatch.GetElapsedTime(graphicsStart).TotalMilliseconds, "graphics",