diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.Graphics.Vulkan/PipelineBase.cs | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/PipelineBase.cs')
| -rw-r--r-- | Ryujinx.Graphics.Vulkan/PipelineBase.cs | 1742 |
1 files changed, 0 insertions, 1742 deletions
diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs deleted file mode 100644 index c54d7980..00000000 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ /dev/null @@ -1,1742 +0,0 @@ -using Ryujinx.Common; -using Ryujinx.Graphics.GAL; -using Ryujinx.Graphics.Shader; -using Silk.NET.Vulkan; -using System; -using System.Linq; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Ryujinx.Graphics.Vulkan -{ - class PipelineBase : IDisposable - { - public const int DescriptorSetLayouts = 4; - - public const int UniformSetIndex = 0; - public const int StorageSetIndex = 1; - public const int TextureSetIndex = 2; - public const int ImageSetIndex = 3; - - protected readonly VulkanRenderer Gd; - protected readonly Device Device; - public readonly PipelineCache PipelineCache; - - public readonly AutoFlushCounter AutoFlush; - - protected PipelineDynamicState DynamicState; - private PipelineState _newState; - private bool _stateDirty; - private GAL.PrimitiveTopology _topology; - - private ulong _currentPipelineHandle; - - protected Auto<DisposablePipeline> Pipeline; - - protected PipelineBindPoint Pbp; - - protected CommandBufferScoped Cbs; - protected CommandBufferScoped? PreloadCbs; - protected CommandBuffer CommandBuffer; - - public CommandBufferScoped CurrentCommandBuffer => Cbs; - - private ShaderCollection _program; - - private Vector4<float>[] _renderScale = new Vector4<float>[73]; - private int _fragmentScaleCount; - - protected FramebufferParams FramebufferParams; - private Auto<DisposableFramebuffer> _framebuffer; - private Auto<DisposableRenderPass> _renderPass; - private int _writtenAttachmentCount; - - private bool _framebufferUsingColorWriteMask; - - private ITexture[] _preMaskColors; - private ITexture _preMaskDepthStencil; - - private readonly DescriptorSetUpdater _descriptorSetUpdater; - - private IndexBufferState _indexBuffer; - private IndexBufferPattern _indexBufferPattern; - private readonly BufferState[] _transformFeedbackBuffers; - private readonly VertexBufferState[] _vertexBuffers; - private ulong _vertexBuffersDirty; - protected Rectangle<int> ClearScissor; - - public SupportBufferUpdater SupportBufferUpdater; - public IndexBufferPattern QuadsToTrisPattern; - public IndexBufferPattern TriFanToTrisPattern; - - private bool _needsIndexBufferRebind; - private bool _needsTransformFeedbackBuffersRebind; - - private bool _tfEnabled; - private bool _tfActive; - - private PipelineColorBlendAttachmentState[] _storedBlend; - - public ulong DrawCount { get; private set; } - public bool RenderPassActive { get; private set; } - - public unsafe PipelineBase(VulkanRenderer gd, Device device) - { - Gd = gd; - Device = device; - - AutoFlush = new AutoFlushCounter(gd); - - var pipelineCacheCreateInfo = new PipelineCacheCreateInfo() - { - SType = StructureType.PipelineCacheCreateInfo - }; - - gd.Api.CreatePipelineCache(device, pipelineCacheCreateInfo, null, out PipelineCache).ThrowOnError(); - - _descriptorSetUpdater = new DescriptorSetUpdater(gd, this); - - _transformFeedbackBuffers = new BufferState[Constants.MaxTransformFeedbackBuffers]; - _vertexBuffers = new VertexBufferState[Constants.MaxVertexBuffers + 1]; - - const int EmptyVbSize = 16; - - using var emptyVb = gd.BufferManager.Create(gd, EmptyVbSize); - emptyVb.SetData(0, new byte[EmptyVbSize]); - _vertexBuffers[0] = new VertexBufferState(emptyVb.GetBuffer(), 0, 0, EmptyVbSize, 0); - _vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length); - - ClearScissor = new Rectangle<int>(0, 0, 0xffff, 0xffff); - - var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f }; - new Span<Vector4<float>>(_renderScale).Fill(defaultScale); - - _storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets]; - - _newState.Initialize(); - } - - public void Initialize() - { - _descriptorSetUpdater.Initialize(); - - SupportBufferUpdater = new SupportBufferUpdater(Gd); - SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, SupportBuffer.RenderScaleMaxCount); - - QuadsToTrisPattern = new IndexBufferPattern(Gd, 4, 6, 0, new[] { 0, 1, 2, 0, 2, 3 }, 4, false); - TriFanToTrisPattern = new IndexBufferPattern(Gd, 3, 3, 2, new[] { int.MinValue, -1, 0 }, 1, true); - } - - public unsafe void Barrier() - { - MemoryBarrier memoryBarrier = new MemoryBarrier() - { - SType = StructureType.MemoryBarrier, - SrcAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit, - DstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit - }; - - Gd.Api.CmdPipelineBarrier( - CommandBuffer, - PipelineStageFlags.FragmentShaderBit, - PipelineStageFlags.FragmentShaderBit, - 0, - 1, - memoryBarrier, - 0, - null, - 0, - null); - } - - public void ComputeBarrier() - { - MemoryBarrier memoryBarrier = new MemoryBarrier() - { - SType = StructureType.MemoryBarrier, - SrcAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit, - DstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit - }; - - Gd.Api.CmdPipelineBarrier( - CommandBuffer, - PipelineStageFlags.ComputeShaderBit, - PipelineStageFlags.AllCommandsBit, - 0, - 1, - new ReadOnlySpan<MemoryBarrier>(memoryBarrier), - 0, - ReadOnlySpan<BufferMemoryBarrier>.Empty, - 0, - ReadOnlySpan<ImageMemoryBarrier>.Empty); - } - - public void BeginTransformFeedback(GAL.PrimitiveTopology topology) - { - _tfEnabled = true; - } - - public void ClearBuffer(BufferHandle destination, int offset, int size, uint value) - { - EndRenderPass(); - - var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, offset, size, true).Get(Cbs, offset, size).Value; - - BufferHolder.InsertBufferBarrier( - Gd, - Cbs.CommandBuffer, - dst, - BufferHolder.DefaultAccessFlags, - AccessFlags.TransferWriteBit, - PipelineStageFlags.AllCommandsBit, - PipelineStageFlags.TransferBit, - offset, - size); - - Gd.Api.CmdFillBuffer(CommandBuffer, dst, (ulong)offset, (ulong)size, value); - - BufferHolder.InsertBufferBarrier( - Gd, - Cbs.CommandBuffer, - dst, - AccessFlags.TransferWriteBit, - BufferHolder.DefaultAccessFlags, - PipelineStageFlags.TransferBit, - PipelineStageFlags.AllCommandsBit, - offset, - size); - } - - public unsafe void ClearRenderTargetColor(int index, int layer, int layerCount, ColorF color) - { - if (FramebufferParams == null || !FramebufferParams.IsValidColorAttachment(index)) - { - return; - } - - if (_renderPass == null) - { - CreateRenderPass(); - } - - BeginRenderPass(); - - var clearValue = new ClearValue(new ClearColorValue(color.Red, color.Green, color.Blue, color.Alpha)); - var attachment = new ClearAttachment(ImageAspectFlags.ColorBit, (uint)index, clearValue); - var clearRect = FramebufferParams.GetClearRect(ClearScissor, layer, layerCount); - - FramebufferParams.InsertClearBarrier(Cbs, index); - - Gd.Api.CmdClearAttachments(CommandBuffer, 1, &attachment, 1, &clearRect); - } - - public unsafe void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) - { - // TODO: Use stencilMask (fully) - - if (FramebufferParams == null || !FramebufferParams.HasDepthStencil) - { - return; - } - - if (_renderPass == null) - { - CreateRenderPass(); - } - - BeginRenderPass(); - - var clearValue = new ClearValue(null, new ClearDepthStencilValue(depthValue, (uint)stencilValue)); - var flags = depthMask ? ImageAspectFlags.DepthBit : 0; - - if (stencilMask != 0) - { - flags |= ImageAspectFlags.StencilBit; - } - - var attachment = new ClearAttachment(flags, 0, clearValue); - var clearRect = FramebufferParams.GetClearRect(ClearScissor, layer, layerCount); - - FramebufferParams.InsertClearBarrierDS(Cbs); - - Gd.Api.CmdClearAttachments(CommandBuffer, 1, &attachment, 1, &clearRect); - } - - public unsafe void CommandBufferBarrier() - { - MemoryBarrier memoryBarrier = new MemoryBarrier() - { - SType = StructureType.MemoryBarrier, - SrcAccessMask = BufferHolder.DefaultAccessFlags, - DstAccessMask = AccessFlags.IndirectCommandReadBit - }; - - Gd.Api.CmdPipelineBarrier( - CommandBuffer, - PipelineStageFlags.AllCommandsBit, - PipelineStageFlags.DrawIndirectBit, - 0, - 1, - memoryBarrier, - 0, - null, - 0, - null); - } - - public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size) - { - EndRenderPass(); - - var src = Gd.BufferManager.GetBuffer(CommandBuffer, source, srcOffset, size, false); - var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, dstOffset, size, true); - - BufferHolder.Copy(Gd, Cbs, src, dst, srcOffset, dstOffset, size); - } - - public void DirtyVertexBuffer(Auto<DisposableBuffer> buffer) - { - for (int i = 0; i < _vertexBuffers.Length; i++) - { - if (_vertexBuffers[i].BoundEquals(buffer)) - { - _vertexBuffersDirty |= 1UL << i; - } - } - } - - public void DirtyIndexBuffer(Auto<DisposableBuffer> buffer) - { - if (_indexBuffer.BoundEquals(buffer)) - { - _needsIndexBufferRebind = true; - } - } - - public void DispatchCompute(int groupsX, int groupsY, int groupsZ) - { - if (!_program.IsLinked) - { - return; - } - - EndRenderPass(); - RecreatePipelineIfNeeded(PipelineBindPoint.Compute); - - Gd.Api.CmdDispatch(CommandBuffer, (uint)groupsX, (uint)groupsY, (uint)groupsZ); - } - - public void DispatchComputeIndirect(Auto<DisposableBuffer> indirectBuffer, int indirectBufferOffset) - { - if (!_program.IsLinked) - { - return; - } - - EndRenderPass(); - RecreatePipelineIfNeeded(PipelineBindPoint.Compute); - - Gd.Api.CmdDispatchIndirect(CommandBuffer, indirectBuffer.Get(Cbs, indirectBufferOffset, 12).Value, (ulong)indirectBufferOffset); - } - - public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) - { - if (!_program.IsLinked) - { - return; - } - - RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); - BeginRenderPass(); - DrawCount++; - - if (Gd.TopologyUnsupported(_topology)) - { - // Temporarily bind a conversion pattern as an index buffer. - _needsIndexBufferRebind = true; - - IndexBufferPattern pattern = _topology switch - { - GAL.PrimitiveTopology.Quads => QuadsToTrisPattern, - GAL.PrimitiveTopology.TriangleFan or - GAL.PrimitiveTopology.Polygon => TriFanToTrisPattern, - _ => throw new NotSupportedException($"Unsupported topology: {_topology}") - }; - - BufferHandle handle = pattern.GetRepeatingBuffer(vertexCount, out int indexCount); - var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, handle, false); - - Gd.Api.CmdBindIndexBuffer(CommandBuffer, buffer.Get(Cbs, 0, indexCount * sizeof(int)).Value, 0, Silk.NET.Vulkan.IndexType.Uint32); - - BeginRenderPass(); // May have been interrupted to set buffer data. - ResumeTransformFeedbackInternal(); - - Gd.Api.CmdDrawIndexed(CommandBuffer, (uint)indexCount, (uint)instanceCount, 0, firstVertex, (uint)firstInstance); - } - else - { - ResumeTransformFeedbackInternal(); - - Gd.Api.CmdDraw(CommandBuffer, (uint)vertexCount, (uint)instanceCount, (uint)firstVertex, (uint)firstInstance); - } - } - - private void UpdateIndexBufferPattern() - { - IndexBufferPattern pattern = null; - - if (Gd.TopologyUnsupported(_topology)) - { - pattern = _topology switch - { - GAL.PrimitiveTopology.Quads => QuadsToTrisPattern, - GAL.PrimitiveTopology.TriangleFan or - GAL.PrimitiveTopology.Polygon => TriFanToTrisPattern, - _ => throw new NotSupportedException($"Unsupported topology: {_topology}") - }; - } - - if (_indexBufferPattern != pattern) - { - _indexBufferPattern = pattern; - _needsIndexBufferRebind = true; - } - } - - public void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int firstVertex, int firstInstance) - { - if (!_program.IsLinked) - { - return; - } - - UpdateIndexBufferPattern(); - RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); - BeginRenderPass(); - DrawCount++; - - if (_indexBufferPattern != null) - { - // Convert the index buffer into a supported topology. - IndexBufferPattern pattern = _indexBufferPattern; - - int convertedCount = pattern.GetConvertedCount(indexCount); - - if (_needsIndexBufferRebind) - { - _indexBuffer.BindConvertedIndexBuffer(Gd, Cbs, firstIndex, indexCount, convertedCount, pattern); - - _needsIndexBufferRebind = false; - } - - BeginRenderPass(); // May have been interrupted to set buffer data. - ResumeTransformFeedbackInternal(); - - Gd.Api.CmdDrawIndexed(CommandBuffer, (uint)convertedCount, (uint)instanceCount, 0, firstVertex, (uint)firstInstance); - } - else - { - ResumeTransformFeedbackInternal(); - - Gd.Api.CmdDrawIndexed(CommandBuffer, (uint)indexCount, (uint)instanceCount, (uint)firstIndex, firstVertex, (uint)firstInstance); - } - } - - public void DrawIndexedIndirect(BufferRange indirectBuffer) - { - if (!_program.IsLinked) - { - return; - } - - UpdateIndexBufferPattern(); - RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); - BeginRenderPass(); - DrawCount++; - - if (_indexBufferPattern != null) - { - // Convert the index buffer into a supported topology. - IndexBufferPattern pattern = _indexBufferPattern; - - Auto<DisposableBuffer> indirectBufferAuto = _indexBuffer.BindConvertedIndexBufferIndirect( - Gd, - Cbs, - indirectBuffer, - BufferRange.Empty, - pattern, - false, - 1, - indirectBuffer.Size); - - _needsIndexBufferRebind = false; - - BeginRenderPass(); // May have been interrupted to set buffer data. - ResumeTransformFeedbackInternal(); - - Gd.Api.CmdDrawIndexedIndirect(CommandBuffer, indirectBufferAuto.Get(Cbs, 0, indirectBuffer.Size).Value, 0, 1, (uint)indirectBuffer.Size); - } - else - { - var buffer = Gd.BufferManager - .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false) - .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; - - ResumeTransformFeedbackInternal(); - - Gd.Api.CmdDrawIndexedIndirect(CommandBuffer, buffer, (ulong)indirectBuffer.Offset, 1, (uint)indirectBuffer.Size); - } - } - - public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) - { - if (!_program.IsLinked) - { - return; - } - - UpdateIndexBufferPattern(); - RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); - BeginRenderPass(); - DrawCount++; - - var countBuffer = Gd.BufferManager - .GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, false) - .Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value; - - if (_indexBufferPattern != null) - { - // Convert the index buffer into a supported topology. - IndexBufferPattern pattern = _indexBufferPattern; - - Auto<DisposableBuffer> indirectBufferAuto = _indexBuffer.BindConvertedIndexBufferIndirect( - Gd, - Cbs, - indirectBuffer, - parameterBuffer, - pattern, - true, - maxDrawCount, - stride); - - _needsIndexBufferRebind = false; - - BeginRenderPass(); // May have been interrupted to set buffer data. - ResumeTransformFeedbackInternal(); - - if (Gd.Capabilities.SupportsIndirectParameters) - { - Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount( - CommandBuffer, - indirectBufferAuto.Get(Cbs, 0, indirectBuffer.Size).Value, - 0, - countBuffer, - (ulong)parameterBuffer.Offset, - (uint)maxDrawCount, - (uint)stride); - } - else - { - // This is also fine because the indirect data conversion always zeros - // the entries that are past the current draw count. - - Gd.Api.CmdDrawIndexedIndirect( - CommandBuffer, - indirectBufferAuto.Get(Cbs, 0, indirectBuffer.Size).Value, - 0, - (uint)maxDrawCount, - (uint)stride); - } - - } - else - { - var buffer = Gd.BufferManager - .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false) - .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; - - ResumeTransformFeedbackInternal(); - - if (Gd.Capabilities.SupportsIndirectParameters) - { - Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount( - CommandBuffer, - buffer, - (ulong)indirectBuffer.Offset, - countBuffer, - (ulong)parameterBuffer.Offset, - (uint)maxDrawCount, - (uint)stride); - } - else - { - // Not fully correct, but we can't do much better if the host does not support indirect count. - Gd.Api.CmdDrawIndexedIndirect( - CommandBuffer, - buffer, - (ulong)indirectBuffer.Offset, - (uint)maxDrawCount, - (uint)stride); - } - } - } - - public void DrawIndirect(BufferRange indirectBuffer) - { - if (!_program.IsLinked) - { - return; - } - - // TODO: Support quads and other unsupported topologies. - - RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); - BeginRenderPass(); - ResumeTransformFeedbackInternal(); - DrawCount++; - - var buffer = Gd.BufferManager - .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false) - .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; - - Gd.Api.CmdDrawIndirect(CommandBuffer, buffer, (ulong)indirectBuffer.Offset, 1, (uint)indirectBuffer.Size); - } - - public void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) - { - if (!Gd.Capabilities.SupportsIndirectParameters) - { - // TODO: Fallback for when this is not supported. - throw new NotSupportedException(); - } - - if (!_program.IsLinked) - { - return; - } - - // TODO: Support quads and other unsupported topologies. - - RecreatePipelineIfNeeded(PipelineBindPoint.Graphics); - BeginRenderPass(); - ResumeTransformFeedbackInternal(); - DrawCount++; - - var buffer = Gd.BufferManager - .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false) - .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value; - - var countBuffer = Gd.BufferManager - .GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, false) - .Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value; - - Gd.DrawIndirectCountApi.CmdDrawIndirectCount( - CommandBuffer, - buffer, - (ulong)indirectBuffer.Offset, - countBuffer, - (ulong)parameterBuffer.Offset, - (uint)maxDrawCount, - (uint)stride); - } - - public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion) - { - if (texture is TextureView srcTexture) - { - SupportBufferUpdater.Commit(); - - 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; - - _newState.CullMode = CullModeFlags.None; - _newState.StencilTestEnable = false; - _newState.DepthTestEnable = false; - _newState.DepthWriteEnable = false; - SignalStateChange(); - - Gd.HelperShader.DrawTexture( - Gd, - this, - srcTexture, - sampler, - srcRegion, - dstRegion); - - _newState.CullMode = oldCullMode; - _newState.StencilTestEnable = oldStencilTestEnable; - _newState.DepthTestEnable = oldDepthTestEnable; - _newState.DepthWriteEnable = oldDepthWriteEnable; - _newState.Topology = oldTopology; - - DynamicState.SetViewports(ref oldViewports, oldViewportsCount); - - _newState.ViewportsCount = oldViewportsCount; - SignalStateChange(); - } - } - - public void EndTransformFeedback() - { - PauseTransformFeedbackInternal(); - _tfEnabled = false; - } - - public double GetCounterDivisor(CounterType type) - { - if (type == CounterType.SamplesPassed) - { - return _renderScale[0].X * _renderScale[0].X; - } - - return 1; - } - - public bool IsCommandBufferActive(CommandBuffer cb) - { - return CommandBuffer.Handle == cb.Handle; - } - - public void SetAlphaTest(bool enable, float reference, GAL.CompareOp op) - { - // This is currently handled using shader specialization, as Vulkan does not support alpha test. - // In the future, we may want to use this to write the reference value into the support buffer, - // to avoid creating one version of the shader per reference value used. - } - - public void SetBlendState(AdvancedBlendDescriptor blend) - { - for (int index = 0; index < Constants.MaxRenderTargets; index++) - { - ref var vkBlend = ref _newState.Internal.ColorBlendAttachmentState[index]; - - if (index == 0) - { - var blendOp = blend.Op.Convert(); - - vkBlend = new PipelineColorBlendAttachmentState( - blendEnable: true, - colorBlendOp: blendOp, - alphaBlendOp: blendOp, - colorWriteMask: vkBlend.ColorWriteMask); - - if (Gd.Capabilities.SupportsBlendEquationAdvancedNonPreMultipliedSrcColor) - { - _newState.AdvancedBlendSrcPreMultiplied = blend.SrcPreMultiplied; - } - - if (Gd.Capabilities.SupportsBlendEquationAdvancedCorrelatedOverlap) - { - _newState.AdvancedBlendOverlap = blend.Overlap.Convert(); - } - } - else - { - vkBlend = new PipelineColorBlendAttachmentState( - colorWriteMask: vkBlend.ColorWriteMask); - } - - if (vkBlend.ColorWriteMask == 0) - { - _storedBlend[index] = vkBlend; - - vkBlend = new PipelineColorBlendAttachmentState(); - } - } - - SignalStateChange(); - } - - public void SetBlendState(int index, BlendDescriptor blend) - { - ref var vkBlend = ref _newState.Internal.ColorBlendAttachmentState[index]; - - if (blend.Enable) - { - vkBlend.BlendEnable = blend.Enable; - vkBlend.SrcColorBlendFactor = blend.ColorSrcFactor.Convert(); - vkBlend.DstColorBlendFactor = blend.ColorDstFactor.Convert(); - vkBlend.ColorBlendOp = blend.ColorOp.Convert(); - vkBlend.SrcAlphaBlendFactor = blend.AlphaSrcFactor.Convert(); - vkBlend.DstAlphaBlendFactor = blend.AlphaDstFactor.Convert(); - vkBlend.AlphaBlendOp = blend.AlphaOp.Convert(); - } - else - { - vkBlend = new PipelineColorBlendAttachmentState( - colorWriteMask: vkBlend.ColorWriteMask); - } - - if (vkBlend.ColorWriteMask == 0) - { - _storedBlend[index] = vkBlend; - - vkBlend = new PipelineColorBlendAttachmentState(); - } - - DynamicState.SetBlendConstants( - blend.BlendConstant.Red, - blend.BlendConstant.Green, - blend.BlendConstant.Blue, - blend.BlendConstant.Alpha); - - // Reset advanced blend state back defaults to the cache to help the pipeline cache. - _newState.AdvancedBlendSrcPreMultiplied = true; - _newState.AdvancedBlendDstPreMultiplied = true; - _newState.AdvancedBlendOverlap = BlendOverlapEXT.UncorrelatedExt; - - SignalStateChange(); - } - - public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) - { - DynamicState.SetDepthBias(factor, units, clamp); - - _newState.DepthBiasEnable = enables != 0; - SignalStateChange(); - } - - public void SetDepthClamp(bool clamp) - { - _newState.DepthClampEnable = clamp; - SignalStateChange(); - } - - public void SetDepthMode(DepthMode mode) - { - // Currently this is emulated on the shader, because Vulkan had no support for changing the depth mode. - // In the future, we may want to use the VK_EXT_depth_clip_control extension to change it here. - } - - public void SetDepthTest(DepthTestDescriptor depthTest) - { - _newState.DepthTestEnable = depthTest.TestEnable; - _newState.DepthWriteEnable = depthTest.WriteEnable; - _newState.DepthCompareOp = depthTest.Func.Convert(); - SignalStateChange(); - } - - public void SetFaceCulling(bool enable, Face face) - { - _newState.CullMode = enable ? face.Convert() : CullModeFlags.None; - SignalStateChange(); - } - - public void SetFrontFace(GAL.FrontFace frontFace) - { - _newState.FrontFace = frontFace.Convert(); - SignalStateChange(); - } - - public void SetImage(int binding, ITexture image, GAL.Format imageFormat) - { - _descriptorSetUpdater.SetImage(binding, image, imageFormat); - } - - public void SetImage(int binding, Auto<DisposableImageView> image) - { - _descriptorSetUpdater.SetImage(binding, image); - } - - public void SetIndexBuffer(BufferRange buffer, GAL.IndexType type) - { - if (buffer.Handle != BufferHandle.Null) - { - _indexBuffer = new IndexBufferState(buffer.Handle, buffer.Offset, buffer.Size, type.Convert()); - } - else - { - _indexBuffer = IndexBufferState.Null; - } - - _needsIndexBufferRebind = true; - } - - public void SetLineParameters(float width, bool smooth) - { - _newState.LineWidth = width; - SignalStateChange(); - } - - public void SetLogicOpState(bool enable, LogicalOp op) - { - _newState.LogicOpEnable = enable; - _newState.LogicOp = op.Convert(); - SignalStateChange(); - } - - public void SetMultisampleState(MultisampleDescriptor multisample) - { - _newState.AlphaToCoverageEnable = multisample.AlphaToCoverageEnable; - _newState.AlphaToOneEnable = multisample.AlphaToOneEnable; - SignalStateChange(); - } - - public void SetOrigin(Origin origin) - { - // TODO. - } - - public unsafe void SetPatchParameters(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel) - { - _newState.PatchControlPoints = (uint)vertices; - SignalStateChange(); - - // TODO: Default levels (likely needs emulation on shaders?) - } - - public void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin) - { - // TODO. - } - - public void SetPolygonMode(GAL.PolygonMode frontMode, GAL.PolygonMode backMode) - { - // TODO. - } - - public void SetPrimitiveRestart(bool enable, int index) - { - _newState.PrimitiveRestartEnable = enable; - // TODO: What to do about the index? - SignalStateChange(); - } - - public void SetPrimitiveTopology(GAL.PrimitiveTopology topology) - { - _topology = topology; - - var vkTopology = Gd.TopologyRemap(topology).Convert(); - - _newState.Topology = vkTopology; - - SignalStateChange(); - } - - public void SetProgram(IProgram program) - { - var internalProgram = (ShaderCollection)program; - var stages = internalProgram.GetInfos(); - - _program = internalProgram; - - _descriptorSetUpdater.SetProgram(internalProgram); - - _newState.PipelineLayout = internalProgram.PipelineLayout; - _newState.StagesCount = (uint)stages.Length; - - stages.CopyTo(_newState.Stages.AsSpan().Slice(0, stages.Length)); - - SignalStateChange(); - - if (_program.IsCompute) - { - EndRenderPass(); - } - } - - public void Specialize<T>(in T data) where T : unmanaged - { - var dataSpan = MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in data), 1)); - - if (!dataSpan.SequenceEqual(_newState.SpecializationData.Span)) - { - _newState.SpecializationData = new SpecData(dataSpan); - - SignalStateChange(); - } - } - - protected virtual void SignalAttachmentChange() - { - } - - public void SetRasterizerDiscard(bool discard) - { - _newState.RasterizerDiscardEnable = discard; - SignalStateChange(); - } - - public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask) - { - int count = Math.Min(Constants.MaxRenderTargets, componentMask.Length); - int writtenAttachments = 0; - - for (int i = 0; i < count; i++) - { - ref var vkBlend = ref _newState.Internal.ColorBlendAttachmentState[i]; - var newMask = (ColorComponentFlags)componentMask[i]; - - // When color write mask is 0, remove all blend state to help the pipeline cache. - // Restore it when the mask becomes non-zero. - if (vkBlend.ColorWriteMask != newMask) - { - if (newMask == 0) - { - _storedBlend[i] = vkBlend; - - vkBlend = new PipelineColorBlendAttachmentState(); - } - else if (vkBlend.ColorWriteMask == 0) - { - vkBlend = _storedBlend[i]; - } - } - - vkBlend.ColorWriteMask = newMask; - - if (componentMask[i] != 0) - { - writtenAttachments++; - } - } - - if (_framebufferUsingColorWriteMask) - { - SetRenderTargetsInternal(_preMaskColors, _preMaskDepthStencil, true); - } - else - { - SignalStateChange(); - - if (writtenAttachments != _writtenAttachmentCount) - { - SignalAttachmentChange(); - _writtenAttachmentCount = writtenAttachments; - } - } - } - - private void SetRenderTargetsInternal(ITexture[] colors, ITexture depthStencil, bool filterWriteMasked) - { - FramebufferParams?.UpdateModifications(); - CreateFramebuffer(colors, depthStencil, filterWriteMasked); - CreateRenderPass(); - SignalStateChange(); - SignalAttachmentChange(); - } - - public void SetRenderTargets(ITexture[] colors, ITexture depthStencil) - { - _framebufferUsingColorWriteMask = false; - SetRenderTargetsInternal(colors, depthStencil, Gd.IsTBDR); - } - - public void SetRenderTargetScale(float scale) - { - _renderScale[0].X = scale; - SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, 1); // Just the first element. - } - - public void SetScissors(ReadOnlySpan<Rectangle<int>> regions) - { - int maxScissors = Gd.Capabilities.SupportsMultiView ? Constants.MaxViewports : 1; - int count = Math.Min(maxScissors, regions.Length); - if (count > 0) - { - ClearScissor = regions[0]; - } - - for (int i = 0; i < count; i++) - { - var region = regions[i]; - var offset = new Offset2D(region.X, region.Y); - var extent = new Extent2D((uint)region.Width, (uint)region.Height); - - DynamicState.SetScissor(i, new Rect2D(offset, extent)); - } - - DynamicState.ScissorsCount = count; - - _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); - - _newState.StencilTestEnable = stencilTest.TestEnable; - _newState.StencilBackFailOp = stencilTest.BackSFail.Convert(); - _newState.StencilBackPassOp = stencilTest.BackDpPass.Convert(); - _newState.StencilBackDepthFailOp = stencilTest.BackDpFail.Convert(); - _newState.StencilBackCompareOp = stencilTest.BackFunc.Convert(); - _newState.StencilFrontFailOp = stencilTest.FrontSFail.Convert(); - _newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert(); - _newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert(); - _newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert(); - SignalStateChange(); - } - - public void SetStorageBuffers(ReadOnlySpan<BufferAssignment> buffers) - { - _descriptorSetUpdater.SetStorageBuffers(CommandBuffer, buffers); - } - - public void SetStorageBuffers(int first, ReadOnlySpan<Auto<DisposableBuffer>> buffers) - { - _descriptorSetUpdater.SetStorageBuffers(CommandBuffer, first, buffers); - } - - public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler) - { - _descriptorSetUpdater.SetTextureAndSampler(Cbs, stage, binding, texture, sampler); - } - - public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers) - { - PauseTransformFeedbackInternal(); - - int count = Math.Min(Constants.MaxTransformFeedbackBuffers, buffers.Length); - - for (int i = 0; i < count; i++) - { - var range = buffers[i]; - - _transformFeedbackBuffers[i].Dispose(); - - if (range.Handle != BufferHandle.Null) - { - _transformFeedbackBuffers[i] = - new BufferState(Gd.BufferManager.GetBuffer(CommandBuffer, range.Handle, range.Offset, range.Size, true), range.Offset, range.Size); - _transformFeedbackBuffers[i].BindTransformFeedbackBuffer(Gd, Cbs, (uint)i); - } - else - { - _transformFeedbackBuffers[i] = BufferState.Null; - } - } - } - - public void SetUniformBuffers(ReadOnlySpan<BufferAssignment> buffers) - { - _descriptorSetUpdater.SetUniformBuffers(CommandBuffer, buffers); - } - - public void SetUserClipDistance(int index, bool enableClip) - { - // TODO. - } - - public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs) - { - var formatCapabilities = Gd.FormatCapabilities; - - Span<int> newVbScalarSizes = stackalloc int[Constants.MaxVertexBuffers]; - - int count = Math.Min(Constants.MaxVertexAttributes, vertexAttribs.Length); - uint dirtyVbSizes = 0; - - for (int i = 0; i < count; i++) - { - var attribute = vertexAttribs[i]; - var rawIndex = attribute.BufferIndex; - var bufferIndex = attribute.IsZero ? 0 : rawIndex + 1; - - if (!attribute.IsZero) - { - newVbScalarSizes[rawIndex] = Math.Max(newVbScalarSizes[rawIndex], attribute.Format.GetScalarSize()); - dirtyVbSizes |= 1u << rawIndex; - } - - _newState.Internal.VertexAttributeDescriptions[i] = new VertexInputAttributeDescription( - (uint)i, - (uint)bufferIndex, - formatCapabilities.ConvertToVertexVkFormat(attribute.Format), - (uint)attribute.Offset); - } - - while (dirtyVbSizes != 0) - { - int dirtyBit = BitOperations.TrailingZeroCount(dirtyVbSizes); - - ref var buffer = ref _vertexBuffers[dirtyBit + 1]; - - if (buffer.AttributeScalarAlignment != newVbScalarSizes[dirtyBit]) - { - _vertexBuffersDirty |= 1UL << (dirtyBit + 1); - buffer.AttributeScalarAlignment = newVbScalarSizes[dirtyBit]; - } - - dirtyVbSizes &= ~(1u << dirtyBit); - } - - _newState.VertexAttributeDescriptionsCount = (uint)count; - SignalStateChange(); - } - - public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers) - { - int count = Math.Min(Constants.MaxVertexBuffers, vertexBuffers.Length); - - _newState.Internal.VertexBindingDescriptions[0] = new VertexInputBindingDescription(0, 0, VertexInputRate.Vertex); - - int validCount = 1; - - for (int i = 0; i < count; i++) - { - var vertexBuffer = vertexBuffers[i]; - - // TODO: Support divisor > 1 - var inputRate = vertexBuffer.Divisor != 0 ? VertexInputRate.Instance : VertexInputRate.Vertex; - - if (vertexBuffer.Buffer.Handle != BufferHandle.Null) - { - var vb = Gd.BufferManager.GetBuffer(CommandBuffer, vertexBuffer.Buffer.Handle, false); - if (vb != null) - { - int binding = i + 1; - int descriptorIndex = validCount++; - - _newState.Internal.VertexBindingDescriptions[descriptorIndex] = new VertexInputBindingDescription( - (uint)binding, - (uint)vertexBuffer.Stride, - inputRate); - - int vbSize = vertexBuffer.Buffer.Size; - - if (Gd.Vendor == Vendor.Amd && !Gd.IsMoltenVk && vertexBuffer.Stride > 0) - { - // AMD has a bug where if offset + stride * count is greater than - // the size, then the last attribute will have the wrong value. - // As a workaround, simply use the full buffer size. - int remainder = vbSize % vertexBuffer.Stride; - if (remainder != 0) - { - vbSize += vertexBuffer.Stride - remainder; - } - } - - ref var buffer = ref _vertexBuffers[binding]; - int oldScalarAlign = buffer.AttributeScalarAlignment; - - buffer.Dispose(); - - if (Gd.Capabilities.VertexBufferAlignment < 2 && - (vertexBuffer.Stride % FormatExtensions.MaxBufferFormatScalarSize) == 0) - { - buffer = new VertexBufferState( - vb, - descriptorIndex, - vertexBuffer.Buffer.Offset, - vbSize, - vertexBuffer.Stride); - - buffer.BindVertexBuffer(Gd, Cbs, (uint)binding, ref _newState); - } - else - { - // May need to be rewritten. Bind this buffer before draw. - - buffer = new VertexBufferState( - vertexBuffer.Buffer.Handle, - descriptorIndex, - vertexBuffer.Buffer.Offset, - vbSize, - vertexBuffer.Stride); - - _vertexBuffersDirty |= 1UL << binding; - } - - buffer.AttributeScalarAlignment = oldScalarAlign; - } - } - } - - _newState.VertexBindingDescriptionsCount = (uint)validCount; - SignalStateChange(); - } - - public void SetViewports(ReadOnlySpan<GAL.Viewport> viewports, bool disableTransform) - { - int maxViewports = Gd.Capabilities.SupportsMultiView ? Constants.MaxViewports : 1; - int count = Math.Min(maxViewports, viewports.Length); - - static float Clamp(float value) - { - return Math.Clamp(value, 0f, 1f); - } - - DynamicState.ViewportsCount = (uint)count; - - for (int i = 0; i < count; i++) - { - var viewport = viewports[i]; - - DynamicState.SetViewport(i, new Silk.NET.Vulkan.Viewport( - viewport.Region.X, - viewport.Region.Y, - viewport.Region.Width == 0f ? 1f : viewport.Region.Width, - viewport.Region.Height == 0f ? 1f : viewport.Region.Height, - Clamp(viewport.DepthNear), - Clamp(viewport.DepthFar))); - } - - float disableTransformF = disableTransform ? 1.0f : 0.0f; - if (SupportBufferUpdater.Data.ViewportInverse.W != disableTransformF || disableTransform) - { - float scale = _renderScale[0].X; - SupportBufferUpdater.UpdateViewportInverse(new Vector4<float> - { - X = scale * 2f / viewports[0].Region.Width, - Y = scale * 2f / viewports[0].Region.Height, - Z = 1, - W = disableTransformF - }); - } - - _newState.ViewportsCount = (uint)count; - SignalStateChange(); - } - - public void SwapBuffer(Auto<DisposableBuffer> from, Auto<DisposableBuffer> to) - { - _indexBuffer.Swap(from, to); - - for (int i = 0; i < _vertexBuffers.Length; i++) - { - _vertexBuffers[i].Swap(from, to); - } - - for (int i = 0; i < _transformFeedbackBuffers.Length; i++) - { - _transformFeedbackBuffers[i].Swap(from, to); - } - - _descriptorSetUpdater.SwapBuffer(from, to); - - SignalCommandBufferChange(); - } - - public unsafe void TextureBarrier() - { - MemoryBarrier memoryBarrier = new MemoryBarrier() - { - SType = StructureType.MemoryBarrier, - SrcAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit, - DstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit - }; - - Gd.Api.CmdPipelineBarrier( - CommandBuffer, - PipelineStageFlags.FragmentShaderBit, - PipelineStageFlags.FragmentShaderBit, - 0, - 1, - memoryBarrier, - 0, - null, - 0, - null); - } - - public void TextureBarrierTiled() - { - TextureBarrier(); - } - - public void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount) - { - bool changed = false; - - for (int index = 0; index < totalCount; index++) - { - if (_renderScale[1 + index].X != scales[index]) - { - _renderScale[1 + index].X = scales[index]; - changed = true; - } - } - - // Only update fragment count if there are scales after it for the vertex stage. - if (fragmentCount != totalCount && fragmentCount != _fragmentScaleCount) - { - _fragmentScaleCount = fragmentCount; - SupportBufferUpdater.UpdateFragmentRenderScaleCount(_fragmentScaleCount); - } - - if (changed) - { - SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, 1 + totalCount); - } - } - - protected void SignalCommandBufferChange() - { - _needsIndexBufferRebind = true; - _needsTransformFeedbackBuffersRebind = true; - _vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length); - - _descriptorSetUpdater.SignalCommandBufferChange(); - DynamicState.ForceAllDirty(); - _currentPipelineHandle = 0; - } - - private void CreateFramebuffer(ITexture[] colors, ITexture depthStencil, bool filterWriteMasked) - { - if (filterWriteMasked) - { - // TBDR GPUs don't work properly if the same attachment is bound to multiple targets, - // due to each attachment being a copy of the real attachment, rather than a direct write. - - // Just try to remove duplicate attachments. - // Save a copy of the array to rebind when mask changes. - - void maskOut() - { - if (!_framebufferUsingColorWriteMask) - { - _preMaskColors = colors.ToArray(); - _preMaskDepthStencil = depthStencil; - } - - // If true, then the framebuffer must be recreated when the mask changes. - _framebufferUsingColorWriteMask = true; - } - - // Look for textures that are masked out. - - for (int i = 0; i < colors.Length; i++) - { - if (colors[i] == null) - { - continue; - } - - ref var vkBlend = ref _newState.Internal.ColorBlendAttachmentState[i]; - - for (int j = 0; j < i; j++) - { - // Check each binding for a duplicate binding before it. - - if (colors[i] == colors[j]) - { - // Prefer the binding with no write mask. - ref var vkBlend2 = ref _newState.Internal.ColorBlendAttachmentState[j]; - if (vkBlend.ColorWriteMask == 0) - { - colors[i] = null; - maskOut(); - } - else if (vkBlend2.ColorWriteMask == 0) - { - colors[j] = null; - maskOut(); - } - } - } - } - } - - FramebufferParams = new FramebufferParams(Device, colors, depthStencil); - UpdatePipelineAttachmentFormats(); - } - - protected void UpdatePipelineAttachmentFormats() - { - var dstAttachmentFormats = _newState.Internal.AttachmentFormats.AsSpan(); - FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats); - - for (int i = FramebufferParams.AttachmentFormats.Length; i < dstAttachmentFormats.Length; i++) - { - dstAttachmentFormats[i] = 0; - } - - _newState.ColorBlendAttachmentStateCount = (uint)(FramebufferParams.MaxColorAttachmentIndex + 1); - _newState.HasDepthStencil = FramebufferParams.HasDepthStencil; - _newState.SamplesCount = FramebufferParams.AttachmentSamples.Length != 0 ? FramebufferParams.AttachmentSamples[0] : 1; - } - - protected unsafe void CreateRenderPass() - { - const int MaxAttachments = Constants.MaxRenderTargets + 1; - - AttachmentDescription[] attachmentDescs = null; - - var subpass = new SubpassDescription() - { - PipelineBindPoint = PipelineBindPoint.Graphics - }; - - AttachmentReference* attachmentReferences = stackalloc AttachmentReference[MaxAttachments]; - - var hasFramebuffer = FramebufferParams != null; - - if (hasFramebuffer && FramebufferParams.AttachmentsCount != 0) - { - attachmentDescs = new AttachmentDescription[FramebufferParams.AttachmentsCount]; - - for (int i = 0; i < FramebufferParams.AttachmentsCount; i++) - { - attachmentDescs[i] = new AttachmentDescription( - 0, - FramebufferParams.AttachmentFormats[i], - TextureStorage.ConvertToSampleCountFlags(Gd.Capabilities.SupportedSampleCounts, FramebufferParams.AttachmentSamples[i]), - AttachmentLoadOp.Load, - AttachmentStoreOp.Store, - AttachmentLoadOp.Load, - AttachmentStoreOp.Store, - ImageLayout.General, - ImageLayout.General); - } - - int colorAttachmentsCount = FramebufferParams.ColorAttachmentsCount; - - if (colorAttachmentsCount > MaxAttachments - 1) - { - colorAttachmentsCount = MaxAttachments - 1; - } - - if (colorAttachmentsCount != 0) - { - int maxAttachmentIndex = FramebufferParams.MaxColorAttachmentIndex; - subpass.ColorAttachmentCount = (uint)maxAttachmentIndex + 1; - subpass.PColorAttachments = &attachmentReferences[0]; - - // Fill with VK_ATTACHMENT_UNUSED to cover any gaps. - for (int i = 0; i <= maxAttachmentIndex; i++) - { - subpass.PColorAttachments[i] = new AttachmentReference(Vk.AttachmentUnused, ImageLayout.Undefined); - } - - for (int i = 0; i < colorAttachmentsCount; i++) - { - int bindIndex = FramebufferParams.AttachmentIndices[i]; - - subpass.PColorAttachments[bindIndex] = new AttachmentReference((uint)i, ImageLayout.General); - } - } - - if (FramebufferParams.HasDepthStencil) - { - uint dsIndex = (uint)FramebufferParams.AttachmentsCount - 1; - - subpass.PDepthStencilAttachment = &attachmentReferences[MaxAttachments - 1]; - *subpass.PDepthStencilAttachment = new AttachmentReference(dsIndex, ImageLayout.General); - } - } - - var subpassDependency = PipelineConverter.CreateSubpassDependency(); - - fixed (AttachmentDescription* pAttachmentDescs = attachmentDescs) - { - var renderPassCreateInfo = new RenderPassCreateInfo() - { - SType = StructureType.RenderPassCreateInfo, - PAttachments = pAttachmentDescs, - AttachmentCount = attachmentDescs != null ? (uint)attachmentDescs.Length : 0, - PSubpasses = &subpass, - SubpassCount = 1, - PDependencies = &subpassDependency, - DependencyCount = 1 - }; - - Gd.Api.CreateRenderPass(Device, renderPassCreateInfo, null, out var renderPass).ThrowOnError(); - - _renderPass?.Dispose(); - _renderPass = new Auto<DisposableRenderPass>(new DisposableRenderPass(Gd.Api, Device, renderPass)); - } - - EndRenderPass(); - - _framebuffer?.Dispose(); - _framebuffer = hasFramebuffer ? FramebufferParams.Create(Gd.Api, Cbs, _renderPass) : null; - } - - protected void SignalStateChange() - { - _stateDirty = true; - } - - private void RecreatePipelineIfNeeded(PipelineBindPoint pbp) - { - if (AutoFlush.ShouldFlushDraw(DrawCount)) - { - Gd.FlushAllCommands(); - } - - DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer); - - // Commit changes to the support buffer before drawing. - SupportBufferUpdater.Commit(); - - if (_needsIndexBufferRebind && _indexBufferPattern == null) - { - _indexBuffer.BindIndexBuffer(Gd, Cbs); - _needsIndexBufferRebind = false; - } - - if (_needsTransformFeedbackBuffersRebind) - { - PauseTransformFeedbackInternal(); - - for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++) - { - _transformFeedbackBuffers[i].BindTransformFeedbackBuffer(Gd, Cbs, (uint)i); - } - - _needsTransformFeedbackBuffersRebind = false; - } - - if (_vertexBuffersDirty != 0) - { - while (_vertexBuffersDirty != 0) - { - int i = BitOperations.TrailingZeroCount(_vertexBuffersDirty); - - _vertexBuffers[i].BindVertexBuffer(Gd, Cbs, (uint)i, ref _newState); - - _vertexBuffersDirty &= ~(1UL << i); - } - } - - if (_stateDirty || Pbp != pbp) - { - CreatePipeline(pbp); - _stateDirty = false; - Pbp = pbp; - } - - _descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, pbp); - } - - private void CreatePipeline(PipelineBindPoint pbp) - { - // We can only create a pipeline if the have the shader stages set. - if (_newState.Stages != null) - { - if (pbp == PipelineBindPoint.Graphics && _renderPass == null) - { - CreateRenderPass(); - } - - var pipeline = pbp == PipelineBindPoint.Compute - ? _newState.CreateComputePipeline(Gd, Device, _program, PipelineCache) - : _newState.CreateGraphicsPipeline(Gd, Device, _program, PipelineCache, _renderPass.Get(Cbs).Value); - - ulong pipelineHandle = pipeline.GetUnsafe().Value.Handle; - - if (_currentPipelineHandle != pipelineHandle) - { - _currentPipelineHandle = pipelineHandle; - Pipeline = pipeline; - - PauseTransformFeedbackInternal(); - Gd.Api.CmdBindPipeline(CommandBuffer, pbp, Pipeline.Get(Cbs).Value); - } - } - } - - private unsafe void BeginRenderPass() - { - if (!RenderPassActive) - { - var renderArea = new Rect2D(null, new Extent2D(FramebufferParams.Width, FramebufferParams.Height)); - var clearValue = new ClearValue(); - - var renderPassBeginInfo = new RenderPassBeginInfo() - { - SType = StructureType.RenderPassBeginInfo, - RenderPass = _renderPass.Get(Cbs).Value, - Framebuffer = _framebuffer.Get(Cbs).Value, - RenderArea = renderArea, - PClearValues = &clearValue, - ClearValueCount = 1 - }; - - Gd.Api.CmdBeginRenderPass(CommandBuffer, renderPassBeginInfo, SubpassContents.Inline); - RenderPassActive = true; - } - } - - public void EndRenderPass() - { - if (RenderPassActive) - { - PauseTransformFeedbackInternal(); - Gd.Api.CmdEndRenderPass(CommandBuffer); - SignalRenderPassEnd(); - RenderPassActive = false; - } - } - - protected virtual void SignalRenderPassEnd() - { - } - - private void PauseTransformFeedbackInternal() - { - if (_tfEnabled && _tfActive) - { - EndTransformFeedbackInternal(); - _tfActive = false; - } - } - - private void ResumeTransformFeedbackInternal() - { - if (_tfEnabled && !_tfActive) - { - BeginTransformFeedbackInternal(); - _tfActive = true; - } - } - - private unsafe void BeginTransformFeedbackInternal() - { - Gd.TransformFeedbackApi.CmdBeginTransformFeedback(CommandBuffer, 0, 0, null, null); - } - - private unsafe void EndTransformFeedbackInternal() - { - Gd.TransformFeedbackApi.CmdEndTransformFeedback(CommandBuffer, 0, 0, null, null); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - _renderPass?.Dispose(); - _framebuffer?.Dispose(); - _newState.Dispose(); - _descriptorSetUpdater.Dispose(); - - for (int i = 0; i < _vertexBuffers.Length; i++) - { - _vertexBuffers[i].Dispose(); - } - - for (int i = 0; i < _transformFeedbackBuffers.Length; i++) - { - _transformFeedbackBuffers[i].Dispose(); - } - - Pipeline?.Dispose(); - - unsafe - { - Gd.Api.DestroyPipelineCache(Device, PipelineCache, null); - } - - SupportBufferUpdater.Dispose(); - } - } - - public void Dispose() - { - Dispose(true); - } - } -} |
