Use dynamic state for primitive topology if dynamicPrimitiveTopologyUnrestricted is supported.

This commit is contained in:
sunshineinabox 2024-05-22 09:45:50 -07:00
parent dcc999c798
commit 89dee194d2
4 changed files with 77 additions and 5 deletions

View file

@ -697,7 +697,7 @@ namespace Ryujinx.Graphics.Vulkan
var oldStencilTestEnable = _supportExtDynamic ? DynamicState.StencilTestEnable : _newState.StencilTestEnable; var oldStencilTestEnable = _supportExtDynamic ? DynamicState.StencilTestEnable : _newState.StencilTestEnable;
var oldDepthTestEnable = _supportExtDynamic ? DynamicState.DepthTestEnable : _newState.DepthTestEnable; var oldDepthTestEnable = _supportExtDynamic ? DynamicState.DepthTestEnable : _newState.DepthTestEnable;
var oldDepthWriteEnable = _supportExtDynamic ? DynamicState.DepthWriteEnable : _newState.DepthWriteEnable; var oldDepthWriteEnable = _supportExtDynamic ? DynamicState.DepthWriteEnable : _newState.DepthWriteEnable;
var oldTopology = _newState.Topology; var oldTopology = Gd.SupportsUnrestrictedDynamicTopology ? DynamicState.Topology : _newState.Topology;
var oldViewports = DynamicState.Viewports; var oldViewports = DynamicState.Viewports;
var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount; var oldViewportsCount = _supportExtDynamic ? DynamicState.ViewportsCount : _newState.ViewportsCount;
@ -740,7 +740,14 @@ namespace Ryujinx.Graphics.Vulkan
_newState.ViewportsCount = oldViewportsCount; _newState.ViewportsCount = oldViewportsCount;
} }
if (Gd.SupportsUnrestrictedDynamicTopology)
{
DynamicState.SetPrimitiveTopology(oldTopology);
}
else
{
_newState.Topology = oldTopology; _newState.Topology = oldTopology;
}
DynamicState.SetViewports(ref oldViewports, oldViewportsCount); DynamicState.SetViewports(ref oldViewports, oldViewportsCount);
@ -1128,7 +1135,14 @@ namespace Ryujinx.Graphics.Vulkan
var vkTopology = Gd.TopologyRemap(topology).Convert(); var vkTopology = Gd.TopologyRemap(topology).Convert();
if (Gd.SupportsUnrestrictedDynamicTopology)
{
DynamicState.SetPrimitiveTopology(vkTopology);
}
else
{
_newState.Topology = vkTopology; _newState.Topology = vkTopology;
}
SignalStateChange(); SignalStateChange();
} }

View file

@ -65,6 +65,8 @@ namespace Ryujinx.Graphics.Vulkan
private bool _primitiveRestartEnable; private bool _primitiveRestartEnable;
public PrimitiveTopology Topology;
[Flags] [Flags]
private enum DirtyFlags private enum DirtyFlags
{ {
@ -89,10 +91,11 @@ namespace Ryujinx.Graphics.Vulkan
PatchControlPoints = 1 << 17, PatchControlPoints = 1 << 17,
DepthMode = 1 << 18, DepthMode = 1 << 18,
PrimitiveRestart = 1 << 19, PrimitiveRestart = 1 << 19,
PrimitiveTopology = 1 << 20,
Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth,
Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable,
Extended2 = RasterDiscard | LogicOp | PatchControlPoints | PrimitiveRestart, Extended2 = RasterDiscard | LogicOp | PatchControlPoints | PrimitiveRestart,
Extended3 = DepthClampEnable | LogicOpEnable | AlphaToCover | AlphaToOne | DepthMode, Extended3 = DepthClampEnable | LogicOpEnable | AlphaToCover | AlphaToOne | DepthMode | PrimitiveTopology,
} }
private DirtyFlags _dirty; private DirtyFlags _dirty;
@ -218,6 +221,12 @@ namespace Ryujinx.Graphics.Vulkan
_dirty |= DirtyFlags.PrimitiveRestart; _dirty |= DirtyFlags.PrimitiveRestart;
} }
public void SetPrimitiveTopology(PrimitiveTopology topology)
{
Topology = topology;
_dirty |= DirtyFlags.PrimitiveTopology;
}
public void SetLogicOp(LogicOp op) public void SetLogicOp(LogicOp op)
{ {
_logicOp = op; _logicOp = op;
@ -318,6 +327,11 @@ namespace Ryujinx.Graphics.Vulkan
{ {
_dirty &= ~DirtyFlags.DepthMode; _dirty &= ~DirtyFlags.DepthMode;
} }
if (!gd.SupportsUnrestrictedDynamicTopology)
{
_dirty &= ~DirtyFlags.PrimitiveTopology;
}
} }
public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer)
@ -387,6 +401,11 @@ namespace Ryujinx.Graphics.Vulkan
RecordPrimitiveRestartEnable(gd, commandBuffer); RecordPrimitiveRestartEnable(gd, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.PrimitiveTopology))
{
RecordPrimitiveRestartEnable(gd, commandBuffer);
}
if (_dirty.HasFlag(DirtyFlags.LogicOp)) if (_dirty.HasFlag(DirtyFlags.LogicOp))
{ {
RecordLogicOp(gd, commandBuffer); RecordLogicOp(gd, commandBuffer);
@ -422,6 +441,11 @@ namespace Ryujinx.Graphics.Vulkan
RecordDepthMode(gd, commandBuffer); RecordDepthMode(gd, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.PrimitiveTopology))
{
RecordPrimitiveTopology(gd, commandBuffer);
}
_dirty = DirtyFlags.None; _dirty = DirtyFlags.None;
} }
@ -538,6 +562,11 @@ namespace Ryujinx.Graphics.Vulkan
gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, _primitiveRestartEnable); gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, _primitiveRestartEnable);
} }
private readonly void RecordPrimitiveTopology(VulkanRenderer gd, CommandBuffer commandBuffer)
{
gd.ExtendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, Topology);
}
private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer)
{ {
if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable && !_logicOpEnable) if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable && !_logicOpEnable)

