Rework to reduce code duplication and possibility of error.
Reduce number of pipelines?
This commit is contained in:
parent
2846e88a5d
commit
1cb35a42db
4 changed files with 115 additions and 95 deletions
|
@ -709,8 +709,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
{
|
{
|
||||||
DepthTestDescriptor descriptor = new(
|
DepthTestDescriptor descriptor = new(
|
||||||
_state.State.DepthTestEnable,
|
_state.State.DepthTestEnable,
|
||||||
_state.State.DepthWriteEnable && _state.State.DepthTestEnable,
|
_state.State.DepthWriteEnable,
|
||||||
_state.State.DepthTestEnable ? _state.State.DepthTestFunc : default);
|
_state.State.DepthTestFunc);
|
||||||
|
|
||||||
_pipeline.DepthTest = descriptor;
|
_pipeline.DepthTest = descriptor;
|
||||||
_context.Renderer.Pipeline.SetDepthTest(descriptor);
|
_context.Renderer.Pipeline.SetDepthTest(descriptor);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
|
@ -675,9 +676,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
if (_supportExtDynamic)
|
if (_supportExtDynamic)
|
||||||
{
|
{
|
||||||
if (oldTopologyClass != _newState.Topology)
|
if (oldTopologyClass != _newState.Topology.ConvertToClass())
|
||||||
{
|
{
|
||||||
_newState.Topology = oldTopologyClass;
|
_newState.Topology = oldTopology;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicState.SetCullMode(oldCullMode);
|
DynamicState.SetCullMode(oldCullMode);
|
||||||
|
@ -983,7 +984,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_newState.LogicOp = logicOpEnable ? op.Convert() : default;
|
_newState.LogicOp = op.Convert();
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalStateChange();
|
SignalStateChange();
|
||||||
|
@ -1049,9 +1050,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
var newTopologyClass = vkTopology.ConvertToClass();
|
var newTopologyClass = vkTopology.ConvertToClass();
|
||||||
|
|
||||||
if ((_newState.Topology != newTopologyClass))
|
if ((_newState.Topology.ConvertToClass() != newTopologyClass))
|
||||||
{
|
{
|
||||||
_newState.Topology = newTopologyClass;
|
_newState.Topology = vkTopology;
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicState.SetPrimitiveTopology(vkTopology);
|
DynamicState.SetPrimitiveTopology(vkTopology);
|
||||||
|
@ -1401,7 +1402,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
_newState.Internal.VertexBindingDescriptions[descriptorIndex] = new VertexInputBindingDescription(
|
_newState.Internal.VertexBindingDescriptions[descriptorIndex] = new VertexInputBindingDescription(
|
||||||
(uint)binding,
|
(uint)binding,
|
||||||
_supportExtDynamic && !Gd.IsMoltenVk ? default : (uint)vertexBuffer.Stride,
|
(uint)vertexBuffer.Stride,
|
||||||
inputRate);
|
inputRate);
|
||||||
|
|
||||||
int vbSize = vertexBuffer.Buffer.Size;
|
int vbSize = vertexBuffer.Buffer.Size;
|
||||||
|
|
|
@ -175,7 +175,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
pipeline.PolygonMode = PolygonMode.Fill; // Not implemented.
|
pipeline.PolygonMode = PolygonMode.Fill; // Not implemented.
|
||||||
|
|
||||||
pipeline.Topology = extendedDynamicState ? gd.TopologyRemap(state.Topology).Convert().ConvertToClass() : gd.TopologyRemap(state.Topology).Convert();
|
pipeline.Topology = gd.TopologyRemap(state.Topology).Convert();
|
||||||
|
|
||||||
if (!extendedDynamicState)
|
if (!extendedDynamicState)
|
||||||
{
|
{
|
||||||
|
@ -219,6 +219,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
(state.DepthBiasFactor != 0 && state.DepthBiasUnits != 0));
|
(state.DepthBiasFactor != 0 && state.DepthBiasUnits != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!extendedDynamicState2.ExtendedDynamicState2LogicOp)
|
||||||
|
{
|
||||||
|
pipeline.LogicOp = state.LogicOp.Convert();
|
||||||
|
}
|
||||||
|
|
||||||
if (!extendedDynamicState2.ExtendedDynamicState2PatchControlPoints)
|
if (!extendedDynamicState2.ExtendedDynamicState2PatchControlPoints)
|
||||||
{
|
{
|
||||||
pipeline.PatchControlPoints = state.PatchControlPoints;
|
pipeline.PatchControlPoints = state.PatchControlPoints;
|
||||||
|
@ -271,7 +276,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
// TODO: Support divisor > 1
|
// TODO: Support divisor > 1
|
||||||
pipeline.Internal.VertexBindingDescriptions[descriptorIndex++] = new VertexInputBindingDescription(
|
pipeline.Internal.VertexBindingDescriptions[descriptorIndex++] = new VertexInputBindingDescription(
|
||||||
(uint)i + 1,
|
(uint)i + 1,
|
||||||
extendedDynamicState && !gd.IsMoltenVk ? default : (uint)alignedStride,
|
(uint)alignedStride,
|
||||||
inputRate);
|
inputRate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,14 +339,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
pipeline.Internal.AttachmentIntegerFormatMask = attachmentIntegerFormatMask;
|
pipeline.Internal.AttachmentIntegerFormatMask = attachmentIntegerFormatMask;
|
||||||
pipeline.Internal.LogicOpsAllowed = attachmentCount == 0 || !allFormatsFloatOrSrgb;
|
pipeline.Internal.LogicOpsAllowed = attachmentCount == 0 || !allFormatsFloatOrSrgb;
|
||||||
|
|
||||||
if (!extendedDynamicState2.ExtendedDynamicState2LogicOp)
|
|
||||||
{
|
|
||||||
bool logicOpEnable = state.LogicOpEnable &&
|
|
||||||
(gd.Vendor == Vendor.Nvidia || pipeline.Internal.LogicOpsAllowed);
|
|
||||||
|
|
||||||
pipeline.LogicOp = logicOpEnable ? state.LogicOp.Convert() : default;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,6 +256,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
private bool _supportsExtDynamicState;
|
private bool _supportsExtDynamicState;
|
||||||
private PhysicalDeviceExtendedDynamicState2FeaturesEXT _supportsExtDynamicState2;
|
private PhysicalDeviceExtendedDynamicState2FeaturesEXT _supportsExtDynamicState2;
|
||||||
private bool _supportsFeedBackLoopDynamicState;
|
private bool _supportsFeedBackLoopDynamicState;
|
||||||
|
private uint _blendEnables;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void Initialize(HardwareCapabilities capabilities)
|
public void Initialize(HardwareCapabilities capabilities)
|
||||||
|
@ -297,7 +299,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
DepthWriteEnable = false;
|
DepthWriteEnable = false;
|
||||||
DepthCompareOp = 0;
|
DepthCompareOp = 0;
|
||||||
StencilTestEnable = false;
|
StencilTestEnable = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_supportsExtDynamicState2.ExtendedDynamicState2)
|
if (_supportsExtDynamicState2.ExtendedDynamicState2)
|
||||||
|
@ -368,6 +369,74 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void CheckCapability(VulkanRenderer gd)
|
||||||
|
{
|
||||||
|
// Vendors other than NVIDIA have a bug where it enables logical operations even for float formats,
|
||||||
|
// so we need to force disable them here.
|
||||||
|
LogicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed);
|
||||||
|
|
||||||
|
if (!_supportsExtDynamicState)
|
||||||
|
{
|
||||||
|
DepthWriteEnable = DepthWriteEnable && DepthTestEnable;
|
||||||
|
DepthCompareOp = DepthTestEnable ? DepthCompareOp : default;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_supportsExtDynamicState2.ExtendedDynamicState2LogicOp)
|
||||||
|
{
|
||||||
|
LogicOp = LogicOpEnable ? LogicOp : default;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_supportsExtDynamicState2.ExtendedDynamicState2)
|
||||||
|
{
|
||||||
|
bool topologySupportsRestart;
|
||||||
|
|
||||||
|
if (gd.Capabilities.SupportsPrimitiveTopologyListRestart)
|
||||||
|
{
|
||||||
|
topologySupportsRestart = gd.Capabilities.SupportsPrimitiveTopologyPatchListRestart ||
|
||||||
|
Topology != PrimitiveTopology.PatchList;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
topologySupportsRestart = Topology == PrimitiveTopology.LineStrip ||
|
||||||
|
Topology == PrimitiveTopology.TriangleStrip ||
|
||||||
|
Topology == PrimitiveTopology.TriangleFan ||
|
||||||
|
Topology == PrimitiveTopology.LineStripWithAdjacency ||
|
||||||
|
Topology == PrimitiveTopology.TriangleStripWithAdjacency;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrimitiveRestartEnable &= topologySupportsRestart;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_supportsExtDynamicState)
|
||||||
|
{
|
||||||
|
Topology = Topology.ConvertToClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
Topology = HasTessellationControlShader ? PrimitiveTopology.PatchList : Topology;
|
||||||
|
|
||||||
|
if (gd.IsMoltenVk && Internal.AttachmentIntegerFormatMask != 0)
|
||||||
|
{
|
||||||
|
_blendEnables = 0;
|
||||||
|
|
||||||
|
// Blend can't be enabled for integer formats, so let's make sure it is disabled.
|
||||||
|
uint attachmentIntegerFormatMask = Internal.AttachmentIntegerFormatMask;
|
||||||
|
|
||||||
|
while (attachmentIntegerFormatMask != 0)
|
||||||
|
{
|
||||||
|
int i = BitOperations.TrailingZeroCount(attachmentIntegerFormatMask);
|
||||||
|
|
||||||
|
if (Internal.ColorBlendAttachmentState[i].BlendEnable)
|
||||||
|
{
|
||||||
|
_blendEnables |= 1u << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
Internal.ColorBlendAttachmentState[i].BlendEnable = false;
|
||||||
|
attachmentIntegerFormatMask &= ~(1u << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public unsafe Auto<DisposablePipeline> CreateGraphicsPipeline(
|
public unsafe Auto<DisposablePipeline> CreateGraphicsPipeline(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
Device device,
|
Device device,
|
||||||
|
@ -376,6 +445,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
RenderPass renderPass,
|
RenderPass renderPass,
|
||||||
bool throwOnError = false)
|
bool throwOnError = false)
|
||||||
{
|
{
|
||||||
|
CheckCapability(gd);
|
||||||
|
|
||||||
// Using patches topology without a tessellation shader is invalid.
|
// Using patches topology without a tessellation shader is invalid.
|
||||||
// If we find such a case, return null pipeline to skip the draw.
|
// If we find such a case, return null pipeline to skip the draw.
|
||||||
if (Topology == PrimitiveTopology.PatchList && !HasTessellationControlShader)
|
if (Topology == PrimitiveTopology.PatchList && !HasTessellationControlShader)
|
||||||
|
@ -413,12 +484,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
PVertexBindingDescriptions = pVertexBindingDescriptions,
|
PVertexBindingDescriptions = pVertexBindingDescriptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
var topology = HasTessellationControlShader ? PrimitiveTopology.PatchList : Topology;
|
|
||||||
|
|
||||||
var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo
|
var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.PipelineInputAssemblyStateCreateInfo,
|
SType = StructureType.PipelineInputAssemblyStateCreateInfo,
|
||||||
Topology = topology,
|
Topology = Topology,
|
||||||
};
|
};
|
||||||
|
|
||||||
PipelineTessellationStateCreateInfo tessellationState;
|
PipelineTessellationStateCreateInfo tessellationState;
|
||||||
|
@ -497,27 +566,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
if (!_supportsExtDynamicState2.ExtendedDynamicState2)
|
if (!_supportsExtDynamicState2.ExtendedDynamicState2)
|
||||||
{
|
{
|
||||||
bool primitiveRestartEnable = PrimitiveRestartEnable;
|
|
||||||
|
|
||||||
bool topologySupportsRestart;
|
inputAssemblyState.PrimitiveRestartEnable = PrimitiveRestartEnable;
|
||||||
|
|
||||||
if (gd.Capabilities.SupportsPrimitiveTopologyListRestart)
|
|
||||||
{
|
|
||||||
topologySupportsRestart = gd.Capabilities.SupportsPrimitiveTopologyPatchListRestart ||
|
|
||||||
Topology != PrimitiveTopology.PatchList;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
topologySupportsRestart = Topology == PrimitiveTopology.LineStrip ||
|
|
||||||
Topology == PrimitiveTopology.TriangleStrip ||
|
|
||||||
Topology == PrimitiveTopology.TriangleFan ||
|
|
||||||
Topology == PrimitiveTopology.LineStripWithAdjacency ||
|
|
||||||
Topology == PrimitiveTopology.TriangleStripWithAdjacency;
|
|
||||||
}
|
|
||||||
|
|
||||||
primitiveRestartEnable &= topologySupportsRestart;
|
|
||||||
|
|
||||||
inputAssemblyState.PrimitiveRestartEnable = primitiveRestartEnable;
|
|
||||||
rasterizationState.DepthBiasEnable = DepthBiasEnable;
|
rasterizationState.DepthBiasEnable = DepthBiasEnable;
|
||||||
rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable;
|
rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable;
|
||||||
}
|
}
|
||||||
|
@ -531,37 +581,12 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint blendEnables = 0;
|
|
||||||
|
|
||||||
if (isMoltenVk && Internal.AttachmentIntegerFormatMask != 0)
|
|
||||||
{
|
|
||||||
// Blend can't be enabled for integer formats, so let's make sure it is disabled.
|
|
||||||
uint attachmentIntegerFormatMask = Internal.AttachmentIntegerFormatMask;
|
|
||||||
|
|
||||||
while (attachmentIntegerFormatMask != 0)
|
|
||||||
{
|
|
||||||
int i = BitOperations.TrailingZeroCount(attachmentIntegerFormatMask);
|
|
||||||
|
|
||||||
if (Internal.ColorBlendAttachmentState[i].BlendEnable)
|
|
||||||
{
|
|
||||||
blendEnables |= 1u << i;
|
|
||||||
}
|
|
||||||
|
|
||||||
Internal.ColorBlendAttachmentState[i].BlendEnable = false;
|
|
||||||
attachmentIntegerFormatMask &= ~(1u << i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vendors other than NVIDIA have a bug where it enables logical operations even for float formats,
|
|
||||||
// so we need to force disable them here.
|
|
||||||
bool logicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed);
|
|
||||||
|
|
||||||
var colorBlendState = new PipelineColorBlendStateCreateInfo
|
var colorBlendState = new PipelineColorBlendStateCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.PipelineColorBlendStateCreateInfo,
|
SType = StructureType.PipelineColorBlendStateCreateInfo,
|
||||||
AttachmentCount = ColorBlendAttachmentStateCount,
|
AttachmentCount = ColorBlendAttachmentStateCount,
|
||||||
PAttachments = pColorBlendAttachmentState,
|
PAttachments = pColorBlendAttachmentState,
|
||||||
LogicOpEnable = logicOpEnable,
|
LogicOpEnable = LogicOpEnable,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp)
|
if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp)
|
||||||
|
@ -650,27 +675,9 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
PDynamicStates = dynamicStates,
|
PDynamicStates = dynamicStates,
|
||||||
};
|
};
|
||||||
|
|
||||||
PipelineCreateFlags flags = 0;
|
|
||||||
|
|
||||||
if (gd.Capabilities.SupportsAttachmentFeedbackLoop && !_supportsFeedBackLoopDynamicState)
|
|
||||||
{
|
|
||||||
FeedbackLoopAspects aspects = FeedbackLoopAspects;
|
|
||||||
|
|
||||||
if ((aspects & FeedbackLoopAspects.Color) != 0)
|
|
||||||
{
|
|
||||||
flags |= PipelineCreateFlags.CreateColorAttachmentFeedbackLoopBitExt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((aspects & FeedbackLoopAspects.Depth) != 0)
|
|
||||||
{
|
|
||||||
flags |= PipelineCreateFlags.CreateDepthStencilAttachmentFeedbackLoopBitExt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var pipelineCreateInfo = new GraphicsPipelineCreateInfo
|
var pipelineCreateInfo = new GraphicsPipelineCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.GraphicsPipelineCreateInfo,
|
SType = StructureType.GraphicsPipelineCreateInfo,
|
||||||
Flags = flags,
|
|
||||||
StageCount = StagesCount,
|
StageCount = StagesCount,
|
||||||
PStages = Stages.Pointer,
|
PStages = Stages.Pointer,
|
||||||
PVertexInputState = &vertexInputState,
|
PVertexInputState = &vertexInputState,
|
||||||
|
@ -685,6 +692,21 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
RenderPass = renderPass,
|
RenderPass = renderPass,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (gd.Capabilities.SupportsAttachmentFeedbackLoop && !_supportsFeedBackLoopDynamicState)
|
||||||
|
{
|
||||||
|
FeedbackLoopAspects aspects = FeedbackLoopAspects;
|
||||||
|
|
||||||
|
if ((aspects & FeedbackLoopAspects.Color) != 0)
|
||||||
|
{
|
||||||
|
pipelineCreateInfo.Flags |= PipelineCreateFlags.CreateColorAttachmentFeedbackLoopBitExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((aspects & FeedbackLoopAspects.Depth) != 0)
|
||||||
|
{
|
||||||
|
pipelineCreateInfo.Flags |= PipelineCreateFlags.CreateDepthStencilAttachmentFeedbackLoopBitExt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints)
|
if (!gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints)
|
||||||
{
|
{
|
||||||
pipelineCreateInfo.PTessellationState = &tessellationState;
|
pipelineCreateInfo.PTessellationState = &tessellationState;
|
||||||
|
@ -702,21 +724,21 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore previous blend enable values if we changed it.
|
|
||||||
while (blendEnables != 0)
|
|
||||||
{
|
|
||||||
int i = BitOperations.TrailingZeroCount(blendEnables);
|
|
||||||
|
|
||||||
Internal.ColorBlendAttachmentState[i].BlendEnable = true;
|
|
||||||
blendEnables &= ~(1u << i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline = new Auto<DisposablePipeline>(new DisposablePipeline(gd.Api, device, pipelineHandle));
|
pipeline = new Auto<DisposablePipeline>(new DisposablePipeline(gd.Api, device, pipelineHandle));
|
||||||
|
|
||||||
program.AddGraphicsPipeline(ref Internal, pipeline);
|
program.AddGraphicsPipeline(ref Internal, pipeline);
|
||||||
|
|
||||||
|
// Restore previous blend enable values if we changed it.
|
||||||
|
while (_blendEnables != 0)
|
||||||
|
{
|
||||||
|
int i = BitOperations.TrailingZeroCount(_blendEnables);
|
||||||
|
|
||||||
|
Internal.ColorBlendAttachmentState[i].BlendEnable = true;
|
||||||
|
_blendEnables &= ~(1u << i);
|
||||||
|
}
|
||||||
|
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue