1
0
Fork 0
mirror of https://github.com/Ryujinx/Ryujinx.git synced 2024-12-26 08:06:01 +00:00

Use device features to enable to disable LogicOp Extended Dynamic State

Improve index counting
This commit is contained in:
sunshineinabox 2024-05-17 15:02:56 -07:00
parent 0049585a36
commit 66b6b46716
6 changed files with 121 additions and 82 deletions

View file

@ -84,8 +84,8 @@ namespace Ryujinx.Graphics.Vulkan
private bool _tfEnabled; private bool _tfEnabled;
private bool _tfActive; private bool _tfActive;
private bool _supportExtDynamic; private readonly bool _supportExtDynamic;
private bool _supportExtDynamic2; private readonly bool _supportExtDynamic2;
private readonly PipelineColorBlendAttachmentState[] _storedBlend; private readonly PipelineColorBlendAttachmentState[] _storedBlend;
@ -126,7 +126,7 @@ namespace Ryujinx.Graphics.Vulkan
_storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets]; _storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets];
_supportExtDynamic = gd.Capabilities.SupportsExtendedDynamicState; _supportExtDynamic = gd.Capabilities.SupportsExtendedDynamicState;
_supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2; _supportExtDynamic2 = gd.Capabilities.SupportsExtendedDynamicState2;
@ -714,7 +714,7 @@ namespace Ryujinx.Graphics.Vulkan
_newState.DepthTestEnable = false; _newState.DepthTestEnable = false;
_newState.DepthWriteEnable = false; _newState.DepthWriteEnable = false;
} }
SignalStateChange(); SignalStateChange();
Gd.HelperShader.DrawTexture( Gd.HelperShader.DrawTexture(
@ -739,7 +739,7 @@ namespace Ryujinx.Graphics.Vulkan
_newState.DepthWriteEnable = oldDepthWriteEnable; _newState.DepthWriteEnable = oldDepthWriteEnable;
_newState.ViewportsCount = oldViewportsCount; _newState.ViewportsCount = oldViewportsCount;
} }
_newState.Topology = oldTopology; _newState.Topology = oldTopology;
DynamicState.SetViewports(ref oldViewports, oldViewportsCount); DynamicState.SetViewports(ref oldViewports, oldViewportsCount);
@ -878,7 +878,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
_newState.DepthBiasEnable = enables != 0; _newState.DepthBiasEnable = enables != 0;
} }
SignalStateChange(); SignalStateChange();
} }
@ -911,7 +911,7 @@ namespace Ryujinx.Graphics.Vulkan
_newState.DepthWriteEnable = depthTest.WriteEnable; _newState.DepthWriteEnable = depthTest.WriteEnable;
_newState.DepthCompareOp = depthTest.Func.Convert(); _newState.DepthCompareOp = depthTest.Func.Convert();
} }
SignalStateChange(); SignalStateChange();
} }
@ -983,14 +983,22 @@ namespace Ryujinx.Graphics.Vulkan
{ {
DynamicState.SetLineWidth(Gd.Capabilities.SupportsWideLines ? width : 1.0f); DynamicState.SetLineWidth(Gd.Capabilities.SupportsWideLines ? width : 1.0f);
} }
SignalStateChange(); SignalStateChange();
} }
public void SetLogicOpState(bool enable, LogicalOp op) public void SetLogicOpState(bool enable, LogicalOp op)
{ {
if (_supportExtDynamic2 && Gd.ExtendedLogicOp)
{
DynamicState.SetLogicOp(op.Convert());
}
else
{
_newState.LogicOp = op.Convert();
}
_newState.LogicOpEnable = enable; _newState.LogicOpEnable = enable;
_newState.LogicOp = op.Convert();
SignalStateChange(); SignalStateChange();
} }
@ -1032,9 +1040,9 @@ namespace Ryujinx.Graphics.Vulkan
_topology = topology; _topology = topology;
var vkTopology = Gd.TopologyRemap(topology).Convert(); var vkTopology = Gd.TopologyRemap(topology).Convert();
_newState.Topology = vkTopology; _newState.Topology = vkTopology;
SignalStateChange(); SignalStateChange();
} }
@ -1195,7 +1203,7 @@ namespace Ryujinx.Graphics.Vulkan
stencilTest.FrontDpPass.Convert(), stencilTest.FrontDpPass.Convert(),
stencilTest.FrontDpFail.Convert(), stencilTest.FrontDpFail.Convert(),
stencilTest.FrontFunc.Convert()); stencilTest.FrontFunc.Convert());
DynamicState.SetStencilTest(stencilTest.TestEnable); DynamicState.SetStencilTest(stencilTest.TestEnable);
} }
else else
@ -1210,7 +1218,7 @@ namespace Ryujinx.Graphics.Vulkan
_newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert();
_newState.StencilTestEnable = stencilTest.TestEnable; _newState.StencilTestEnable = stencilTest.TestEnable;
} }
DynamicState.SetStencilMask((uint)stencilTest.BackFuncMask, DynamicState.SetStencilMask((uint)stencilTest.BackFuncMask,
(uint)stencilTest.BackMask, (uint)stencilTest.BackMask,
(uint)stencilTest.BackFuncRef, (uint)stencilTest.BackFuncRef,
@ -1454,11 +1462,11 @@ namespace Ryujinx.Graphics.Vulkan
Clamp(viewport.DepthNear), Clamp(viewport.DepthNear),
Clamp(viewport.DepthFar))); Clamp(viewport.DepthFar)));
} }
if (!_supportExtDynamic) if (!_supportExtDynamic)
{ {
_newState.ViewportsCount = (uint)count; _newState.ViewportsCount = (uint)count;
} }
SignalStateChange(); SignalStateChange();
} }

