Compare commits

...

129 Commits

Author SHA1 Message Date
sunshineinabox a2ce18a326
Merge e87ce0209a into ef81658fbd 2024-09-18 23:44:13 +02:00
gdkchan ef81658fbd
Implement support for shader ATOM.EXCH instruction (#7320)
* Implement support for shader ATOM.EXCH instruction

* Shader cache version bump

* Check type
2024-09-18 15:48:55 -03:00
sunshineinabox e87ce0209a Resolve validation error 2024-09-14 01:12:35 -07:00
sunshineinabox 6e132e9fd7 Style correction 2024-09-13 15:28:21 -07:00
sunshineinabox bc14efe5f1 Avoid setting the dynamic state for feedback loop if it is not set avoids validation error. Also linewidth value is ignored if dynamic state is supported. 2024-09-13 15:22:05 -07:00
sunshineinabox b557dc805b Missed line 2024-09-13 10:44:39 -07:00
sunshineinabox 2d0c1c3a1c Code review suggestions 2024-09-13 08:13:44 -07:00
sunshineinabox dff81088e8 Replace Action array with a switch statment. 2024-09-09 22:03:50 -07:00
sunshineinabox 5a391f38fd Refactor Cull Mode to only send face. 2024-09-09 21:50:18 -07:00
sunshineinabox 2fd093d4b4 Avoid setting stride if dynamic state is supported 2024-09-09 21:17:44 -07:00
sunshineinabox f085b47b30 Address Feedback 2024-09-09 21:08:13 -07:00
sunshineinabox d7089682ae Code Review Suggestion 2024-09-10 01:57:31 +00:00
sunshineinabox 01c6d5491e Code Review Suggestions 2024-09-09 18:53:40 -07:00
sunshineinabox 4a3b10fa9f
Apply suggestions from code review
Simple suggestions from code review

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-09-09 18:11:35 -07:00
sunshineinabox d9c5b5c753 Correct typo 2024-09-09 11:04:33 -07:00
sunshineinabox 2a3069d9a1 Enable Vertex Input Binding Stride extended state when available on newer MVK 2024-09-09 11:02:07 -07:00
sunshineinabox 381abda2c8 Primitive restart is enabled/disabled based on the original topology before its converted to its topology class, make this behavior consistent 2024-09-09 09:01:00 -07:00
sunshineinabox 9bcc8374da Only attempt to change topology class if needed 2024-09-07 20:09:58 -07:00
sunshineinabox 1cb35a42db Rework to reduce code duplication and possibility of error.
Reduce number of pipelines?
2024-09-07 17:26:26 -07:00
sunshineinabox 2846e88a5d Clean up and some housekeeping 2024-09-04 19:51:26 -07:00
sunshineinabox 1fa1c7b01d Need to test this on Windows 2024-09-02 21:09:09 -07:00
sunshineinabox 91c3ac2701 Revert a change 2024-09-02 16:22:10 -07:00
sunshineinabox a7409e6fba Some missed changes 2024-09-02 12:40:29 -07:00
sunshineinabox 5e86d5e178 There will still be an issue with extension is supported and dynmaic state is not 2024-09-01 21:33:05 -07:00
sunshineinabox 09b8095584 Avoid changing feedback loop aspect if extension is not supported prevents failed pipeline compiles (or seemingly incompatible) 2024-09-01 19:21:44 -07:00
sunshineinabox 3f900e6fa0 Resolve missed changes 2024-09-01 18:47:06 -07:00
sunshineinabox 6464f97973
Merge branch 'master' into MoreDynamicStatesPartOne 2024-09-01 18:43:34 -07:00
sunshineinabox 2298362e7f Resolve remaining pipeline creation errors when extended pipeline states extension not supported 2024-09-01 18:17:19 -07:00
sunshineinabox 07f80bdbb7 Resolve some pipeline creation issue when extended dynamic states are not supported 2024-09-01 16:41:36 -07:00
sunshineinabox 3e5b946289
Merge branch 'master' into MoreDynamicStatesPartOne 2024-09-01 14:54:00 -07:00
sunshineinabox 674288a71f Avoid creating pipelines for each topology. 2024-08-12 22:09:09 -07:00
sunshineinabox 2d1af4ddb4 Set a default topology state that can be overwritten later if needed. 2024-08-12 20:57:08 -07:00
sunshineinabox 1a43536092 LogicOps 2024-08-11 19:54:52 -07:00
sunshineinabox 49494b5b2d Some more default values 2024-08-10 17:16:48 -07:00
sunshineinabox d6f05044ea Set stride to 0 if Vertex Input dynamic state is enabled 2024-08-10 16:49:05 -07:00
sunshineinabox 42c47e408d If dynamic states are enabled use default values for calculation uuid 2024-08-10 16:35:30 -07:00
sunshineinabox af31a14c77 Spec states it CAN be null 2024-08-06 23:24:34 -07:00
sunshineinabox 6aa30b24ba Actually change what is being passed to HwCapabilities instead of just disabling the feature. 2024-08-06 08:15:17 -07:00
sunshineinabox 53ca3b53b6 Exclude Patch Control Points dynamic state at this time 2024-08-05 23:18:28 -07:00
sunshineinabox 482b960740 More changes to be inline with spec 2024-08-04 20:53:54 -07:00
sunshineinabox af9de85a1b Origin of crash? 2024-08-04 20:34:49 -07:00
sunshineinabox f15b6c85f6 According to spec there is no need to do this as it should automatically be not set when not needed 2024-08-04 16:16:27 -07:00
sunshineinabox c53f58a4a9 Resolve issue with primitive toplogy
Primitive Restart Enable should depend on Extended dynamic state 2 extension not 1

Resolve Primitive restart enable

Fix MoltenVK crash
2024-08-03 23:24:49 -07:00
sunshineinabox 3b398adbe6 Refactor PipelineUid and pack TopologyClass
Remove basepipelineindex as its extraneous
2024-08-03 19:22:46 -07:00
sunshineinabox 59ef2ac799 Accidental change 2024-08-02 18:17:28 -07:00
sunshineinabox ce450dc08e Invert logic to only set flags dirty if those are supported. 2024-08-02 07:27:44 -07:00
sunshineinabox 023f3ed44f Resolve build errors 2024-08-01 19:21:32 -07:00
sunshineinabox fa801ba472 Match other code in project 2024-08-01 19:17:59 -07:00
sunshineinabox 9b02fd6dc0 Conver to TopologyClass from Vulkan Topology 2024-08-01 08:19:11 -07:00
sunshineinabox adc7528b54 Why cast when you don't need to cast 2024-07-31 18:56:06 -07:00
sunshineinabox 1bcc9c029a Remove redundant logic, just use max possible dynamic states 2024-07-31 18:51:44 -07:00
sunshineinabox 38c9ec925c Whitespace fix 2024-07-31 18:22:29 -07:00
sunshineinabox 3f7a3ac558 Adapt changes from #7102 for dynamic states 2024-07-31 18:18:46 -07:00
sunshineinabox 7b480edf86
Merge branch 'master' into MoreDynamicStatesPartOne 2024-07-31 17:17:24 -07:00
sunshineinabox da11dc1288 Only pass Tesselation state create info if dynamic state is not supported 2024-07-31 17:12:57 -07:00
sunshineinabox 693f268090 Accidental change 2024-07-31 08:18:58 -07:00
sunshineinabox fb964b514c Do not set patch control points dynamic state if there is no tessalation control shader. Thank you riperiperi 2024-07-31 08:14:26 -07:00
sunshineinabox 1b9e42bdb4 Should not just check for extension. This is more correct. 2024-07-30 18:17:49 -07:00
sunshineinabox 7396c05b35 Resolve crash 2024-07-29 20:32:52 -07:00
sunshineinabox e7a4299400 Minor change 2024-07-23 22:09:56 -07:00
sunshineinabox ea44670330 Set logicOp and DepthCompareOp only if enabled 2024-07-23 22:03:47 -07:00
sunshineinabox 2cba50a9ed Move TopologyClass conversoin to EnumConversion.cs 2024-07-23 21:54:01 -07:00
sunshineinabox 34ac6f33ad
Merge branch 'master' into MoreDynamicStatesPartOne 2024-07-23 20:59:44 -07:00
sunshineinabox b66f6ce673 Resolve some validation errors 2024-07-23 20:58:47 -07:00
sunshineinabox a5052013f3 Fix some conditions 2024-07-23 20:25:23 -07:00
sunshineinabox 7610236816 Resolve merge error 2024-07-19 17:36:29 -07:00
sunshineinabox afe4d581ee
Merge branch 'master' into MoreDynamicStatesPartOne 2024-07-18 07:32:07 -07:00
sunshineinabox feb67dede6 Avoid setting depth bias state when not needed. 2024-07-04 23:38:21 -07:00
sunshineinabox 086656b736 Missed changes during merge 2024-07-04 23:03:22 -07:00
sunshineinabox 1d5a449931
Merge branch 'master' into MoreDynamicStatesPartOne 2024-07-04 22:54:17 -07:00
sunshineinabox 933c9c89ff Resolve logic op validation error only primitive topology pending 2024-06-03 21:10:13 -07:00
sunshineinabox 266649929f Clean up for some clarity and attempt to resolve some validation errors. 2024-06-02 21:00:18 -07:00
sunshineinabox 966c5d463c Sleep Deprivation 2024-05-30 07:52:05 -07:00
sunshineinabox 985c648860 Bring up pipeline converter inline with dynamic states. 2024-05-30 07:52:05 -07:00
sunshineinabox 16a4374ae8 Fix whitespace 2024-05-29 10:16:14 -07:00
sunshineinabox d8d33417e9 Fix oversight with implementing Primitive Topology Dynamic State 2024-05-29 10:14:12 -07:00
sunshineinabox e6492f8e78 Reduce unneeded state changes 2024-05-29 09:45:56 -07:00
sunshineinabox 5c65880ec0 Whitespaces 2024-05-29 09:16:44 -07:00
sunshineinabox 88786ba29c Missed change 2024-05-29 08:44:08 -07:00
sunshineinabox efdcce4415 Only enable enable LogicOp dynamic state and logic op if its enabled. 2024-05-29 08:36:24 -07:00
sunshineinabox 424166acd8 Oversight 2024-05-28 13:01:08 -07:00
sunshineinabox 3683ee5c29 Follow namign rules. 2024-05-27 23:25:59 -07:00
sunshineinabox 4a3932ed54 Use dictionary instead for clarity and rework some logic. 2024-05-27 23:11:39 -07:00
sunshineinabox 7ac2cd44d0 Attempt proper VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY implementation 2024-05-27 23:11:39 -07:00
sunshineinabox 4b504243d8 Consolidate some checks 2024-05-27 23:11:39 -07:00
sunshineinabox 1adae7794a Small changes 2024-05-27 23:11:39 -07:00
sunshineinabox ba56c1d3b3 Missed line 2024-05-27 23:11:39 -07:00
sunshineinabox f43413f374 Revert Silk.NET to main branch version.
Remove VK_EXT_extended_dynamic_state3 functionality until later PR
2024-05-27 23:11:39 -07:00
sunshineinabox fb4ef3347a Rebase 2024-05-27 23:11:39 -07:00
sunshineinabox 0000a7ac9c Rebased 2024-05-27 23:11:39 -07:00
sunshineinabox 74a1ab031d Attempt to resolve more validation errors. 2024-05-27 23:11:39 -07:00
sunshineinabox 89dee194d2 Use dynamic state for primitive topology if dynamicPrimitiveTopologyUnrestricted is supported. 2024-05-27 23:11:39 -07:00
sunshineinabox dcc999c798 Set dirty flag even when value has not changed. 2024-05-27 23:11:39 -07:00
sunshineinabox 7d7b1923aa Resolve
VUID-vkCmdSetPatchControlPointsEXT-None-09422(ERROR / SPEC): msgNum: -1559328192 - Validation Error: [ VUID-vkCmdSetPatchControlPointsEXT-None-09422 ] Object 0: handle = 0x25f0eb40170, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0xa30e8a40 | vkCmdSetPatchControlPointsEXT():   extendedDynamicState2PatchControlPoints or shaderObject feature is not enabled. The Vulkan spec states: At least one of the following must be true: The extendedDynamicState2PatchControlPoints feature is enabled The shaderObject feature is enabled (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdSetPatchControlPointsEXT-None-09422)
    Objects: 1
        [0] 0x25f0eb40170, type: 6, name: NULL
2024-05-27 23:11:39 -07:00
sunshineinabox de5cb66caf Resolve below validation error
VUID-vkCmdDraw-logicOp-04878(ERROR / SPEC): msgNum: 282117419 - Validation Error: [ VUID-vkCmdDraw-logicOp-04878 ] Object 0: handle = 0x2db247c7370, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0x81dc7e0000000305, type = VK_OBJECT_TYPE_PIPELINE; | MessageID = 0x10d0c52b | vkCmdDraw():  VK_DYNAMIC_STATE_LOGIC_OP_EXT state not set for this command buffer. The Vulkan spec states: If the bound graphics pipeline state was created with the VK_DYNAMIC_STATE_LOGIC_OP_EXT dynamic state enabled then vkCmdSetLogicOpEXT must have been called in the current command buffer prior to this drawing command and the logicOp must be a valid VkLogicOp value (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-vkCmdDraw-logicOp-04878)
    Objects: 2
        [0] 0x2db247c7370, type: 6, name: NULL
        [1] 0x81dc7e0000000305, type: 19, name: NULL
2024-05-27 23:11:39 -07:00
sunshineinabox 76c9c2ac8c Resolve the below validation errors.
VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442(ERROR / SPEC): msgNum: 1313692360 - Validation Error: [ VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442 ] | MessageID = 0x4e4d5ac8 | vkCreateGraphicsPipelines(): pCreateInfos[0].pDynamicState has VK_DYNAMIC_STATE_VIEWPORT at pDynamicStates[0] and pDynamicStates[28]. The Vulkan spec states: Each element of pDynamicStates must be unique (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442)
    Objects: 0
VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04132(ERROR / SPEC): msgNum: -206448348 - Validation Error: [ VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04132 ] | MessageID = 0xf3b1d924 | vkCreateGraphicsPipelines(): pCreateInfos[0].pDynamicState pDynamicStates[15] is VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT and pDynamicStates[28] is VK_DYNAMIC_STATE_VIEWPORT. The Vulkan spec states: If the pipeline requires pre-rasterization shader state, and VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT is included in the pDynamicStates array then VK_DYNAMIC_STATE_VIEWPORT must not be present (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04132)
    Objects: 0

VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04133(ERROR / SPEC): msgNum: -858144982 - Validation Error: [ VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04133 ] | MessageID = 0xccd9bf2a | vkCreateGraphicsPipelines(): pCreateInfos[0].pDynamicState pDynamicStates[16] is VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT and pDynamicStates[1] is VK_DYNAMIC_STATE_SCISSOR. The Vulkan spec states: If the pipeline requires pre-rasterization shader state, and VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT is included in the pDynamicStates array then VK_DYNAMIC_STATE_SCISSOR must not be present (https://vulkan.lunarg.com/doc/view/1.3.283.0/windows/1.3-extensions/vkspec.html#VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04133)
    Objects: 0
2024-05-27 23:11:39 -07:00
sunshineinabox f30a8f1580 Whitespace 2024-05-27 23:11:39 -07:00
sunshineinabox 6c6cd8927a Combine compatibility check. 2024-05-27 23:11:39 -07:00
sunshineinabox 8bb369f37d Missed enabling Dynamic State 2024-05-27 23:11:39 -07:00
sunshineinabox 5d5f482d57 Enable VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT 2024-05-27 23:11:39 -07:00
sunshineinabox 863674768d Some more small changes 2024-05-27 23:11:39 -07:00
sunshineinabox ab7f379e11 Formatting 2024-05-27 23:11:39 -07:00
sunshineinabox ecadc6a4f9 Implement VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT 2024-05-27 23:11:39 -07:00
sunshineinabox 3fe159f4dd Small fix 2024-05-27 23:11:39 -07:00
sunshineinabox d4e4ddca91 Fix formatting 2024-05-27 23:11:39 -07:00
sunshineinabox 2483b1a52a Enable VK_EXT_extended_dynamic_state3 this time without seizures. 2024-05-27 23:11:39 -07:00
sunshineinabox 5bf0937be1 Reverted previous commit as it caused mass seizures, disable for now. 2024-05-27 23:11:39 -07:00
sunshineinabox 0f2ed45f96 Revert "Enable the extension..."
This reverts commit 8bbdaab9a1.
2024-05-27 23:11:39 -07:00
sunshineinabox 404f4be9e7 Enable the extension... 2024-05-27 23:11:39 -07:00
sunshineinabox fd9b4cc10f More comments and formatting fixes 2024-05-27 23:11:39 -07:00
sunshineinabox eeecd894b9 Add Some Comments 2024-05-27 23:11:39 -07:00
sunshineinabox 767abfe500 Avoid unncessary state changes? 2024-05-27 23:11:39 -07:00
sunshineinabox 5f2d924bac Misc 2024-05-27 23:11:39 -07:00
sunshineinabox 19db5a0ce2 Implement VK_EXT_extended_dynamic_state3 2024-05-27 23:11:39 -07:00
sunshineinabox 66b6b46716 Use device features to enable to disable LogicOp Extended Dynamic State
Improve index counting
2024-05-27 23:11:39 -07:00
sunshineinabox 0049585a36 Enable if supported. 2024-05-27 23:11:39 -07:00
sunshineinabox c728a3b6a4 ExtDynamicState2 2024-05-27 23:11:39 -07:00
sunshineinabox cee5ae5551 Some missed values 2024-05-27 23:11:39 -07:00
sunshineinabox 398ca7ad82 Revert unrelated changes. 2024-05-27 23:11:39 -07:00
sunshineinabox eaedc3ec9e Use Viewport and Scissor with count.
Topology Dynamic State is not working as intended. Need to add check to set correct Topology class. Circle back to this later. For now revert it.

Some minor fixes.
2024-05-27 23:11:39 -07:00
sunshineinabox e7fbc9a1be Use Correct namespace 2024-05-27 23:11:39 -07:00
sunshineinabox 506f25054d LineWidth is not supported on MoltenVK 2024-05-27 23:11:39 -07:00
sunshineinabox 1befb5bd8f Check if widelines is supported. 2024-05-27 23:11:39 -07:00
sunshineinabox 5894ef043b No need to by reference 2024-05-27 23:11:38 -07:00
sunshineinabox 07ac4192cd Resolve MoltenVK (future version) warning.
Flags are not set for deriving pipelines so remove unnecessary basePipelineIndex value.
2024-05-27 23:11:38 -07:00
sunshineinabox 24e6105e6f Primitive Topolgy DynamicState maybe causing performance degredation. 2024-05-27 23:11:38 -07:00
sunshineinabox 5f02e28017 More Dynamic States 2024-05-27 23:11:38 -07:00
sunshineinabox 4933888a9d Make StencilOp, FrontFace and CullMode Dynamic States. Also prevent Vertex Input Binding Stride dynamic state from enabling with MoltenVK. 2024-05-27 23:11:38 -07:00
sunshineinabox e6e5829abf Dynamic state for Depth Bounds should not be passed to PipelineDynamicStateCreateInfo as the command to set them is never called.
Do not pass pointer to viewport and scissor as those dynamic states should be supported on all devices.

Same as above for DepthBias values.
2024-05-27 23:11:38 -07:00
21 changed files with 1317 additions and 610 deletions

View File

@ -2,6 +2,7 @@ namespace Ryujinx.Graphics.GAL
{
public enum Face
{
None = 0,
Front = 0x404,
Back = 0x405,
FrontAndBack = 0x408,

View File

@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.GAL
void SetDepthMode(DepthMode mode);
void SetDepthTest(DepthTestDescriptor depthTest);
void SetFaceCulling(bool enable, Face face);
void SetFaceCulling(Face face);
void SetFrontFace(FrontFace frontFace);

View File

@ -3,18 +3,16 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
struct SetFaceCullingCommand : IGALCommand, IGALCommand<SetFaceCullingCommand>
{
public readonly CommandType CommandType => CommandType.SetFaceCulling;
private bool _enable;
private Face _face;
public void Set(bool enable, Face face)
public void Set(Face face)
{
_enable = enable;
_face = face;
}
public static void Run(ref SetFaceCullingCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
renderer.Pipeline.SetFaceCulling(command._enable, command._face);
renderer.Pipeline.SetFaceCulling(command._face);
}
}
}

View File

@ -165,9 +165,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading
_renderer.QueueCommand();
}
public void SetFaceCulling(bool enable, Face face)
public void SetFaceCulling(Face face)
{
_renderer.New<SetFaceCullingCommand>().Set(enable, face);
_renderer.New<SetFaceCullingCommand>().Set(face);
_renderer.QueueCommand();
}

View File

@ -51,11 +51,12 @@ namespace Ryujinx.Graphics.GAL
public StencilTestDescriptor StencilTest;
public FrontFace FrontFace;
public Face CullMode;
public bool CullEnable;
public PolygonModeMask BiasEnable;
public float LineWidth;
public bool AlphaToCoverageEnable;
public bool AlphaToOneEnable;
// TODO: Polygon mode.
public bool DepthClampEnable;
public bool RasterizerDiscard;
@ -63,6 +64,9 @@ namespace Ryujinx.Graphics.GAL
public bool PrimitiveRestartEnable;
public uint PatchControlPoints;
public float DepthBiasUnits;
public float DepthBiasFactor;
public DepthMode DepthMode;
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)

View File

@ -854,6 +854,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
enables |= (depthBias.FillEnable ? PolygonModeMask.Fill : 0);
_pipeline.BiasEnable = enables;
_pipeline.DepthBiasUnits = units / 2f;
_pipeline.DepthBiasFactor = factor;
_context.Renderer.Pipeline.SetDepthBias(enables, factor, units / 2f, clamp);
}
@ -1026,7 +1029,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
float width = _state.State.LineWidthSmooth;
bool smooth = _state.State.LineSmoothEnable;
_pipeline.LineWidth = width;
_context.Renderer.Pipeline.SetLineParameters(width, smooth);
}
@ -1196,9 +1198,16 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
var yControl = _state.State.YControl;
var face = _state.State.FaceState;
_pipeline.CullEnable = face.CullEnable;
if (face.CullEnable)
{
_pipeline.CullMode = face.CullFace;
_context.Renderer.Pipeline.SetFaceCulling(face.CullEnable, face.CullFace);
_context.Renderer.Pipeline.SetFaceCulling(face.CullFace);
}
else
{
_pipeline.CullMode = Face.None;
_context.Renderer.Pipeline.SetFaceCulling(Face.None);
}
UpdateFrontFace(yControl, face.FrontFace);
}
@ -1388,6 +1397,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
bool alphaToCoverageEnable = (_state.State.MultisampleControl & 1) != 0;
bool alphaToOneEnable = (_state.State.MultisampleControl & 0x10) != 0;
_pipeline.AlphaToCoverageEnable = alphaToCoverageEnable;
_pipeline.AlphaToOneEnable = alphaToOneEnable;
_context.Renderer.Pipeline.SetMultisampleState(new MultisampleDescriptor(
alphaToCoverageEnable,
_state.State.AlphaToCoverageDitherEnable,

View File

@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 2;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 7131;
private const uint CodeGenVersion = 7320;
private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data";

View File

@ -915,11 +915,11 @@ namespace Ryujinx.Graphics.OpenGL
_depthTestEnable = depthTest.TestEnable;
}
public void SetFaceCulling(bool enable, Face face)
public void SetFaceCulling(Face face)
{
_cullEnable = enable;
_cullEnable = face != Face.None;
if (!enable)
if (!_cullEnable)
{
GL.Disable(EnableCap.CullFace);
return;

View File

@ -222,30 +222,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.And:
if (type == AtomSize.S32 || type == AtomSize.U32)
case AtomOp.Min:
if (type == AtomSize.S32)
{
res = context.AtomicAnd(storageKind, e0, e1, value);
res = context.AtomicMinS32(storageKind, e0, e1, value);
}
else
else if (type == AtomSize.U32)
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Xor:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicXor(storageKind, e0, e1, value);
}
else
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Or:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicOr(storageKind, e0, e1, value);
res = context.AtomicMinU32(storageKind, e0, e1, value);
}
else
{
@ -266,20 +250,49 @@ namespace Ryujinx.Graphics.Shader.Instructions
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Min:
if (type == AtomSize.S32)
case AtomOp.And:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicMinS32(storageKind, e0, e1, value);
}
else if (type == AtomSize.U32)
{
res = context.AtomicMinU32(storageKind, e0, e1, value);
res = context.AtomicAnd(storageKind, e0, e1, value);
}
else
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Or:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicOr(storageKind, e0, e1, value);
}
else
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Xor:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicXor(storageKind, e0, e1, value);
}
else
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
case AtomOp.Exch:
if (type == AtomSize.S32 || type == AtomSize.U32)
{
res = context.AtomicSwap(storageKind, e0, e1, value);
}
else
{
context.TranslatorContext.GpuAccessor.Log($"Invalid reduction type: {type}.");
}
break;
default:
context.TranslatorContext.GpuAccessor.Log($"Invalid atomic operation: {op}.");
break;
}
return res;

