From d5f9ed6a2ee4e2313c9c69be2bc3fb2c02f89d47 Mon Sep 17 00:00:00 2001 From: sunshineinabox Date: Fri, 17 May 2024 15:02:56 -0700 Subject: [PATCH] Use device features to enable to disable LogicOp Extended Dynamic State Improve index counting --- src/Ryujinx.Graphics.Vulkan/PipelineBase.cs | 38 +++--- .../PipelineConverter.cs | 18 +-- .../PipelineDynamicState.cs | 115 +++++++++++------- src/Ryujinx.Graphics.Vulkan/PipelineState.cs | 86 +++++++++---- .../VulkanInitialization.cs | 10 +- src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 8 +- 6 files changed, 173 insertions(+), 102 deletions(-) diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 009714c4b..5ae36a4b0 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -84,8 +84,8 @@ namespace Ryujinx.Graphics.Vulkan private bool _tfEnabled; private bool _tfActive; - private bool _supportExtDynamic; - private bool _supportExtDynamic2; + private readonly bool _supportExtDynamic; + private readonly bool _supportExtDynamic2; private readonly PipelineColorBlendAttachmentState[] _storedBlend; @@ -126,7 +126,7 @@ namespace Ryujinx.Graphics.Vulkan _storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets]; _supportExtDynamic = gd.Capabilities.SupportsExtendedDynamicState; - + _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2; @@ -714,7 +714,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthTestEnable = false; _newState.DepthWriteEnable = false; } - + SignalStateChange(); Gd.HelperShader.DrawTexture( @@ -739,7 +739,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthWriteEnable = oldDepthWriteEnable; _newState.ViewportsCount = oldViewportsCount; } - + _newState.Topology = oldTopology; DynamicState.SetViewports(ref oldViewports, oldViewportsCount); @@ -880,7 +880,7 @@ namespace Ryujinx.Graphics.Vulkan { _newState.DepthBiasEnable = enables != 0; } - + SignalStateChange(); } @@ -913,7 +913,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.DepthWriteEnable = depthTest.WriteEnable; _newState.DepthCompareOp = depthTest.Func.Convert(); } - + SignalStateChange(); } @@ -980,14 +980,22 @@ namespace Ryujinx.Graphics.Vulkan { DynamicState.SetLineWidth(Gd.Capabilities.SupportsWideLines ? width : 1.0f); } - + SignalStateChange(); } public void SetLogicOpState(bool enable, LogicalOp op) { + if (_supportExtDynamic2 && Gd.ExtendedLogicOp) + { + DynamicState.SetLogicOp(op.Convert()); + } + else + { + _newState.LogicOp = op.Convert(); + } + _newState.LogicOpEnable = enable; - _newState.LogicOp = op.Convert(); SignalStateChange(); } @@ -1031,9 +1039,9 @@ namespace Ryujinx.Graphics.Vulkan _topology = topology; var vkTopology = Gd.TopologyRemap(topology).Convert(); - + _newState.Topology = vkTopology; - + SignalStateChange(); } @@ -1194,7 +1202,7 @@ namespace Ryujinx.Graphics.Vulkan stencilTest.FrontDpPass.Convert(), stencilTest.FrontDpFail.Convert(), stencilTest.FrontFunc.Convert()); - + DynamicState.SetStencilTest(stencilTest.TestEnable); } else @@ -1209,7 +1217,7 @@ namespace Ryujinx.Graphics.Vulkan _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); _newState.StencilTestEnable = stencilTest.TestEnable; } - + DynamicState.SetStencilMask((uint)stencilTest.BackFuncMask, (uint)stencilTest.BackMask, (uint)stencilTest.BackFuncRef, @@ -1450,11 +1458,11 @@ namespace Ryujinx.Graphics.Vulkan Clamp(viewport.DepthNear), Clamp(viewport.DepthFar))); } - + if (!_supportExtDynamic) { _newState.ViewportsCount = (uint)count; - } + } SignalStateChange(); } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs index 7ccd040e3..d122b478a 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineConverter.cs @@ -164,9 +164,9 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthBoundsTestEnable = false; // Not implemented. pipeline.DepthClampEnable = state.DepthClampEnable; - + pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; - + pipeline.HasDepthStencil = state.DepthStencilEnable; pipeline.LogicOpEnable = state.LogicOpEnable; pipeline.LogicOp = state.LogicOp.Convert(); @@ -188,11 +188,11 @@ namespace Ryujinx.Graphics.Vulkan pipeline.DepthTestEnable = state.DepthTest.TestEnable; pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); - + pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; - + pipeline.FrontFace = state.FrontFace.Convert(); - + if (gd.Capabilities.SupportsMultiView) { pipeline.ScissorsCount = Constants.MaxViewports; @@ -203,7 +203,7 @@ namespace Ryujinx.Graphics.Vulkan pipeline.ScissorsCount = 1; pipeline.ViewportsCount = 1; } - + pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert(); pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); @@ -213,12 +213,12 @@ 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; } - + pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); - + int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs index efee04b10..783f2bf71 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs @@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Vulkan private uint _frontCompareMask; private uint _frontWriteMask; private uint _frontReference; - + private bool _opToo; private StencilOp _backfailop; private StencilOp _backpassop; @@ -33,13 +33,13 @@ namespace Ryujinx.Graphics.Vulkan private CompareOp _frontcompareop; private float _linewidth; - + public bool _stencilTestEnable; public bool _depthtestEnable; public bool _depthwriteEnable; private CompareOp _depthCompareOp; - + private Array4 _blendConstants; public uint ViewportsCount; @@ -49,7 +49,9 @@ namespace Ryujinx.Graphics.Vulkan public FrontFace FrontFace; private bool _discard; - + + private LogicOp _logicOp; + [Flags] private enum DirtyFlags { @@ -61,14 +63,15 @@ namespace Ryujinx.Graphics.Vulkan Viewport = 1 << 4, CullMode = 1 << 5, FrontFace = 1 << 6, - DepthTestBool = 1 << 7, + DepthTestBool = 1 << 7, DepthTestCompareOp = 1 << 8, StencilTestEnable = 1 << 9, LineWidth = 1 << 10, RasterDiscard = 1 << 11, + LogicOp = 1 << 12, Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth, Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable, - Extended2 = RasterDiscard, + Extended2 = RasterDiscard | LogicOp, } private DirtyFlags _dirty; @@ -107,14 +110,14 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.DepthTestBool; } - + public void SetDepthTestCompareOp(CompareOp depthTestOp) { _depthCompareOp = depthTestOp; _dirty |= DirtyFlags.DepthTestCompareOp; } - + public void SetStencilOp(StencilOp backFailOp, StencilOp backPassOp, StencilOp backDepthFailOp, @@ -133,10 +136,10 @@ namespace Ryujinx.Graphics.Vulkan _frontpassop = frontPassOp; _frontdepthfailop = frontDepthFailOp; _frontcompareop = frontCompareOp; - + _opToo = true; } - + public void SetStencilMask( uint backCompareMask, uint backWriteMask, @@ -154,11 +157,11 @@ namespace Ryujinx.Graphics.Vulkan _dirty |= DirtyFlags.Stencil; } - + public void SetStencilTest(bool stencilTestEnable) { _stencilTestEnable = stencilTestEnable; - + _dirty |= DirtyFlags.StencilTestEnable; } @@ -180,35 +183,42 @@ namespace Ryujinx.Graphics.Vulkan _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 SetRasterizerDiscard(bool discard) { _discard = discard; - + _dirty |= DirtyFlags.RasterDiscard; } + public void SetLogicOp(LogicOp op) + { + _logicOp = op; + + _dirty |= DirtyFlags.LogicOp; + } + public void ForceAllDirty(VulkanRenderer gd) { _dirty = DirtyFlags.Standard; @@ -227,6 +237,11 @@ namespace Ryujinx.Graphics.Vulkan { _dirty &= ~DirtyFlags.LineWidth; } + + if (!gd.ExtendedLogicOp) + { + _dirty &= ~DirtyFlags.LogicOp; + } } public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) @@ -255,42 +270,47 @@ namespace Ryujinx.Graphics.Vulkan { RecordViewport(gd, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.CullMode)) { RecordCullMode(gd.ExtendedDynamicStateApi, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.FrontFace)) { RecordFrontFace(gd.ExtendedDynamicStateApi, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.DepthTestBool)) { RecordDepthTestBool(gd.ExtendedDynamicStateApi, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.DepthTestCompareOp)) { RecordDepthTestCompareOp(gd.ExtendedDynamicStateApi, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.StencilTestEnable)) { RecordStencilTestEnable(gd.ExtendedDynamicStateApi, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.LineWidth)) { RecordLineWidth(gd.Api, commandBuffer); } - + if (_dirty.HasFlag(DirtyFlags.RasterDiscard)) { RecordRasterizationDiscard(gd, commandBuffer); } - + + if (_dirty.HasFlag(DirtyFlags.RasterDiscard)) + { + RecordLogicOp(gd, commandBuffer); + } + _dirty = DirtyFlags.None; } @@ -302,7 +322,7 @@ namespace Ryujinx.Graphics.Vulkan private readonly void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) { gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); - + if (gd.Capabilities.SupportsExtendedDynamicState2) { gd.ExtendedDynamicState2Api.CmdSetDepthBiasEnable(commandBuffer, _depthBiasEnable); @@ -326,7 +346,7 @@ namespace Ryujinx.Graphics.Vulkan } } } - + private readonly void RecordStencil(VulkanRenderer gd, CommandBuffer commandBuffer) { if (_opToo) @@ -336,7 +356,7 @@ namespace Ryujinx.Graphics.Vulkan gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontfailop, _frontpassop, _frontdepthfailop, _frontcompareop); } - + gd.Api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference); @@ -344,12 +364,12 @@ namespace Ryujinx.Graphics.Vulkan gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontWriteMask); gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); } - + private readonly void RecordStencilTestEnable(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetStencilTestEnable(commandBuffer, _stencilTestEnable); } - + private void RecordViewport(VulkanRenderer gd, CommandBuffer commandBuffer) { if (ViewportsCount == 0) @@ -369,34 +389,39 @@ namespace Ryujinx.Graphics.Vulkan Viewports.AsSpan()); } } - - private void RecordCullMode(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + + private readonly void RecordCullMode(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetCullMode(commandBuffer, CullMode); } - - private void RecordFrontFace(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + + private readonly void RecordFrontFace(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetFrontFace(commandBuffer, FrontFace); } - - private void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + + private readonly void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetDepthTestEnable(commandBuffer, _depthtestEnable); api.CmdSetDepthWriteEnable(commandBuffer, _depthwriteEnable); } - - private void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) + + private readonly void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) { api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp); } - - private void RecordRasterizationDiscard(VulkanRenderer gd, CommandBuffer commandBuffer) + + private readonly void RecordRasterizationDiscard(VulkanRenderer gd, CommandBuffer commandBuffer) { gd.ExtendedDynamicState2Api.CmdSetRasterizerDiscardEnable(commandBuffer, _discard); } - - private void RecordLineWidth(Vk api, CommandBuffer commandBuffer) + + private readonly void RecordLogicOp(VulkanRenderer gd, CommandBuffer commandBuffer) + { + gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp); + } + + private readonly void RecordLineWidth(Vk api, CommandBuffer commandBuffer) { if (!OperatingSystem.IsMacOS()) { diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs index 529881cbe..4678ef763 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs @@ -404,7 +404,7 @@ namespace Ryujinx.Graphics.Vulkan { UpdateVertexAttributeDescriptions(gd); } - + bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState; bool supportsExtDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2; @@ -457,7 +457,7 @@ namespace Ryujinx.Graphics.Vulkan { primitiveRestartEnable = true; } - + var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo { SType = StructureType.PipelineInputAssemblyStateCreateInfo, @@ -494,12 +494,12 @@ namespace Ryujinx.Graphics.Vulkan rasterizationState.DepthBiasEnable = DepthBiasEnable; rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable; } - + var viewportState = new PipelineViewportStateCreateInfo { SType = StructureType.PipelineViewportStateCreateInfo, }; - + if (!supportsExtDynamicState) { viewportState.ViewportCount = ViewportsCount; @@ -534,7 +534,7 @@ namespace Ryujinx.Graphics.Vulkan MinDepthBounds = MinDepthBounds, MaxDepthBounds = MaxDepthBounds, }; - + if (!supportsExtDynamicState) { var stencilFront = new StencilOpState( @@ -588,11 +588,15 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PipelineColorBlendStateCreateInfo, LogicOpEnable = LogicOpEnable, - LogicOp = LogicOp, AttachmentCount = ColorBlendAttachmentStateCount, PAttachments = pColorBlendAttachmentState, }; - + + if (!(supportsExtDynamicState2 && gd.ExtendedLogicOp)) + { + colorBlendState.LogicOp = LogicOp; + } + PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState; if (!AdvancedBlendSrcPreMultiplied || @@ -609,9 +613,30 @@ namespace Ryujinx.Graphics.Vulkan colorBlendState.PNext = &colorBlendAdvancedState; } - - int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 18 : 19) : (isMoltenVk ? 7 : 8); + int baseDynamicStatesCount = 7; + int additionalDynamicStatesCount = 0; + + if (!isMoltenVk) + { + baseDynamicStatesCount++; + } + + if (supportsExtDynamicState) + { + additionalDynamicStatesCount += isMoltenVk ? 11 : 12; + } + + if (supportsExtDynamicState2) + { + additionalDynamicStatesCount += 2; + if (gd.ExtendedLogicOp) + { + additionalDynamicStatesCount++; + } + } + + int dynamicStatesCount = baseDynamicStatesCount + additionalDynamicStatesCount; DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount]; dynamicStates[0] = DynamicState.Viewport; @@ -621,33 +646,40 @@ namespace Ryujinx.Graphics.Vulkan dynamicStates[4] = DynamicState.StencilWriteMask; dynamicStates[5] = DynamicState.StencilReference; dynamicStates[6] = DynamicState.BlendConstants; - - if(!isMoltenVk) + + int currentIndex = 7; + + if (!isMoltenVk) { - dynamicStates[7] = DynamicState.LineWidth; + dynamicStates[currentIndex++] = DynamicState.LineWidth; } - + if (supportsExtDynamicState) { - int index = (isMoltenVk ? 7 : 8); - if (!isMoltenVk) { - dynamicStates[index++] = DynamicState.VertexInputBindingStrideExt; + if (!isMoltenVk) + { + dynamicStates[currentIndex++] = DynamicState.VertexInputBindingStrideExt; } - dynamicStates[index++] = DynamicState.CullModeExt; - dynamicStates[index++] = DynamicState.FrontFaceExt; - dynamicStates[index++] = DynamicState.DepthTestEnableExt; - dynamicStates[index++] = DynamicState.DepthWriteEnableExt; - dynamicStates[index++] = DynamicState.DepthCompareOpExt; - dynamicStates[index++] = DynamicState.StencilTestEnableExt; - dynamicStates[index++] = DynamicState.ViewportWithCountExt; - dynamicStates[index++] = DynamicState.ScissorWithCountExt; - dynamicStates[index] = DynamicState.StencilOpExt; + dynamicStates[currentIndex++] = DynamicState.CullModeExt; + dynamicStates[currentIndex++] = DynamicState.FrontFaceExt; + dynamicStates[currentIndex++] = DynamicState.DepthTestEnableExt; + dynamicStates[currentIndex++] = DynamicState.DepthWriteEnableExt; + dynamicStates[currentIndex++] = DynamicState.DepthCompareOpExt; + dynamicStates[currentIndex++] = DynamicState.StencilTestEnableExt; + dynamicStates[currentIndex++] = DynamicState.ViewportWithCountExt; + dynamicStates[currentIndex++] = DynamicState.ScissorWithCountExt; + dynamicStates[currentIndex++] = DynamicState.StencilOpExt; } if (supportsExtDynamicState2) { - dynamicStates[16] = DynamicState.DepthBiasEnableExt; - dynamicStates[17] = DynamicState.RasterizerDiscardEnableExt; + dynamicStates[currentIndex++] = DynamicState.DepthBiasEnableExt; + dynamicStates[currentIndex++] = DynamicState.RasterizerDiscardEnableExt; + + if (gd.ExtendedLogicOp) + { + dynamicStates[currentIndex++] = DynamicState.LogicOpExt; + } } var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index d6b4c7a87..6b4ca1d3d 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -263,7 +263,7 @@ namespace Ryujinx.Graphics.Vulkan return InvalidIndex; } - internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount) + internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount, out bool extendedLogicOp) { if (queueCount > QueuesCount) { @@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PhysicalDeviceFeatures2, }; - + PhysicalDeviceVulkan11Features supportedFeaturesVk11 = new() { SType = StructureType.PhysicalDeviceVulkan11Features, @@ -310,7 +310,7 @@ namespace Ryujinx.Graphics.Vulkan { features2.PNext = &supportedFeaturesCustomBorderColor; } - + PhysicalDeviceExtendedDynamicState2FeaturesEXT supportedFeaturesExtExtendedDynamicState2 = new() { SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, @@ -450,7 +450,7 @@ namespace Ryujinx.Graphics.Vulkan }; pExtendedFeatures = &featuresExtendedDynamicState; - + var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT() { SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, @@ -460,6 +460,8 @@ namespace Ryujinx.Graphics.Vulkan ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints, }; + extendedLogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp; + pExtendedFeatures = &featuresExtendedDynamicState2; var featuresVk11 = new PhysicalDeviceVulkan11Features diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 192c37ad4..8829c038b 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -99,6 +99,8 @@ namespace Ryujinx.Graphics.Vulkan public bool PreferThreading => true; + public bool ExtendedLogicOp; + public event EventHandler ScreenCaptured; public VulkanRenderer(Vk api, Func surfaceFunc, Func requiredExtensionsFunc, string preferredGpuId) @@ -133,7 +135,7 @@ namespace Ryujinx.Graphics.Vulkan { ExtendedDynamicStateApi = extendedDynamicStateApi; } - + if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExtendedDynamicState2 extendedDynamicState2Api)) { ExtendedDynamicState2Api = extendedDynamicState2Api; @@ -454,7 +456,9 @@ namespace Ryujinx.Graphics.Vulkan var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(Api, _physicalDevice, _surface, out uint maxQueueCount); - _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount); + _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount, out bool extendedLogicOp); + + ExtendedLogicOp = extendedLogicOp; if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrSwapchain swapchainApi)) {