View file

@ -164,9 +164,9 @@ namespace Ryujinx.Graphics.Vulkan
pipeline.DepthBoundsTestEnable = false; // Not implemented. pipeline.DepthBoundsTestEnable = false; // Not implemented.
pipeline.DepthClampEnable = state.DepthClampEnable; pipeline.DepthClampEnable = state.DepthClampEnable;
pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne; pipeline.DepthMode = state.DepthMode == DepthMode.MinusOneToOne;
pipeline.HasDepthStencil = state.DepthStencilEnable; pipeline.HasDepthStencil = state.DepthStencilEnable;
pipeline.LogicOpEnable = state.LogicOpEnable; pipeline.LogicOpEnable = state.LogicOpEnable;
pipeline.LogicOp = state.LogicOp.Convert(); pipeline.LogicOp = state.LogicOp.Convert();
@ -188,11 +188,11 @@ namespace Ryujinx.Graphics.Vulkan
pipeline.DepthTestEnable = state.DepthTest.TestEnable; pipeline.DepthTestEnable = state.DepthTest.TestEnable;
pipeline.DepthWriteEnable = state.DepthTest.WriteEnable; pipeline.DepthWriteEnable = state.DepthTest.WriteEnable;
pipeline.DepthCompareOp = state.DepthTest.Func.Convert(); pipeline.DepthCompareOp = state.DepthTest.Func.Convert();
pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None; pipeline.CullMode = state.CullEnable ? state.CullMode.Convert() : CullModeFlags.None;
pipeline.FrontFace = state.FrontFace.Convert(); pipeline.FrontFace = state.FrontFace.Convert();
if (gd.Capabilities.SupportsMultiView) if (gd.Capabilities.SupportsMultiView)
{ {
pipeline.ScissorsCount = Constants.MaxViewports; pipeline.ScissorsCount = Constants.MaxViewports;
@ -203,7 +203,7 @@ namespace Ryujinx.Graphics.Vulkan
pipeline.ScissorsCount = 1; pipeline.ScissorsCount = 1;
pipeline.ViewportsCount = 1; pipeline.ViewportsCount = 1;
} }
pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert(); pipeline.StencilFrontFailOp = state.StencilTest.FrontSFail.Convert();
pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert(); pipeline.StencilFrontPassOp = state.StencilTest.FrontDpPass.Convert();
pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert(); pipeline.StencilFrontDepthFailOp = state.StencilTest.FrontDpFail.Convert();
@ -213,12 +213,12 @@ namespace Ryujinx.Graphics.Vulkan
pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert(); pipeline.StencilBackPassOp = state.StencilTest.BackDpPass.Convert();
pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert(); pipeline.StencilBackDepthFailOp = state.StencilTest.BackDpFail.Convert();
pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert(); pipeline.StencilBackCompareOp = state.StencilTest.BackFunc.Convert();
pipeline.StencilTestEnable = state.StencilTest.TestEnable; pipeline.StencilTestEnable = state.StencilTest.TestEnable;
} }
pipeline.Topology = gd.TopologyRemap(state.Topology).Convert(); pipeline.Topology = gd.TopologyRemap(state.Topology).Convert();
int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount); int vaCount = Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount);
int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount); int vbCount = Math.Min(Constants.MaxVertexBuffers, state.VertexBufferCount);