View File

@ -238,6 +238,7 @@ namespace Ryujinx.Graphics.Vulkan
Face.Back => CullModeFlags.BackBit,
Face.Front => CullModeFlags.FrontBit,
Face.FrontAndBack => CullModeFlags.FrontAndBack,
Face.None => CullModeFlags.None,
_ => LogInvalidAndReturn(face, nameof(Face), CullModeFlags.BackBit),
};
}
@ -310,6 +311,25 @@ namespace Ryujinx.Graphics.Vulkan
};
}
public static PrimitiveTopology ConvertToClass(this PrimitiveTopology topology)
{
return topology switch
{
PrimitiveTopology.PointList => PrimitiveTopology.PointList,
PrimitiveTopology.LineList or
PrimitiveTopology.LineStrip or
PrimitiveTopology.LineListWithAdjacency or
PrimitiveTopology.LineStripWithAdjacency => PrimitiveTopology.LineList,
PrimitiveTopology.TriangleList or
PrimitiveTopology.TriangleStrip or
PrimitiveTopology.TriangleFan or
PrimitiveTopology.TriangleListWithAdjacency or
PrimitiveTopology.TriangleStripWithAdjacency => PrimitiveTopology.TriangleStrip,
PrimitiveTopology.PatchList => PrimitiveTopology.PatchList,
_ => LogInvalidAndReturn(topology, nameof(PrimitiveTopology), PrimitiveTopology.TriangleStrip),
};
}
public static StencilOp Convert(this GAL.StencilOp op)
{
return op switch

View File

@ -31,6 +31,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly bool SupportsShaderStorageImageMultisample;
public readonly bool SupportsConditionalRendering;
public readonly bool SupportsExtendedDynamicState;
public readonly PhysicalDeviceExtendedDynamicState2FeaturesEXT SupportsExtendedDynamicState2;
public readonly bool SupportsMultiView;
public readonly bool SupportsNullDescriptors;
public readonly bool SupportsPushDescriptors;
@ -46,6 +47,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly bool SupportsViewportArray2;
public readonly bool SupportsHostImportedMemory;
public readonly bool SupportsDepthClipControl;
public readonly bool SupportsWideLines;
public readonly bool SupportsAttachmentFeedbackLoop;
public readonly bool SupportsDynamicAttachmentFeedbackLoop;
public readonly uint SubgroupSize;
@ -54,6 +56,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly uint VertexBufferAlignment;
public readonly uint SubTexelPrecisionBits;
public readonly ulong MinResourceAlignment;
public readonly uint MaxTessellationPatchSize;
public HardwareCapabilities(
bool supportsIndexTypeUint8,
@ -71,6 +74,8 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsShaderStorageImageMultisample,
bool supportsConditionalRendering,
bool supportsExtendedDynamicState,
PhysicalDeviceExtendedDynamicState2FeaturesEXT supportsExtendedDynamicState2,
uint maxTessellationPatchSize,
bool supportsMultiView,
bool supportsNullDescriptors,
bool supportsPushDescriptors,
@ -86,6 +91,7 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsViewportArray2,
bool supportsHostImportedMemory,
bool supportsDepthClipControl,
bool supportsWideLines,
bool supportsAttachmentFeedbackLoop,
bool supportsDynamicAttachmentFeedbackLoop,
uint subgroupSize,
@ -110,6 +116,8 @@ namespace Ryujinx.Graphics.Vulkan
SupportsShaderStorageImageMultisample = supportsShaderStorageImageMultisample;
SupportsConditionalRendering = supportsConditionalRendering;
SupportsExtendedDynamicState = supportsExtendedDynamicState;
SupportsExtendedDynamicState2 = supportsExtendedDynamicState2;
MaxTessellationPatchSize = maxTessellationPatchSize;
SupportsMultiView = supportsMultiView;
SupportsNullDescriptors = supportsNullDescriptors;
SupportsPushDescriptors = supportsPushDescriptors;
@ -125,6 +133,7 @@ namespace Ryujinx.Graphics.Vulkan
SupportsViewportArray2 = supportsViewportArray2;
SupportsHostImportedMemory = supportsHostImportedMemory;
SupportsDepthClipControl = supportsDepthClipControl;
SupportsWideLines = supportsWideLines;
SupportsAttachmentFeedbackLoop = supportsAttachmentFeedbackLoop;
SupportsDynamicAttachmentFeedbackLoop = supportsDynamicAttachmentFeedbackLoop;
SubgroupSize = subgroupSize;

View File

@ -1,3 +1,5 @@
using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader;
using Silk.NET.Vulkan;
@ -87,6 +89,9 @@ namespace Ryujinx.Graphics.Vulkan
private bool _tfEnabled;
private bool _tfActive;
private readonly bool _supportExtDynamic;
private readonly bool _supportExtDynamic2;
private FeedbackLoopAspects _feedbackLoop;
private bool _passWritesDepthStencil;
@ -126,7 +131,11 @@ namespace Ryujinx.Graphics.Vulkan
_storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets];
_newState.Initialize();
_supportExtDynamic = gd.Capabilities.SupportsExtendedDynamicState;
_supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2;
_newState.Initialize(gd.Capabilities);
}
public void Initialize()
@ -632,19 +641,48 @@ namespace Ryujinx.Graphics.Vulkan
{
if (texture is TextureView srcTexture)
{
var oldCullMode = _newState.CullMode;
var oldStencilTestEnable = _newState.StencilTestEnable;
var oldDepthTestEnable = _newState.DepthTestEnable;
var oldDepthWriteEnable = _newState.DepthWriteEnable;
var oldTopology = _newState.Topology;
var oldViewports = DynamicState.Viewports;
var oldViewportsCount = _newState.ViewportsCount;
CullModeFlags oldCullMode;
bool oldStencilTestEnable;
bool oldDepthTestEnable;
bool oldDepthWriteEnable;
Silk.NET.Vulkan.PrimitiveTopology oldTopology;
Array16<Silk.NET.Vulkan.Viewport> oldViewports = DynamicState.Viewports;
uint oldViewportsCount;
if (_supportExtDynamic)
{
oldCullMode = DynamicState.CullMode;
oldStencilTestEnable = DynamicState.StencilTestEnable;
oldDepthTestEnable = DynamicState.DepthTestEnable;
oldDepthWriteEnable = DynamicState.DepthWriteEnable;
oldTopology = DynamicState.Topology;
oldViewportsCount = DynamicState.ViewportsCount;
}
else
{
oldCullMode = _newState.CullMode;
oldStencilTestEnable = _newState.StencilTestEnable;
oldDepthTestEnable = _newState.DepthTestEnable;
oldDepthWriteEnable = _newState.DepthWriteEnable;
oldTopology = _newState.Topology;
oldViewportsCount = _newState.ViewportsCount;
}
if (_supportExtDynamic)
{
DynamicState.SetCullMode(CullModeFlags.None);
DynamicState.SetDepthTestBool(false, false);
DynamicState.SetStencilTest(false);
}
else
{
_newState.CullMode = CullModeFlags.None;
_newState.StencilTestEnable = false;
_newState.DepthTestEnable = false;
_newState.DepthWriteEnable = false;
SignalStateChange();
}
Gd.HelperShader.DrawTexture(
Gd,
@ -654,15 +692,26 @@ namespace Ryujinx.Graphics.Vulkan
srcRegion,
dstRegion);
_newState.Topology = oldTopology;
if (_supportExtDynamic)
{
DynamicState.SetCullMode(oldCullMode);
DynamicState.SetStencilTest(oldStencilTestEnable);
DynamicState.SetDepthTestBool(oldDepthTestEnable, oldDepthWriteEnable);
DynamicState.SetPrimitiveTopology(oldTopology);
}
else
{
_newState.CullMode = oldCullMode;
_newState.StencilTestEnable = oldStencilTestEnable;
_newState.DepthTestEnable = oldDepthTestEnable;
_newState.DepthWriteEnable = oldDepthWriteEnable;
_newState.Topology = oldTopology;
_newState.ViewportsCount = oldViewportsCount;
}
DynamicState.SetViewports(ref oldViewports, oldViewportsCount);
_newState.ViewportsCount = oldViewportsCount;
SignalStateChange();
}
}
@ -792,49 +841,100 @@ namespace Ryujinx.Graphics.Vulkan
public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
{
DynamicState.SetDepthBias(factor, units, clamp);
bool depthBiasEnable = (enables != 0) && (factor != 0 && units != 0);
bool changed = false;
_newState.DepthBiasEnable = enables != 0;
if (_supportExtDynamic2)
{
DynamicState.SetDepthBiasEnable(depthBiasEnable);
}
else if (_newState.DepthBiasEnable != depthBiasEnable)
{
_newState.DepthBiasEnable = depthBiasEnable;
changed = true;
}
if (depthBiasEnable)
{
DynamicState.SetDepthBias(factor, units, clamp);
}
if (changed)
{
SignalStateChange();
}
}
public void SetDepthClamp(bool clamp)
{
_newState.DepthClampEnable = clamp;
SignalStateChange();
}
public void SetDepthMode(DepthMode mode)
{
bool oldMode = _newState.DepthMode;
_newState.DepthMode = mode == DepthMode.MinusOneToOne;
if (_newState.DepthMode != oldMode)
bool newMode = mode == DepthMode.MinusOneToOne;
if (_newState.DepthMode == newMode)
{
SignalStateChange();
return;
}
_newState.DepthMode = newMode;
SignalStateChange();
}
public void SetDepthTest(DepthTestDescriptor depthTest)
{
if (_supportExtDynamic)
{
DynamicState.SetDepthTestBool(depthTest.TestEnable, depthTest.WriteEnable);
if (depthTest.TestEnable)
{
DynamicState.SetDepthTestCompareOp(depthTest.Func.Convert());
}
}
else
{
_newState.DepthTestEnable = depthTest.TestEnable;
_newState.DepthWriteEnable = depthTest.WriteEnable;
_newState.DepthCompareOp = depthTest.Func.Convert();
UpdatePassDepthStencil();
SignalStateChange();
}
public void SetFaceCulling(bool enable, Face face)
UpdatePassDepthStencil();
}
public void SetFaceCulling(Face face)
{
_newState.CullMode = enable ? face.Convert() : CullModeFlags.None;
if (_supportExtDynamic)
{
DynamicState.SetCullMode(face.Convert());
}
else
{
_newState.CullMode = face.Convert();
SignalStateChange();
}
}
public void SetFrontFace(FrontFace frontFace)
{
if (_supportExtDynamic)
{
DynamicState.SetFrontFace(frontFace.Convert());
}
else
{
_newState.FrontFace = frontFace.Convert();
SignalStateChange();
}
}
public void SetImage(ShaderStage stage, int binding, ITexture image)
{
@ -872,28 +972,56 @@ namespace Ryujinx.Graphics.Vulkan
public void SetLineParameters(float width, bool smooth)
{
_newState.LineWidth = width;
SignalStateChange();
if (!Gd.IsMoltenVk)
{
DynamicState.SetLineWidth(Gd.Capabilities.SupportsWideLines ? width : 1.0f);
}
}
public void SetLogicOpState(bool enable, LogicalOp op)
{
// 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 = enable && (Gd.Vendor == Vendor.Nvidia || _newState.Internal.LogicOpsAllowed);
_newState.LogicOpEnable = enable;
if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp)
{
if (logicOpEnable)
{
DynamicState.SetLogicOp(op.Convert());
}
}
else
{
_newState.LogicOp = op.Convert();
}
SignalStateChange();
}
public void SetMultisampleState(MultisampleDescriptor multisample)
{
_newState.AlphaToCoverageEnable = multisample.AlphaToCoverageEnable;
_newState.AlphaToOneEnable = multisample.AlphaToOneEnable;
SignalStateChange();
}
public void SetPatchParameters(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel)
{
if (Gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints)
{
DynamicState.SetPatchControlPoints((uint)vertices);
}
else
{
_newState.PatchControlPoints = (uint)vertices;
SignalStateChange();
}
// TODO: Default levels (likely needs emulation on shaders?)
}
@ -909,12 +1037,21 @@ namespace Ryujinx.Graphics.Vulkan
}
public void SetPrimitiveRestart(bool enable, int index)
{
if (_supportExtDynamic2)
{
DynamicState.SetPrimitiveRestartEnable(enable);
}
else
{
_newState.PrimitiveRestartEnable = enable;
// TODO: What to do about the index?
SignalStateChange();
}
// TODO: What to do about the index?
}
public void SetPrimitiveTopology(PrimitiveTopology topology)
{
_topology = topology;
@ -923,6 +1060,11 @@ namespace Ryujinx.Graphics.Vulkan
_newState.Topology = vkTopology;
if (_supportExtDynamic)
{
DynamicState.SetPrimitiveTopology(vkTopology);
}
SignalStateChange();
}
@ -967,15 +1109,23 @@ namespace Ryujinx.Graphics.Vulkan
}
public void SetRasterizerDiscard(bool discard)
{
if (_supportExtDynamic2)
{
DynamicState.SetRasterizerDiscard(discard);
}
else
{
_newState.RasterizerDiscardEnable = discard;
SignalStateChange();
}
if (!discard && Gd.IsQualcommProprietary)
{
// On Adreno, enabling rasterizer discard somehow corrupts the viewport state.
// Force it to be updated on next use to work around this bug.
DynamicState.ForceAllDirty();
DynamicState.ForceAllDirty(Gd);
}
}
@ -1052,6 +1202,8 @@ namespace Ryujinx.Graphics.Vulkan
ClearScissor = regions[0];
}
DynamicState.ScissorsCount = count;
for (int i = 0; i < count; i++)
{
var region = regions[i];
@ -1061,23 +1213,33 @@ namespace Ryujinx.Graphics.Vulkan
DynamicState.SetScissor(i, new Rect2D(offset, extent));
}
DynamicState.ScissorsCount = count;
if (!_supportExtDynamic)
{
_newState.ScissorsCount = (uint)count;
SignalStateChange();
}
}
public void SetStencilTest(StencilTestDescriptor stencilTest)
{
DynamicState.SetStencilMasks(
(uint)stencilTest.BackFuncMask,
(uint)stencilTest.BackMask,
(uint)stencilTest.BackFuncRef,
(uint)stencilTest.FrontFuncMask,
(uint)stencilTest.FrontMask,
(uint)stencilTest.FrontFuncRef);
if (_supportExtDynamic)
{
DynamicState.SetStencilTestandOp(
stencilTest.BackSFail.Convert(),
stencilTest.BackDpPass.Convert(),
stencilTest.BackDpFail.Convert(),
stencilTest.BackFunc.Convert(),
stencilTest.FrontSFail.Convert(),
stencilTest.FrontDpPass.Convert(),
stencilTest.FrontDpFail.Convert(),
stencilTest.FrontFunc.Convert(),
stencilTest.TestEnable);
_newState.StencilTestEnable = stencilTest.TestEnable;
UpdatePassDepthStencil();
}
else
{
_newState.StencilBackFailOp = stencilTest.BackSFail.Convert();
_newState.StencilBackPassOp = stencilTest.BackDpPass.Convert();
_newState.StencilBackDepthFailOp = stencilTest.BackDpFail.Convert();
@ -1086,11 +1248,20 @@ namespace Ryujinx.Graphics.Vulkan
_newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert();
_newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert();
_newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert();
_newState.StencilTestEnable = stencilTest.TestEnable;
UpdatePassDepthStencil();
SignalStateChange();
}
DynamicState.SetStencilMask((uint)stencilTest.BackFuncMask,
(uint)stencilTest.BackMask,
(uint)stencilTest.BackFuncRef,
(uint)stencilTest.FrontFuncMask,
(uint)stencilTest.FrontMask,
(uint)stencilTest.FrontFuncRef);
}
public void SetStorageBuffers(ReadOnlySpan<BufferAssignment> buffers)
{
_descriptorSetUpdater.SetStorageBuffers(CommandBuffer, buffers);
@ -1207,7 +1378,7 @@ namespace Ryujinx.Graphics.Vulkan
{
int count = Math.Min(Constants.MaxVertexBuffers, vertexBuffers.Length);
_newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, 0, VertexInputRate.Vertex);
_newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, _supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex);
int validCount = 1;
@ -1236,7 +1407,7 @@ namespace Ryujinx.Graphics.Vulkan
_newState.Internal.VertexBindingDescriptions[descriptorIndex] = new VertexInputBindingDescription(
(uint)binding,
(uint)vertexBuffer.Stride,
_supportExtDynamic && (!Gd.IsMoltenVk || Gd.SupportsMTL31) ? null : (uint)vertexBuffer.Stride,
inputRate);
int vbSize = vertexBuffer.Buffer.Size;
@ -1325,9 +1496,13 @@ namespace Ryujinx.Graphics.Vulkan
Clamp(viewport.DepthFar)));
}
if (!_supportExtDynamic)
{
_newState.ViewportsCount = (uint)count;
SignalStateChange();
}
}
public void SwapBuffer(Auto<DisposableBuffer> from, Auto<DisposableBuffer> to)
{
@ -1375,7 +1550,7 @@ namespace Ryujinx.Graphics.Vulkan
_vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length);
_descriptorSetUpdater.SignalCommandBufferChange();
DynamicState.ForceAllDirty();
DynamicState.ForceAllDirty(Gd);
_currentPipelineHandle = 0;
}
@ -1529,9 +1704,10 @@ namespace Ryujinx.Graphics.Vulkan
{
if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
{
_newState.FeedbackLoopDynamicState = true;
DynamicState.SetFeedbackLoop(aspects);
}
else
else if (Gd.Capabilities.SupportsAttachmentFeedbackLoop)
{
_newState.FeedbackLoopAspects = aspects;
}
@ -1591,8 +1767,15 @@ namespace Ryujinx.Graphics.Vulkan
}
// Stencil test being enabled doesn't necessarily mean a write, but it's not critical to check.
if (_supportExtDynamic)
{
_passWritesDepthStencil |= (DynamicState.DepthTestEnable && DynamicState.DepthWriteEnable) || DynamicState.StencilTestEnable;
}
else
{
_passWritesDepthStencil |= (_newState.DepthTestEnable && _newState.DepthWriteEnable) || _newState.StencilTestEnable;
}
}
private bool RecreateGraphicsPipelineIfNeeded()
{

View File

@ -4,6 +4,7 @@ using Silk.NET.Vulkan;
using System;
using Format = Silk.NET.Vulkan.Format;
using PolygonMode = Silk.NET.Vulkan.PolygonMode;
using PrimitiveTopology = Ryujinx.Graphics.GAL.PrimitiveTopology;
namespace Ryujinx.Graphics.Vulkan
{
@ -154,34 +155,37 @@ namespace Ryujinx.Graphics.Vulkan
public static PipelineState ToVulkanPipelineState(this ProgramPipelineState state, VulkanRenderer gd)
{
var extendedDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2;
var extendedDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
PipelineState pipeline = new();
pipeline.Initialize();
pipeline.Initialize(gd.Capabilities);
// It is assumed that Dynamic State is enabled when this conversion is used.
pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None;
pipeline.DepthBoundsTestEnable = false; // Not implemented.
pipeline.DepthClampEnable = state.DepthClampEnable;
pipeline.DepthTestEnable = state.DepthTest.TestEnable;
pipeline.DepthWriteEnable = state.DepthTest.WriteEnable;
pipeline.DepthCompareOp = state.DepthTest.Func.Convert();
pipeline.AlphaToCoverageEnable = state.AlphaToCoverageEnable;
pipeline.AlphaToOneEnable = state.AlphaToOneEnable;
pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne;
pipeline.FrontFace = state.FrontFace.Convert();
pipeline.HasDepthStencil = state.DepthStencilEnable;
pipeline.LineWidth = state.LineWidth;
pipeline.LogicOpEnable = state.LogicOpEnable;
pipeline.LogicOp = state.LogicOp.Convert();
pipeline.PatchControlPoints = state.PatchControlPoints;
pipeline.PolygonMode = PolygonMode.Fill; // Not implemented.
pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable;
pipeline.RasterizerDiscardEnable = state.RasterizerDiscard;
pipeline.SamplesCount = (uint)state.SamplesCount;
pipeline.Topology = gd.TopologyRemap(state.Topology).Convert();
if (!extendedDynamicState)
{
pipeline.DepthCompareOp = state.DepthTest.Func.Convert();
pipeline.CullMode = state.CullMode.Convert();
pipeline.DepthTestEnable = state.DepthTest.TestEnable;
pipeline.DepthWriteEnable = state.DepthTest.WriteEnable;
pipeline.FrontFace = state.FrontFace.Convert();
if (gd.Capabilities.SupportsMultiView)
{
@ -194,9 +198,7 @@ namespace Ryujinx.Graphics.Vulkan
pipeline.ViewportsCount = 1;
}
pipeline.DepthBiasEnable = state.BiasEnable != 0;
// Stencil masks and ref are dynamic, so are 0 in the Vulkan pipeline.
pipeline.StencilTestEnable = state.StencilTest.TestEnable;
pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert();
pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert();
@ -207,10 +209,29 @@ namespace Ryujinx.Graphics.Vulkan
pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert();
pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert();
pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert();
}
pipeline.StencilTestEnable = state.StencilTest.TestEnable;
if (!extendedDynamicState2.ExtendedDynamicState2)
{
pipeline.PrimitiveRestartEnable = state.PrimitiveRestartEnable;
pipeline.RasterizerDiscardEnable = state.RasterizerDiscard;
pipeline.DepthBiasEnable = (state.BiasEnable != 0) &&
(state.DepthBiasFactor != 0 && state.DepthBiasUnits != 0);
}
pipeline.Topology = gd.TopologyRemap(state.Topology).Convert();
if (!extendedDynamicState2.ExtendedDynamicState2LogicOp)
{
pipeline.LogicOp = state.LogicOp.Convert();
}
if (!extendedDynamicState2.ExtendedDynamicState2PatchControlPoints)
{
pipeline.PatchControlPoints = state.PatchControlPoints;
}
pipeline.SamplesCount = (uint)state.SamplesCount;
pipeline.LogicOpEnable = state.LogicOpEnable;
int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount);
int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount);
@ -235,7 +256,7 @@ namespace Ryujinx.Graphics.Vulkan
}
int descriptorIndex = 1;
pipeline.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, 0, VertexInputRate.Vertex);
pipeline.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, extendedDynamicState && (!gd.IsMoltenVk || gd.SupportsMTL31) ? null : 0, VertexInputRate.Vertex);
for (int i = 0; i < vbCount; i++)
{
@ -255,7 +276,7 @@ namespace Ryujinx.Graphics.Vulkan
// TODO: Support divisor > 1
pipeline.Internal.VertexBindingDescriptions[descriptorIndex++] = new VertexInputBindingDescription(
(uint)i + 1,
(uint)alignedStride,
extendedDynamicState && (!gd.IsMoltenVk || gd.SupportsMTL31) ? null : (uint)alignedStride,
inputRate);
}
}

