PipelineDynamicState.cs
1 using Ryujinx.Common.Memory; 2 using Silk.NET.Vulkan; 3 using Silk.NET.Vulkan.Extensions.EXT; 4 5 namespace Ryujinx.Graphics.Vulkan 6 { 7 struct PipelineDynamicState 8 { 9 private float _depthBiasSlopeFactor; 10 private float _depthBiasConstantFactor; 11 private float _depthBiasClamp; 12 13 public int ScissorsCount; 14 private Array16<Rect2D> _scissors; 15 16 private uint _backCompareMask; 17 private uint _backWriteMask; 18 private uint _backReference; 19 private uint _frontCompareMask; 20 private uint _frontWriteMask; 21 private uint _frontReference; 22 23 private Array4<float> _blendConstants; 24 25 private FeedbackLoopAspects _feedbackLoopAspects; 26 27 public uint ViewportsCount; 28 public Array16<Viewport> Viewports; 29 30 private enum DirtyFlags 31 { 32 None = 0, 33 Blend = 1 << 0, 34 DepthBias = 1 << 1, 35 Scissor = 1 << 2, 36 Stencil = 1 << 3, 37 Viewport = 1 << 4, 38 FeedbackLoop = 1 << 5, 39 All = Blend | DepthBias | Scissor | Stencil | Viewport | FeedbackLoop, 40 } 41 42 private DirtyFlags _dirty; 43 44 public void SetBlendConstants(float r, float g, float b, float a) 45 { 46 _blendConstants[0] = r; 47 _blendConstants[1] = g; 48 _blendConstants[2] = b; 49 _blendConstants[3] = a; 50 51 _dirty |= DirtyFlags.Blend; 52 } 53 54 public void SetDepthBias(float slopeFactor, float constantFactor, float clamp) 55 { 56 _depthBiasSlopeFactor = slopeFactor; 57 _depthBiasConstantFactor = constantFactor; 58 _depthBiasClamp = clamp; 59 60 _dirty |= DirtyFlags.DepthBias; 61 } 62 63 public void SetScissor(int index, Rect2D scissor) 64 { 65 _scissors[index] = scissor; 66 67 _dirty |= DirtyFlags.Scissor; 68 } 69 70 public void SetStencilMasks( 71 uint backCompareMask, 72 uint backWriteMask, 73 uint backReference, 74 uint frontCompareMask, 75 uint frontWriteMask, 76 uint frontReference) 77 { 78 _backCompareMask = backCompareMask; 79 _backWriteMask = backWriteMask; 80 _backReference = backReference; 81 _frontCompareMask = frontCompareMask; 82 _frontWriteMask = frontWriteMask; 83 _frontReference = frontReference; 84 85 _dirty |= DirtyFlags.Stencil; 86 } 87 88 public void SetViewport(int index, Viewport viewport) 89 { 90 Viewports[index] = viewport; 91 92 _dirty |= DirtyFlags.Viewport; 93 } 94 95 public void SetViewports(ref Array16<Viewport> viewports, uint viewportsCount) 96 { 97 Viewports = viewports; 98 ViewportsCount = viewportsCount; 99 100 if (ViewportsCount != 0) 101 { 102 _dirty |= DirtyFlags.Viewport; 103 } 104 } 105 106 public void SetFeedbackLoop(FeedbackLoopAspects aspects) 107 { 108 _feedbackLoopAspects = aspects; 109 110 _dirty |= DirtyFlags.FeedbackLoop; 111 } 112 113 public void ForceAllDirty() 114 { 115 _dirty = DirtyFlags.All; 116 } 117 118 public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer) 119 { 120 Vk api = gd.Api; 121 122 if (_dirty.HasFlag(DirtyFlags.Blend)) 123 { 124 RecordBlend(api, commandBuffer); 125 } 126 127 if (_dirty.HasFlag(DirtyFlags.DepthBias)) 128 { 129 RecordDepthBias(api, commandBuffer); 130 } 131 132 if (_dirty.HasFlag(DirtyFlags.Scissor)) 133 { 134 RecordScissor(api, commandBuffer); 135 } 136 137 if (_dirty.HasFlag(DirtyFlags.Stencil)) 138 { 139 RecordStencilMasks(api, commandBuffer); 140 } 141 142 if (_dirty.HasFlag(DirtyFlags.Viewport)) 143 { 144 RecordViewport(api, commandBuffer); 145 } 146 147 if (_dirty.HasFlag(DirtyFlags.FeedbackLoop) && gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop) 148 { 149 RecordFeedbackLoop(gd.DynamicFeedbackLoopApi, commandBuffer); 150 } 151 152 _dirty = DirtyFlags.None; 153 } 154 155 private void RecordBlend(Vk api, CommandBuffer commandBuffer) 156 { 157 api.CmdSetBlendConstants(commandBuffer, _blendConstants.AsSpan()); 158 } 159 160 private readonly void RecordDepthBias(Vk api, CommandBuffer commandBuffer) 161 { 162 api.CmdSetDepthBias(commandBuffer, _depthBiasConstantFactor, _depthBiasClamp, _depthBiasSlopeFactor); 163 } 164 165 private void RecordScissor(Vk api, CommandBuffer commandBuffer) 166 { 167 if (ScissorsCount != 0) 168 { 169 api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan()); 170 } 171 } 172 173 private readonly void RecordStencilMasks(Vk api, CommandBuffer commandBuffer) 174 { 175 api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backCompareMask); 176 api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceBackBit, _backWriteMask); 177 api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceBackBit, _backReference); 178 api.CmdSetStencilCompareMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontCompareMask); 179 api.CmdSetStencilWriteMask(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontWriteMask); 180 api.CmdSetStencilReference(commandBuffer, StencilFaceFlags.FaceFrontBit, _frontReference); 181 } 182 183 private void RecordViewport(Vk api, CommandBuffer commandBuffer) 184 { 185 if (ViewportsCount != 0) 186 { 187 api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan()); 188 } 189 } 190 191 private readonly void RecordFeedbackLoop(ExtAttachmentFeedbackLoopDynamicState api, CommandBuffer commandBuffer) 192 { 193 ImageAspectFlags aspects = (_feedbackLoopAspects & FeedbackLoopAspects.Color) != 0 ? ImageAspectFlags.ColorBit : 0; 194 195 if ((_feedbackLoopAspects & FeedbackLoopAspects.Depth) != 0) 196 { 197 aspects |= ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit; 198 } 199 200 api.CmdSetAttachmentFeedbackLoopEnable(commandBuffer, aspects); 201 } 202 } 203 }