View file

@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
private uint _frontCompareMask; private uint _frontCompareMask;
private uint _frontWriteMask; private uint _frontWriteMask;
private uint _frontReference; private uint _frontReference;
private bool _opToo; private bool _opToo;
private StencilOp _backfailop; private StencilOp _backfailop;
private StencilOp _backpassop; private StencilOp _backpassop;
@ -33,13 +33,13 @@ namespace Ryujinx.Graphics.Vulkan
private CompareOp _frontcompareop; private CompareOp _frontcompareop;
private float _linewidth; private float _linewidth;
public bool _stencilTestEnable; public bool _stencilTestEnable;
public bool _depthtestEnable; public bool _depthtestEnable;
public bool _depthwriteEnable; public bool _depthwriteEnable;
private CompareOp _depthCompareOp; private CompareOp _depthCompareOp;
private Array4<float> _blendConstants; private Array4<float> _blendConstants;
public uint ViewportsCount; public uint ViewportsCount;
@ -49,7 +49,9 @@ namespace Ryujinx.Graphics.Vulkan
public FrontFace FrontFace; public FrontFace FrontFace;
private bool _discard; private bool _discard;
private LogicOp _logicOp;
[Flags] [Flags]
private enum DirtyFlags private enum DirtyFlags
{ {
@ -61,14 +63,15 @@ namespace Ryujinx.Graphics.Vulkan
Viewport = 1 << 4, Viewport = 1 << 4,
CullMode = 1 << 5, CullMode = 1 << 5,
FrontFace = 1 << 6, FrontFace = 1 << 6,
DepthTestBool = 1 << 7, DepthTestBool = 1 << 7,
DepthTestCompareOp = 1 << 8, DepthTestCompareOp = 1 << 8,
StencilTestEnable = 1 << 9, StencilTestEnable = 1 << 9,
LineWidth = 1 << 10, LineWidth = 1 << 10,
RasterDiscard = 1 << 11, RasterDiscard = 1 << 11,
LogicOp = 1 << 12,
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, Extended2 = RasterDiscard | LogicOp,
} }
private DirtyFlags _dirty; private DirtyFlags _dirty;
@ -107,14 +110,14 @@ namespace Ryujinx.Graphics.Vulkan
_dirty |= DirtyFlags.DepthTestBool; _dirty |= DirtyFlags.DepthTestBool;
} }
public void SetDepthTestCompareOp(CompareOp depthTestOp) public void SetDepthTestCompareOp(CompareOp depthTestOp)
{ {
_depthCompareOp = depthTestOp; _depthCompareOp = depthTestOp;
_dirty |= DirtyFlags.DepthTestCompareOp; _dirty |= DirtyFlags.DepthTestCompareOp;
} }
public void SetStencilOp(StencilOp backFailOp, public void SetStencilOp(StencilOp backFailOp,
StencilOp backPassOp, StencilOp backPassOp,
StencilOp backDepthFailOp, StencilOp backDepthFailOp,
@ -133,10 +136,10 @@ namespace Ryujinx.Graphics.Vulkan
_frontpassop = frontPassOp; _frontpassop = frontPassOp;
_frontdepthfailop = frontDepthFailOp; _frontdepthfailop = frontDepthFailOp;
_frontcompareop = frontCompareOp; _frontcompareop = frontCompareOp;
_opToo = true; _opToo = true;
} }
public void SetStencilMask( public void SetStencilMask(
uint backCompareMask, uint backCompareMask,
uint backWriteMask, uint backWriteMask,
@ -154,11 +157,11 @@ namespace Ryujinx.Graphics.Vulkan
_dirty |= DirtyFlags.Stencil; _dirty |= DirtyFlags.Stencil;
} }
public void SetStencilTest(bool stencilTestEnable) public void SetStencilTest(bool stencilTestEnable)
{ {
_stencilTestEnable = stencilTestEnable; _stencilTestEnable = stencilTestEnable;
_dirty |= DirtyFlags.StencilTestEnable; _dirty |= DirtyFlags.StencilTestEnable;
} }
@ -180,35 +183,42 @@ namespace Ryujinx.Graphics.Vulkan
_dirty |= DirtyFlags.Viewport; _dirty |= DirtyFlags.Viewport;
} }
} }
public void SetCullMode(CullModeFlags cullMode) public void SetCullMode(CullModeFlags cullMode)
{ {
CullMode = cullMode; CullMode = cullMode;
_dirty |= DirtyFlags.CullMode; _dirty |= DirtyFlags.CullMode;
} }
public void SetFrontFace(FrontFace frontFace) public void SetFrontFace(FrontFace frontFace)
{ {
FrontFace = frontFace; FrontFace = frontFace;
_dirty |= DirtyFlags.FrontFace; _dirty |= DirtyFlags.FrontFace;
} }
public void SetLineWidth(float width) public void SetLineWidth(float width)
{ {
_linewidth = width; _linewidth = width;
_dirty |= DirtyFlags.LineWidth; _dirty |= DirtyFlags.LineWidth;
} }
public void SetRasterizerDiscard(bool discard) public void SetRasterizerDiscard(bool discard)
{ {
_discard = discard; _discard = discard;
_dirty |= DirtyFlags.RasterDiscard; _dirty |= DirtyFlags.RasterDiscard;
} }
public void SetLogicOp(LogicOp op)
{
_logicOp = op;
_dirty |= DirtyFlags.LogicOp;
}
public void ForceAllDirty(VulkanRenderer gd) public void ForceAllDirty(VulkanRenderer gd)
{ {
_dirty = DirtyFlags.Standard; _dirty = DirtyFlags.Standard;
@ -227,6 +237,11 @@ namespace Ryujinx.Graphics.Vulkan
{ {
_dirty &= ~DirtyFlags.LineWidth; _dirty &= ~DirtyFlags.LineWidth;
} }
if (!gd.ExtendedLogicOp)
{
_dirty &= ~DirtyFlags.LogicOp;
}
} }
public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer)
@ -255,42 +270,47 @@ namespace Ryujinx.Graphics.Vulkan
{ {
RecordViewport(gd, commandBuffer); RecordViewport(gd, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.CullMode)) if (_dirty.HasFlag(DirtyFlags.CullMode))
{ {
RecordCullMode(gd.ExtendedDynamicStateApi, commandBuffer); RecordCullMode(gd.ExtendedDynamicStateApi, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.FrontFace)) if (_dirty.HasFlag(DirtyFlags.FrontFace))
{ {
RecordFrontFace(gd.ExtendedDynamicStateApi, commandBuffer); RecordFrontFace(gd.ExtendedDynamicStateApi, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.DepthTestBool)) if (_dirty.HasFlag(DirtyFlags.DepthTestBool))
{ {
RecordDepthTestBool(gd.ExtendedDynamicStateApi, commandBuffer); RecordDepthTestBool(gd.ExtendedDynamicStateApi, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.DepthTestCompareOp)) if (_dirty.HasFlag(DirtyFlags.DepthTestCompareOp))
{ {
RecordDepthTestCompareOp(gd.ExtendedDynamicStateApi, commandBuffer); RecordDepthTestCompareOp(gd.ExtendedDynamicStateApi, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.StencilTestEnable)) if (_dirty.HasFlag(DirtyFlags.StencilTestEnable))
{ {
RecordStencilTestEnable(gd.ExtendedDynamicStateApi, commandBuffer); RecordStencilTestEnable(gd.ExtendedDynamicStateApi, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.LineWidth)) if (_dirty.HasFlag(DirtyFlags.LineWidth))
{ {
RecordLineWidth(gd.Api, commandBuffer); RecordLineWidth(gd.Api, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.RasterDiscard)) if (_dirty.HasFlag(DirtyFlags.RasterDiscard))
{ {
RecordRasterizationDiscard(gd, commandBuffer); RecordRasterizationDiscard(gd, commandBuffer);
} }
if (_dirty.HasFlag(DirtyFlags.RasterDiscard))
{
RecordLogicOp(gd, commandBuffer);
}
_dirty = DirtyFlags.None; _dirty = DirtyFlags.None;
} }
@ -302,7 +322,7 @@ namespace Ryujinx.Graphics.Vulkan
private readonly void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer) private readonly void RecordDepthBias(VulkanRenderer gd, CommandBuffer commandBuffer)
{ {
gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); gd.Api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor);
if (gd.Capabilities.SupportsExtendedDynamicState2) if (gd.Capabilities.SupportsExtendedDynamicState2)
{ {
gd.ExtendedDynamicState2Api.CmdSetDepthBiasEnable(commandBuffer, _depthBiasEnable); gd.ExtendedDynamicState2Api.CmdSetDepthBiasEnable(commandBuffer, _depthBiasEnable);
@ -326,7 +346,7 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
} }
private readonly void RecordStencil(VulkanRenderer gd, CommandBuffer commandBuffer) private readonly void RecordStencil(VulkanRenderer gd, CommandBuffer commandBuffer)
{ {
if (_opToo) if (_opToo)
@ -336,7 +356,7 @@ namespace Ryujinx.Graphics.Vulkan
gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontfailop, _frontpassop, gd.ExtendedDynamicStateApi.CmdSetStencilOp(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontfailop, _frontpassop,
_frontdepthfailop, _frontcompareop); _frontdepthfailop, _frontcompareop);
} }
gd.Api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); gd.Api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask);
gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask);
gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference); gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference);
@ -344,12 +364,12 @@ namespace Ryujinx.Graphics.Vulkan
gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontWriteMask); gd.Api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontWriteMask);
gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); gd.Api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference);
} }
private readonly void RecordStencilTestEnable(ExtExtendedDynamicState api, CommandBuffer commandBuffer) private readonly void RecordStencilTestEnable(ExtExtendedDynamicState api, CommandBuffer commandBuffer)
{ {
api.CmdSetStencilTestEnable(commandBuffer, _stencilTestEnable); api.CmdSetStencilTestEnable(commandBuffer, _stencilTestEnable);
} }
private void RecordViewport(VulkanRenderer gd, CommandBuffer commandBuffer) private void RecordViewport(VulkanRenderer gd, CommandBuffer commandBuffer)
{ {
if (ViewportsCount == 0) if (ViewportsCount == 0)
@ -369,34 +389,39 @@ namespace Ryujinx.Graphics.Vulkan
Viewports.AsSpan()); Viewports.AsSpan());
} }
} }
private void RecordCullMode(ExtExtendedDynamicState api, CommandBuffer commandBuffer) private readonly void RecordCullMode(ExtExtendedDynamicState api, CommandBuffer commandBuffer)
{ {
api.CmdSetCullMode(commandBuffer, CullMode); api.CmdSetCullMode(commandBuffer, CullMode);
} }
private void RecordFrontFace(ExtExtendedDynamicState api, CommandBuffer commandBuffer) private readonly void RecordFrontFace(ExtExtendedDynamicState api, CommandBuffer commandBuffer)
{ {
api.CmdSetFrontFace(commandBuffer, FrontFace); api.CmdSetFrontFace(commandBuffer, FrontFace);
} }
private void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer) private readonly void RecordDepthTestBool(ExtExtendedDynamicState api, CommandBuffer commandBuffer)
{ {
api.CmdSetDepthTestEnable(commandBuffer, _depthtestEnable); api.CmdSetDepthTestEnable(commandBuffer, _depthtestEnable);
api.CmdSetDepthWriteEnable(commandBuffer, _depthwriteEnable); api.CmdSetDepthWriteEnable(commandBuffer, _depthwriteEnable);
} }
private void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer) private readonly void RecordDepthTestCompareOp(ExtExtendedDynamicState api, CommandBuffer commandBuffer)
{ {
api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp); api.CmdSetDepthCompareOp(commandBuffer, _depthCompareOp);
} }
private void RecordRasterizationDiscard(VulkanRenderer gd, CommandBuffer commandBuffer) private readonly void RecordRasterizationDiscard(VulkanRenderer gd, CommandBuffer commandBuffer)
{ {
gd.ExtendedDynamicState2Api.CmdSetRasterizerDiscardEnable(commandBuffer, _discard); 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()) if (!OperatingSystem.IsMacOS())
{ {

View file

@ -584,19 +584,19 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
// Vendors other than NVIDIA have a bug where it enables logical operations even for float formats,
// so we need to force disable them here.
bool logicOpEnable = LogicOpEnable && (gd.Vendor == Vendor.Nvidia || Internal.LogicOpsAllowed);
var colorBlendState = new PipelineColorBlendStateCreateInfo var colorBlendState = new PipelineColorBlendStateCreateInfo
{ {
SType = StructureType.PipelineColorBlendStateCreateInfo, SType = StructureType.PipelineColorBlendStateCreateInfo,
LogicOpEnable = logicOpEnable, LogicOpEnable = LogicOpEnable,
LogicOp = LogicOp,
AttachmentCount = ColorBlendAttachmentStateCount, AttachmentCount = ColorBlendAttachmentStateCount,
PAttachments = pColorBlendAttachmentState, PAttachments = pColorBlendAttachmentState,
}; };
if (!(supportsExtDynamicState2 && gd.ExtendedLogicOp))
{
colorBlendState.LogicOp = LogicOp;
}
PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState; PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState;
if (!AdvancedBlendSrcPreMultiplied || if (!AdvancedBlendSrcPreMultiplied ||

View file

@ -263,7 +263,7 @@ namespace Ryujinx.Graphics.Vulkan
return InvalidIndex; 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) if (queueCount > QueuesCount)
{ {
@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
SType = StructureType.PhysicalDeviceFeatures2, SType = StructureType.PhysicalDeviceFeatures2,
}; };
PhysicalDeviceVulkan11Features supportedFeaturesVk11 = new() PhysicalDeviceVulkan11Features supportedFeaturesVk11 = new()
{ {
SType = StructureType.PhysicalDeviceVulkan11Features, SType = StructureType.PhysicalDeviceVulkan11Features,
@ -310,7 +310,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
features2.PNext = &supportedFeaturesCustomBorderColor; features2.PNext = &supportedFeaturesCustomBorderColor;
} }
PhysicalDeviceExtendedDynamicState2FeaturesEXT supportedFeaturesExtExtendedDynamicState2 = new() PhysicalDeviceExtendedDynamicState2FeaturesEXT supportedFeaturesExtExtendedDynamicState2 = new()
{ {
SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
@ -450,7 +450,7 @@ namespace Ryujinx.Graphics.Vulkan
}; };
pExtendedFeatures = &featuresExtendedDynamicState; pExtendedFeatures = &featuresExtendedDynamicState;
var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT() var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT()
{ {
SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt, SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
@ -460,6 +460,8 @@ namespace Ryujinx.Graphics.Vulkan
ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints, ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints,
}; };
extendedLogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp;
pExtendedFeatures = &featuresExtendedDynamicState2; pExtendedFeatures = &featuresExtendedDynamicState2;
var featuresVk11 = new PhysicalDeviceVulkan11Features var featuresVk11 = new PhysicalDeviceVulkan11Features

View file

@ -99,6 +99,8 @@ namespace Ryujinx.Graphics.Vulkan
public bool PreferThreading => true; public bool PreferThreading => true;
public bool ExtendedLogicOp;
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured; public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
public VulkanRenderer(Vk api, Func<Instance, Vk, SurfaceKHR> surfaceFunc, Func<string[]> requiredExtensionsFunc, string preferredGpuId) public VulkanRenderer(Vk api, Func<Instance, Vk, SurfaceKHR> surfaceFunc, Func<string[]> requiredExtensionsFunc, string preferredGpuId)
@ -133,7 +135,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
ExtendedDynamicStateApi = extendedDynamicStateApi; ExtendedDynamicStateApi = extendedDynamicStateApi;
} }
if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExtendedDynamicState2 extendedDynamicState2Api)) if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExtendedDynamicState2 extendedDynamicState2Api))
{ {
ExtendedDynamicState2Api = extendedDynamicState2Api; ExtendedDynamicState2Api = extendedDynamicState2Api;
@ -454,7 +456,9 @@ namespace Ryujinx.Graphics.Vulkan
var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(Api, _physicalDevice, _surface, out uint maxQueueCount); 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)) if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrSwapchain swapchainApi))
{ {