View File

@ -1,6 +1,8 @@
using Ryujinx.Common.Memory;
using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.EXT;
using System;
using System.Numerics;
namespace Ryujinx.Graphics.Vulkan
{
@ -9,6 +11,7 @@ namespace Ryujinx.Graphics.Vulkan
private float _depthBiasSlopeFactor;
private float _depthBiasConstantFactor;
private float _depthBiasClamp;
private bool _depthBiasEnable;
public int ScissorsCount;
private Array16<Rect2D> _scissors;
@ -20,6 +23,23 @@ namespace Ryujinx.Graphics.Vulkan
private uint _frontWriteMask;
private uint _frontReference;
private StencilOp _backFailOp;
private StencilOp _backPassOp;
private StencilOp _backDepthFailOp;
private CompareOp _backCompareOp;
private StencilOp _frontFailOp;
private StencilOp _frontPassOp;
private StencilOp _frontDepthFailOp;
private CompareOp _frontCompareOp;
private float _lineWidth;
public bool StencilTestEnable;
public bool DepthTestEnable;
public bool DepthWriteEnable;
private CompareOp _depthCompareOp;
private Array4<float> _blendConstants;
private FeedbackLoopAspects _feedbackLoopAspects;
@ -27,6 +47,20 @@ namespace Ryujinx.Graphics.Vulkan
public uint ViewportsCount;
public Array16<Viewport> Viewports;
public CullModeFlags CullMode;
private FrontFace _frontFace;
private bool _discard;
private LogicOp _logicOp;
private uint _patchControlPoints;
public PrimitiveTopology Topology;
private bool _primitiveRestartEnable;
[Flags]
private enum DirtyFlags
{
None = 0,
@ -36,7 +70,21 @@ namespace Ryujinx.Graphics.Vulkan
Stencil = 1 << 3,
Viewport = 1 << 4,
FeedbackLoop = 1 << 5,
All = Blend | DepthBias | Scissor | Stencil | Viewport | FeedbackLoop,
CullMode = 1 << 6,
FrontFace = 1 << 7,
DepthTestBool = 1 << 8,
DepthTestCompareOp = 1 << 9,
StencilTestEnableAndStencilOp = 1 << 10,
LineWidth = 1 << 11,
RasterDiscard = 1 << 12,
LogicOp = 1 << 13,
PatchControlPoints = 1 << 14,
PrimitiveRestart = 1 << 15,
PrimitiveTopology = 1 << 16,
DepthBiasEnable = 1 << 17,
Standard = Blend | DepthBias | Scissor | Stencil | Viewport,
Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnableAndStencilOp | PrimitiveTopology,
Extended2 = RasterDiscard | PrimitiveRestart | DepthBiasEnable,
}
private DirtyFlags _dirty;
@ -47,7 +95,6 @@ namespace Ryujinx.Graphics.Vulkan
_blendConstants[1] = g;
_blendConstants[2] = b;
_blendConstants[3] = a;
_dirty |= DirtyFlags.Blend;
}
@ -60,15 +107,64 @@ namespace Ryujinx.Graphics.Vulkan
_dirty |= DirtyFlags.DepthBias;
}
public void SetDepthBiasEnable(bool enable)
{
_depthBiasEnable = enable;
_dirty |= DirtyFlags.DepthBiasEnable;
}
public void SetScissor(int index, Rect2D scissor)
{
_scissors[index] = scissor;
_dirty |= DirtyFlags.Scissor;
}
public void SetStencilMasks(
uint backCompareMask,
public void SetDepthTestBool(bool testEnable, bool writeEnable)
{
DepthTestEnable = testEnable;
DepthWriteEnable = writeEnable;
_dirty |= DirtyFlags.DepthTestBool;
}
public void SetDepthTestCompareOp(CompareOp depthTestOp)
{
_depthCompareOp = depthTestOp;
_dirty |= DirtyFlags.DepthTestCompareOp;
}
public void SetStencilTestandOp(
StencilOp backFailOp,
StencilOp backPassOp,
StencilOp backDepthFailOp,
CompareOp backCompareOp,
StencilOp frontFailOp,
StencilOp frontPassOp,
StencilOp frontDepthFailOp,
CompareOp frontCompareOp,
bool stencilTestEnable)
{
_backFailOp = backFailOp;
_backPassOp = backPassOp;
_backDepthFailOp = backDepthFailOp;
_backCompareOp = backCompareOp;
_frontFailOp = frontFailOp;
_frontPassOp = frontPassOp;
_frontDepthFailOp = frontDepthFailOp;
_frontCompareOp = frontCompareOp;
StencilTestEnable = stencilTestEnable;
_dirty |= DirtyFlags.StencilTestEnableAndStencilOp;
}
public void SetStencilTest(bool stencilTestEnable)
{
StencilTestEnable = stencilTestEnable;
_dirty |= DirtyFlags.StencilTestEnableAndStencilOp;
}
public void SetStencilMask(uint backCompareMask,
uint backWriteMask,
uint backReference,
uint frontCompareMask,
@ -81,27 +177,45 @@ namespace Ryujinx.Graphics.Vulkan
_frontCompareMask = frontCompareMask;
_frontWriteMask = frontWriteMask;
_frontReference = frontReference;
_dirty |= DirtyFlags.Stencil;
}
public void SetViewport(int index, Viewport viewport)
{
Viewports[index] = viewport;
_dirty |= DirtyFlags.Viewport;
}
public void SetViewports(ref Array16<Viewport> viewports, uint viewportsCount)
{
if (!Viewports.Equals(viewports) || ViewportsCount != viewportsCount)
{
Viewports = viewports;
ViewportsCount = viewportsCount;
if (ViewportsCount != 0)
{
_dirty |= DirtyFlags.Viewport;
}
}
}
public void SetCullMode(CullModeFlags cullMode)
{
CullMode = cullMode;
_dirty |= DirtyFlags.CullMode;
}
public void SetFrontFace(FrontFace frontFace)
{
_frontFace = frontFace;
_dirty |= DirtyFlags.FrontFace;
}
public void SetLineWidth(float width)
{
_lineWidth = width;
_dirty |= DirtyFlags.LineWidth;
}
public void SetFeedbackLoop(FeedbackLoopAspects aspects)
{
@ -110,43 +224,149 @@ namespace Ryujinx.Graphics.Vulkan
_dirty |= DirtyFlags.FeedbackLoop;
}
public void ForceAllDirty()
public void SetRasterizerDiscard(bool discard)
{
_dirty = DirtyFlags.All;
_discard = discard;
_dirty |= DirtyFlags.RasterDiscard;
}
public void SetPrimitiveRestartEnable(bool primitiveRestart)
{
_primitiveRestartEnable = primitiveRestart;
_dirty |= DirtyFlags.PrimitiveRestart;
}
public void SetPrimitiveTopology(PrimitiveTopology primitiveTopology)
{
Topology = primitiveTopology;
_dirty |= DirtyFlags.PrimitiveTopology;
}
public void SetLogicOp(LogicOp op)
{
_logicOp = op;
_dirty |= DirtyFlags.LogicOp;
}
public void SetPatchControlPoints(uint points)
{
_patchControlPoints = points;
_dirty |= DirtyFlags.PatchControlPoints;
}
public void ForceAllDirty(VulkanRenderer gd)
{
_dirty = DirtyFlags.Standard;
if (gd.Capabilities.SupportsExtendedDynamicState)
{
_dirty |= DirtyFlags.Extended;
}
if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2)
{
_dirty |= DirtyFlags.Extended2;
if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2LogicOp)
{
_dirty |= DirtyFlags.LogicOp;
}
if (gd.Capabilities.SupportsExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints)
{
_dirty |= DirtyFlags.PatchControlPoints;
}
}
if (!gd.IsMoltenVk)
{
_dirty |= DirtyFlags.LineWidth;
}
if (gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
{
_dirty |= DirtyFlags.FeedbackLoop;
}
}
public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer)
{
Vk api = gd.Api;
if (_dirty.HasFlag(DirtyFlags.Blend))
if (_dirty == DirtyFlags.None)
{
return;
}
var api = gd.Api;
var extendedStateApi = gd.ExtendedDynamicStateApi;
var extendedState2Api = gd.ExtendedDynamicState2Api;
var dynamicFeedbackLoopApi = gd.DynamicFeedbackLoopApi;
DirtyFlags dirtyFlags = _dirty;
while (dirtyFlags != DirtyFlags.None)
{
int bitIndex = BitOperations.TrailingZeroCount((uint)dirtyFlags);
DirtyFlags currentFlag = (DirtyFlags)(1 << bitIndex);
switch (currentFlag)
{
case DirtyFlags.Blend:
RecordBlend(api, commandBuffer);
}
if (_dirty.HasFlag(DirtyFlags.DepthBias))
{
break;
case DirtyFlags.DepthBias:
RecordDepthBias(api, commandBuffer);
break;
case DirtyFlags.Scissor:
RecordScissor(gd, commandBuffer);
break;
case DirtyFlags.Stencil:
RecordStencil(api, commandBuffer);
break;
case DirtyFlags.Viewport:
RecordViewport(gd, commandBuffer);
break;
case DirtyFlags.FeedbackLoop:
RecordFeedbackLoop(dynamicFeedbackLoopApi, commandBuffer);
break;
case DirtyFlags.CullMode:
RecordCullMode(extendedStateApi, commandBuffer);
break;
case DirtyFlags.FrontFace:
RecordFrontFace(extendedStateApi, commandBuffer);
break;
case DirtyFlags.DepthTestBool:
RecordDepthTestBool(extendedStateApi, commandBuffer);
break;
case DirtyFlags.DepthTestCompareOp:
RecordDepthTestCompareOp(extendedStateApi, commandBuffer);
break;
case DirtyFlags.StencilTestEnableAndStencilOp:
RecordStencilTestAndOp(extendedStateApi, commandBuffer);
break;
case DirtyFlags.LineWidth:
RecordLineWidth(api, commandBuffer);
break;
case DirtyFlags.RasterDiscard:
RecordRasterizationDiscard(extendedState2Api, commandBuffer);
break;
case DirtyFlags.LogicOp:
RecordLogicOp(extendedState2Api, commandBuffer);
break;
case DirtyFlags.PatchControlPoints:
RecordPatchControlPoints(extendedState2Api, commandBuffer);
break;
case DirtyFlags.PrimitiveRestart:
RecordPrimitiveRestartEnable(gd, commandBuffer);
break;
case DirtyFlags.PrimitiveTopology:
RecordPrimitiveTopology(extendedStateApi, commandBuffer);
break;
case DirtyFlags.DepthBiasEnable:
RecordDepthBiasEnable(extendedState2Api, commandBuffer);
break;
}
if (_dirty.HasFlag(DirtyFlags.Scissor))
{
RecordScissor(api, commandBuffer);
}
if (_dirty.HasFlag(DirtyFlags.Stencil))
{
RecordStencilMasks(api, commandBuffer);
}
if (_dirty.HasFlag(DirtyFlags.Viewport))
{
RecordViewport(api, commandBuffer);
}
if (_dirty.HasFlag(DirtyFlags.FeedbackLoop) && gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
{
RecordFeedbackLoop(gd.DynamicFeedbackLoopApi, commandBuffer);
dirtyFlags &= ~currentFlag;
}
_dirty = DirtyFlags.None;
@ -162,15 +382,27 @@ namespace Ryujinx.Graphics.Vulkan
api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor);
}
private void RecordScissor(Vk api, CommandBuffer commandBuffer)
private readonly void RecordDepthBiasEnable(ExtExtendedDynamicState2 gd, CommandBuffer commandBuffer)
{
gd.CmdSetDepthBiasEnable(commandBuffer, _depthBiasEnable);
}
private void RecordScissor(VulkanRenderer gd, CommandBuffer commandBuffer)
{
if (ScissorsCount != 0)
{
api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan());
if (gd.Capabilities.SupportsExtendedDynamicState)
{
gd.ExtendedDynamicStateApi.CmdSetScissorWithCount(commandBuffer, (uint)ScissorsCount, _scissors.AsSpan());
}
else
{
gd.Api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan());
}
}
}
private readonly void RecordStencilMasks(Vk api, CommandBuffer commandBuffer)
private readonly void RecordStencil(Vk api, CommandBuffer commandBuffer)
{
api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask);
api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask);
@ -180,12 +412,107 @@ namespace Ryujinx.Graphics.Vulkan
api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference);
}
private void RecordViewport(Vk api, CommandBuffer commandBuffer)
private readonly void RecordStencilTestAndOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer)
{
if (ViewportsCount != 0)
{
api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan());
api.CmdSetStencilTestEnable(commandBuffer, StencilTestEnable);
api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceBackBit, _backFailOp, _backPassOp, _backDepthFailOp, _backCompareOp);
api.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontFailOp, _frontPassOp, _frontDepthFailOp, _frontCompareOp);
}
private void RecordViewport(VulkanRenderer gd, CommandBuffer commandBuffer)
{
if (ViewportsCount == 0)
{
return;
}
if (gd.Capabilities.SupportsExtendedDynamicState)
{
gd.ExtendedDynamicStateApi.CmdSetViewportWithCount(commandBuffer, ViewportsCount, Viewports.AsSpan());
}
else
{
gd.Api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan());
}
}
private readonly void RecordCullMode(ExtExtendedDynamicState api, CommandBuffer commandBuffer)
{
api.CmdSetCullMode(commandBuffer, CullMode);
}
private readonly void RecordFrontFace(ExtExtendedDynamicState api, CommandBuffer commandBuffer)
{
api.CmdSetFrontFace(commandBuffer, _frontFace);
}
private readonly void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer)
{
api.CmdSetDepthTestEnable(commandBuffer, DepthTestEnable);
api.CmdSetDepthWriteEnable(commandBuffer, DepthWriteEnable);
}
private readonly void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer)
{
api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp);
}
private readonly void RecordRasterizationDiscard(ExtExtendedDynamicState2 extendedDynamicState2Api, CommandBuffer commandBuffer)
{
extendedDynamicState2Api.CmdSetRasterizerDiscardEnable(commandBuffer, _discard);
}
private readonly void RecordPrimitiveRestartEnable(VulkanRenderer gd, CommandBuffer commandBuffer)
{
bool primitiveRestartEnable = _primitiveRestartEnable;
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;
// Cannot disable primitiveRestartEnable for these Topologies on MacOS.
if (gd.IsMoltenVk)
{
primitiveRestartEnable = true;
}
gd.ExtendedDynamicState2Api.CmdSetPrimitiveRestartEnable(commandBuffer, primitiveRestartEnable);
}
private readonly void RecordPrimitiveTopology(ExtExtendedDynamicState extendedDynamicStateApi, CommandBuffer commandBuffer)
{
extendedDynamicStateApi.CmdSetPrimitiveTopology(commandBuffer, Topology);
}
private readonly void RecordLogicOp(ExtExtendedDynamicState2 extendedDynamicState2Api, CommandBuffer commandBuffer)
{
extendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp);
}
private readonly void RecordPatchControlPoints(ExtExtendedDynamicState2 extendedDynamicState2Api, CommandBuffer commandBuffer)
{
extendedDynamicState2Api.CmdSetPatchControlPoints(commandBuffer, _patchControlPoints);
}
private readonly void RecordLineWidth(Vk api, CommandBuffer commandBuffer)
{
api.CmdSetLineWidth(commandBuffer, _lineWidth);
}
private readonly void RecordFeedbackLoop(ExtAttachmentFeedbackLoopDynamicState api, CommandBuffer commandBuffer)