View file

@ -435,9 +435,13 @@ namespace Ryujinx.Graphics.Vulkan
var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo
{ {
SType = StructureType.PipelineInputAssemblyStateCreateInfo, SType = StructureType.PipelineInputAssemblyStateCreateInfo,
Topology = Topology,
}; };
if (!gd.SupportsUnrestrictedDynamicTopology)
{
inputAssemblyState.Topology = Topology;
}
var tessellationState = new PipelineTessellationStateCreateInfo var tessellationState = new PipelineTessellationStateCreateInfo
{ {
SType = StructureType.PipelineTessellationStateCreateInfo, SType = StructureType.PipelineTessellationStateCreateInfo,
@ -633,6 +637,11 @@ namespace Ryujinx.Graphics.Vulkan
{ {
additionalDynamicStatesCount++; additionalDynamicStatesCount++;
} }
if (gd.SupportsUnrestrictedDynamicTopology)
{
additionalDynamicStatesCount++;
}
} }
int dynamicStatesCount = baseDynamicStatesCount + additionalDynamicStatesCount; int dynamicStatesCount = baseDynamicStatesCount + additionalDynamicStatesCount;
@ -710,6 +719,11 @@ namespace Ryujinx.Graphics.Vulkan
{ {
dynamicStates[currentIndex++] = DynamicState.DepthClipNegativeOneToOneExt; dynamicStates[currentIndex++] = DynamicState.DepthClipNegativeOneToOneExt;
} }
if (gd.SupportsUnrestrictedDynamicTopology)
{
dynamicStates[currentIndex++] = DynamicState.PrimitiveTopology;
}
} }
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo

View file

@ -104,6 +104,8 @@ namespace Ryujinx.Graphics.Vulkan
public PhysicalDeviceExtendedDynamicState3FeaturesEXT ExtendedDynamicState3Features; public PhysicalDeviceExtendedDynamicState3FeaturesEXT ExtendedDynamicState3Features;
public bool SupportsUnrestrictedDynamicTopology;
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured; public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
@ -211,6 +213,17 @@ namespace Ryujinx.Graphics.Vulkan
properties2.PNext = &propertiesTransformFeedback; properties2.PNext = &propertiesTransformFeedback;
} }
PhysicalDeviceExtendedDynamicState3PropertiesEXT propertiesExtendedDynamicState3 = new()
{
SType = StructureType.PhysicalDeviceExtendedDynamicState3PropertiesExt,
};
if (_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName))
{
propertiesExtendedDynamicState3.PNext = properties2.PNext;
properties2.PNext = &propertiesExtendedDynamicState3;
}
PhysicalDevicePortabilitySubsetPropertiesKHR propertiesPortabilitySubset = new() PhysicalDevicePortabilitySubsetPropertiesKHR propertiesPortabilitySubset = new()
{ {
SType = StructureType.PhysicalDevicePortabilitySubsetPropertiesKhr, SType = StructureType.PhysicalDevicePortabilitySubsetPropertiesKhr,
@ -425,6 +438,8 @@ namespace Ryujinx.Graphics.Vulkan
properties.Limits.SubTexelPrecisionBits, properties.Limits.SubTexelPrecisionBits,
minResourceAlignment); minResourceAlignment);
SupportsUnrestrictedDynamicTopology = propertiesExtendedDynamicState3.DynamicPrimitiveTopologyUnrestricted;
IsSharedMemory = MemoryAllocator.IsDeviceMemoryShared(_physicalDevice); IsSharedMemory = MemoryAllocator.IsDeviceMemoryShared(_physicalDevice);
MemoryAllocator = new MemoryAllocator(Api, _physicalDevice, _device); MemoryAllocator = new MemoryAllocator(Api, _physicalDevice, _device);