File diff suppressed because it is too large Load Diff

View File

@ -11,20 +11,14 @@ namespace Ryujinx.Graphics.Vulkan
{
public ulong Id0;
public ulong Id1;
public ulong Id2;
public ulong Id3;
public ulong Id4;
public ulong Id5;
public ulong Id6;
public ulong Id7;
public ulong Id8;
private readonly uint VertexAttributeDescriptionsCount => (byte)((Id5 >> 38) & 0xFF);
private readonly uint VertexBindingDescriptionsCount => (byte)((Id5 >> 46) & 0xFF);
private readonly uint ColorBlendAttachmentStateCount => (byte)((Id6 >> 8) & 0xFF);
private readonly bool HasDepthStencil => ((Id6 >> 63) & 0x1) != 0UL;
private readonly uint VertexAttributeDescriptionsCount => (byte)((Id0 >> 38) & 0xFF);
private readonly uint VertexBindingDescriptionsCount => (byte)((Id0 >> 46) & 0xFF);
private readonly uint ColorBlendAttachmentStateCount => (byte)((Id1 >> 8) & 0xFF);
private readonly bool HasDepthStencil => ((Id1 >> 63) & 0x1) != 0UL;
public Array32<VertexInputAttributeDescription> VertexAttributeDescriptions;
public Array33<VertexInputBindingDescription> VertexBindingDescriptions;
@ -40,9 +34,7 @@ namespace Ryujinx.Graphics.Vulkan
public bool Equals(ref PipelineUid other)
{
if (!Unsafe.As<ulong, Vector256<byte>>(ref Id0).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id0)) ||
!Unsafe.As<ulong, Vector256<byte>>(ref Id4).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id4)) ||
!Unsafe.As<ulong, Vector128<byte>>(ref Id7).Equals(Unsafe.As<ulong, Vector128<byte>>(ref other.Id7)))
if (!Unsafe.As<ulong, Vector256<byte>>(ref Id0).Equals(Unsafe.As<ulong, Vector256<byte>>(ref other.Id0)))
{
return false;
}
@ -80,12 +72,7 @@ namespace Ryujinx.Graphics.Vulkan
ulong hash64 = Id0 * 23 ^
Id1 * 23 ^
Id2 * 23 ^
Id3 * 23 ^
Id4 * 23 ^
Id5 * 23 ^
Id6 * 23 ^
Id7 * 23 ^
Id8 * 23;
Id3 * 23;
for (int i = 0; i < (int)VertexAttributeDescriptionsCount; i++)
{

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using PrimitiveTopology = Silk.NET.Vulkan.PrimitiveTopology;
namespace Ryujinx.Graphics.Vulkan
{
@ -528,7 +529,7 @@ namespace Ryujinx.Graphics.Vulkan
public void CreateBackgroundComputePipeline()
{
PipelineState pipeline = new();
pipeline.Initialize();
pipeline.Initialize(_gd.Capabilities);
pipeline.Stages[0] = _shaders[0].GetInfo();
pipeline.StagesCount = 1;

View File

@ -71,16 +71,22 @@ namespace Ryujinx.Graphics.Vulkan
_buffer = autoBuffer;
if (!gd.Capabilities.SupportsExtendedDynamicState)
{
state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)stride;
}
}
return;
}
autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int size);
if (!gd.Capabilities.SupportsExtendedDynamicState)
{
// The original stride must be reapplied in case it was rewritten.
state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride;
}
if (_offset >= size)
{

View File

@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Vulkan
{
if (_count != 0)
{
if (_gd.Capabilities.SupportsExtendedDynamicState)
if (_gd.Capabilities.SupportsExtendedDynamicState && (_gd.SupportsMTL31 || !_gd.IsMoltenVk))
{
_gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2(
cbs.CommandBuffer,

View File

@ -23,6 +23,7 @@ namespace Ryujinx.Graphics.Vulkan
private static readonly string[] _desirableExtensions = {
ExtConditionalRendering.ExtensionName,
ExtExtendedDynamicState.ExtensionName,
ExtExtendedDynamicState2.ExtensionName,
ExtTransformFeedback.ExtensionName,
KhrDrawIndirectCount.ExtensionName,
KhrPushDescriptor.ExtensionName,
@ -314,6 +315,17 @@ namespace Ryujinx.Graphics.Vulkan
features2.PNext = &supportedFeaturesCustomBorderColor;
}
PhysicalDeviceExtendedDynamicState2FeaturesEXT supportedFeaturesExtExtendedDynamicState2 = new()
{
SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
PNext = features2.PNext,
};
if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName))
{
features2.PNext = &supportedFeaturesExtExtendedDynamicState2;
}
PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT supportedFeaturesPrimitiveTopologyListRestart = new()
{
SType = StructureType.PhysicalDevicePrimitiveTopologyListRestartFeaturesExt,
@ -416,6 +428,7 @@ namespace Ryujinx.Graphics.Vulkan
TessellationShader = supportedFeatures.TessellationShader,
VertexPipelineStoresAndAtomics = supportedFeatures.VertexPipelineStoresAndAtomics,
RobustBufferAccess = useRobustBufferAccess,
WideLines = supportedFeatures.WideLines,
SampleRateShading = supportedFeatures.SampleRateShading,
};
@ -473,6 +486,20 @@ namespace Ryujinx.Graphics.Vulkan
pExtendedFeatures = &featuresExtendedDynamicState;
if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName))
{
var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT()
{
SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
PNext = pExtendedFeatures,
ExtendedDynamicState2 = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2,
ExtendedDynamicState2LogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp,
ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints,
};
pExtendedFeatures = &featuresExtendedDynamicState2;
}
var featuresVk11 = new PhysicalDeviceVulkan11Features
{
SType = StructureType.PhysicalDeviceVulkan11Features,

View File

@ -35,6 +35,7 @@ namespace Ryujinx.Graphics.Vulkan
internal KhrSwapchain SwapchainApi { get; private set; }
internal ExtConditionalRendering ConditionalRenderingApi { get; private set; }
internal ExtExtendedDynamicState ExtendedDynamicStateApi { get; private set; }
internal ExtExtendedDynamicState2 ExtendedDynamicState2Api { get; private set; }
internal KhrPushDescriptor PushDescriptorApi { get; private set; }
internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
@ -90,6 +91,7 @@ namespace Ryujinx.Graphics.Vulkan
internal bool IsIntelArc { get; private set; }
internal bool IsQualcommProprietary { get; private set; }
internal bool IsMoltenVk { get; private set; }
internal bool SupportsMTL31 { get; private set; }
internal bool IsTBDR { get; private set; }
internal bool IsSharedMemory { get; private set; }
@ -118,6 +120,8 @@ namespace Ryujinx.Graphics.Vulkan
// Any device running on MacOS is using MoltenVK, even Intel and AMD vendors.
IsMoltenVk = true;
SupportsMTL31 = OperatingSystem.IsMacOSVersionAtLeast(14);
}
}
@ -135,6 +139,11 @@ namespace Ryujinx.Graphics.Vulkan
ExtendedDynamicStateApi = extendedDynamicStateApi;
}
if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExtendedDynamicState2 extendedDynamicState2Api))
{
ExtendedDynamicState2Api = extendedDynamicState2Api;
}
if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrPushDescriptor pushDescriptorApi))
{
PushDescriptorApi = pushDescriptorApi;
@ -229,6 +238,11 @@ namespace Ryujinx.Graphics.Vulkan
SType = StructureType.PhysicalDevicePrimitiveTopologyListRestartFeaturesExt,
};
PhysicalDeviceExtendedDynamicState2FeaturesEXT featuresExtendedDynamicState2 = new()
{
SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
};
PhysicalDeviceRobustness2FeaturesEXT featuresRobustness2 = new()
{
SType = StructureType.PhysicalDeviceRobustness2FeaturesExt,
@ -269,6 +283,12 @@ namespace Ryujinx.Graphics.Vulkan
features2.PNext = &featuresPrimitiveTopologyListRestart;
}
if (_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName))
{
featuresExtendedDynamicState2.PNext = features2.PNext;
features2.PNext = &featuresExtendedDynamicState2;
}
if (_physicalDevice.IsDeviceExtensionPresent("VK_EXT_robustness2"))
{
featuresRobustness2.PNext = features2.PNext;
@ -402,6 +422,10 @@ namespace Ryujinx.Graphics.Vulkan
properties.Limits.FramebufferDepthSampleCounts &
properties.Limits.FramebufferStencilSampleCounts;
// Temporarily disable this, can be added back at a later date, make it easy to re-enable.
// Disabled because currently causing Device Lost error on NVIDIA.
featuresExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints = false;
Capabilities = new HardwareCapabilities(
_physicalDevice.IsDeviceExtensionPresent("VK_EXT_index_type_uint8"),
supportsCustomBorderColor,
@ -418,6 +442,8 @@ namespace Ryujinx.Graphics.Vulkan
features2.Features.ShaderStorageImageMultisample,
_physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName),
_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName),
featuresExtendedDynamicState2,
_physicalDevice.PhysicalDeviceProperties.Limits.MaxTessellationPatchSize,
features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue
featuresRobustness2.NullDescriptor || IsMoltenVk,
supportsPushDescriptors && !IsMoltenVk,
@ -433,6 +459,7 @@ namespace Ryujinx.Graphics.Vulkan
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
supportsDepthClipControl && featuresDepthClipControl.DepthClipControl,
_physicalDevice.PhysicalDeviceFeatures.WideLines,
supportsAttachmentFeedbackLoop && featuresAttachmentFeedbackLoop.AttachmentFeedbackLoopLayout,
supportsDynamicAttachmentFeedbackLoop && featuresDynamicAttachmentFeedbackLoop.AttachmentFeedbackLoopDynamicState,
propertiesSubgroup.SubgroupSize,