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/HelperShader.cs | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/HelperShader.cs')
| -rw-r--r-- | Ryujinx.Graphics.Vulkan/HelperShader.cs | 1683 |
1 files changed, 0 insertions, 1683 deletions
diff --git a/Ryujinx.Graphics.Vulkan/HelperShader.cs b/Ryujinx.Graphics.Vulkan/HelperShader.cs deleted file mode 100644 index c57edaf7..00000000 --- a/Ryujinx.Graphics.Vulkan/HelperShader.cs +++ /dev/null @@ -1,1683 +0,0 @@ -using Ryujinx.Graphics.GAL; -using Ryujinx.Graphics.Shader; -using Ryujinx.Graphics.Shader.Translation; -using Ryujinx.Graphics.Vulkan.Shaders; -using Silk.NET.Vulkan; -using System; -using System.Collections.Generic; -using System.Numerics; -using VkFormat = Silk.NET.Vulkan.Format; - -namespace Ryujinx.Graphics.Vulkan -{ - enum ComponentType - { - Float, - SignedInteger, - UnsignedInteger - } - - class HelperShader : IDisposable - { - private const int UniformBufferAlignment = 256; - - private readonly PipelineHelperShader _pipeline; - private readonly ISampler _samplerLinear; - private readonly ISampler _samplerNearest; - private readonly IProgram _programColorBlit; - private readonly IProgram _programColorBlitMs; - private readonly IProgram _programColorBlitClearAlpha; - private readonly IProgram _programColorClearF; - private readonly IProgram _programColorClearSI; - private readonly IProgram _programColorClearUI; - private readonly IProgram _programStrideChange; - private readonly IProgram _programConvertIndexBuffer; - private readonly IProgram _programConvertIndirectData; - private readonly IProgram _programColorCopyShortening; - private readonly IProgram _programColorCopyToNonMs; - private readonly IProgram _programColorCopyWidening; - private readonly IProgram _programColorDrawToMs; - private readonly IProgram _programDepthBlit; - private readonly IProgram _programDepthBlitMs; - private readonly IProgram _programDepthDrawToMs; - private readonly IProgram _programDepthDrawToNonMs; - private readonly IProgram _programStencilBlit; - private readonly IProgram _programStencilBlitMs; - private readonly IProgram _programStencilDrawToMs; - private readonly IProgram _programStencilDrawToNonMs; - - public HelperShader(VulkanRenderer gd, Device device) - { - _pipeline = new PipelineHelperShader(gd, device); - _pipeline.Initialize(); - - _samplerLinear = gd.CreateSampler(GAL.SamplerCreateInfo.Create(MinFilter.Linear, MagFilter.Linear)); - _samplerNearest = gd.CreateSampler(GAL.SamplerCreateInfo.Create(MinFilter.Nearest, MagFilter.Nearest)); - - var blitVertexBindings = new ShaderBindings( - new[] { 1 }, - Array.Empty<int>(), - Array.Empty<int>(), - Array.Empty<int>()); - - var blitFragmentBindings = new ShaderBindings( - Array.Empty<int>(), - Array.Empty<int>(), - new[] { 0 }, - Array.Empty<int>()); - - _programColorBlit = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.ColorBlitFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - _programColorBlitMs = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.ColorBlitMsFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - _programColorBlitClearAlpha = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.ColorBlitClearAlphaFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - var colorClearFragmentBindings = new ShaderBindings( - Array.Empty<int>(), - Array.Empty<int>(), - Array.Empty<int>(), - Array.Empty<int>()); - - _programColorClearF = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.ColorClearFFragmentShaderSource, colorClearFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - _programColorClearSI = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.ColorClearSIFragmentShaderSource, colorClearFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - _programColorClearUI = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorClearVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.ColorClearUIFragmentShaderSource, colorClearFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - var strideChangeBindings = new ShaderBindings( - new[] { 0 }, - new[] { 1, 2 }, - Array.Empty<int>(), - Array.Empty<int>()); - - _programStrideChange = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ChangeBufferStrideShaderSource, strideChangeBindings, ShaderStage.Compute, TargetLanguage.Spirv), - }); - - var colorCopyBindings = new ShaderBindings( - new[] { 0 }, - Array.Empty<int>(), - new[] { 0 }, - new[] { 0 }); - - _programColorCopyShortening = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorCopyShorteningComputeShaderSource, colorCopyBindings, ShaderStage.Compute, TargetLanguage.Spirv), - }); - - _programColorCopyToNonMs = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorCopyToNonMsComputeShaderSource, colorCopyBindings, ShaderStage.Compute, TargetLanguage.Spirv), - }); - - _programColorCopyWidening = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorCopyWideningComputeShaderSource, colorCopyBindings, ShaderStage.Compute, TargetLanguage.Spirv), - }); - - var colorDrawToMsVertexBindings = new ShaderBindings( - Array.Empty<int>(), - Array.Empty<int>(), - Array.Empty<int>(), - Array.Empty<int>()); - - var colorDrawToMsFragmentBindings = new ShaderBindings( - new[] { 0 }, - Array.Empty<int>(), - new[] { 0 }, - Array.Empty<int>()); - - _programColorDrawToMs = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorDrawToMsVertexShaderSource, colorDrawToMsVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.ColorDrawToMsFragmentShaderSource, colorDrawToMsFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - var convertIndexBufferBindings = new ShaderBindings( - new[] { 0 }, - new[] { 1, 2 }, - Array.Empty<int>(), - Array.Empty<int>()); - - _programConvertIndexBuffer = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ConvertIndexBufferShaderSource, convertIndexBufferBindings, ShaderStage.Compute, TargetLanguage.Spirv), - }); - - var convertIndirectDataBindings = new ShaderBindings( - new[] { 0 }, - new[] { 1, 2, 3 }, - Array.Empty<int>(), - Array.Empty<int>()); - - _programConvertIndirectData = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ConvertIndirectDataShaderSource, convertIndirectDataBindings, ShaderStage.Compute, TargetLanguage.Spirv), - }); - - _programDepthBlit = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.DepthBlitFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - _programDepthBlitMs = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.DepthBlitMsFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - _programDepthDrawToMs = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorDrawToMsVertexShaderSource, colorDrawToMsVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.DepthDrawToMsFragmentShaderSource, colorDrawToMsFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - _programDepthDrawToNonMs = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorDrawToMsVertexShaderSource, colorDrawToMsVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.DepthDrawToNonMsFragmentShaderSource, colorDrawToMsFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - if (gd.Capabilities.SupportsShaderStencilExport) - { - _programStencilBlit = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.StencilBlitFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - _programStencilBlitMs = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorBlitVertexShaderSource, blitVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.StencilBlitMsFragmentShaderSource, blitFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - _programStencilDrawToMs = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorDrawToMsVertexShaderSource, colorDrawToMsVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.StencilDrawToMsFragmentShaderSource, colorDrawToMsFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - - _programStencilDrawToNonMs = gd.CreateProgramWithMinimalLayout(new[] - { - new ShaderSource(ShaderBinaries.ColorDrawToMsVertexShaderSource, colorDrawToMsVertexBindings, ShaderStage.Vertex, TargetLanguage.Spirv), - new ShaderSource(ShaderBinaries.StencilDrawToNonMsFragmentShaderSource, colorDrawToMsFragmentBindings, ShaderStage.Fragment, TargetLanguage.Spirv), - }); - } - } - - public void Blit( - VulkanRenderer gd, - TextureView src, - TextureView dst, - Extents2D srcRegion, - Extents2D dstRegion, - int layers, - int levels, - bool isDepthOrStencil, - bool linearFilter, - bool clearAlpha = false) - { - gd.FlushAllCommands(); - - using var cbs = gd.CommandBufferPool.Rent(); - - var dstFormat = dst.VkFormat; - var dstSamples = dst.Info.Samples; - - for (int l = 0; l < levels; l++) - { - int srcWidth = Math.Max(1, src.Width >> l); - int srcHeight = Math.Max(1, src.Height >> l); - - int dstWidth = Math.Max(1, dst.Width >> l); - int dstHeight = Math.Max(1, dst.Height >> l); - - var mipSrcRegion = new Extents2D( - srcRegion.X1 >> l, - srcRegion.Y1 >> l, - srcRegion.X2 >> l, - srcRegion.Y2 >> l); - - var mipDstRegion = new Extents2D( - dstRegion.X1 >> l, - dstRegion.Y1 >> l, - dstRegion.X2 >> l, - dstRegion.Y2 >> l); - - for (int z = 0; z < layers; z++) - { - var srcView = Create2DLayerView(src, z, l); - var dstView = Create2DLayerView(dst, z, l); - - if (isDepthOrStencil) - { - BlitDepthStencil( - gd, - cbs, - srcView, - dst.GetImageViewForAttachment(), - dstWidth, - dstHeight, - dstSamples, - dstFormat, - mipSrcRegion, - mipDstRegion); - } - else - { - BlitColor( - gd, - cbs, - srcView, - dst.GetImageViewForAttachment(), - dstWidth, - dstHeight, - dstSamples, - dstFormat, - false, - mipSrcRegion, - mipDstRegion, - linearFilter, - clearAlpha); - } - - if (srcView != src) - { - srcView.Release(); - } - - if (dstView != dst) - { - dstView.Release(); - } - } - } - } - - public void CopyColor( - VulkanRenderer gd, - CommandBufferScoped cbs, - TextureView src, - TextureView dst, - int srcLayer, - int dstLayer, - int srcLevel, - int dstLevel, - int depth, - int levels) - { - for (int l = 0; l < levels; l++) - { - int mipSrcLevel = srcLevel + l; - int mipDstLevel = dstLevel + l; - - int srcWidth = Math.Max(1, src.Width >> mipSrcLevel); - int srcHeight = Math.Max(1, src.Height >> mipSrcLevel); - - int dstWidth = Math.Max(1, dst.Width >> mipDstLevel); - int dstHeight = Math.Max(1, dst.Height >> mipDstLevel); - - var extents = new Extents2D( - 0, - 0, - Math.Min(srcWidth, dstWidth), - Math.Min(srcHeight, dstHeight)); - - for (int z = 0; z < depth; z++) - { - var srcView = Create2DLayerView(src, srcLayer + z, mipSrcLevel); - var dstView = Create2DLayerView(dst, dstLayer + z, mipDstLevel); - - BlitColor( - gd, - cbs, - srcView, - dstView.GetImageViewForAttachment(), - dstView.Width, - dstView.Height, - dstView.Info.Samples, - dstView.VkFormat, - dstView.Info.Format.IsDepthOrStencil(), - extents, - extents, - false); - - if (srcView != src) - { - srcView.Release(); - } - - if (dstView != dst) - { - dstView.Release(); - } - } - } - } - - public void BlitColor( - VulkanRenderer gd, - CommandBufferScoped cbs, - TextureView src, - Auto<DisposableImageView> dst, - int dstWidth, - int dstHeight, - int dstSamples, - VkFormat dstFormat, - bool dstIsDepthOrStencil, - Extents2D srcRegion, - Extents2D dstRegion, - bool linearFilter, - bool clearAlpha = false) - { - _pipeline.SetCommandBuffer(cbs); - - const int RegionBufferSize = 16; - - var sampler = linearFilter ? _samplerLinear : _samplerNearest; - - _pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, sampler); - - Span<float> region = stackalloc float[RegionBufferSize / sizeof(float)]; - - region[0] = (float)srcRegion.X1 / src.Width; - region[1] = (float)srcRegion.X2 / src.Width; - region[2] = (float)srcRegion.Y1 / src.Height; - region[3] = (float)srcRegion.Y2 / src.Height; - - if (dstRegion.X1 > dstRegion.X2) - { - (region[0], region[1]) = (region[1], region[0]); - } - - if (dstRegion.Y1 > dstRegion.Y2) - { - (region[2], region[3]) = (region[3], region[2]); - } - - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, RegionBufferSize); - - gd.BufferManager.SetData<float>(bufferHandle, 0, region); - - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, RegionBufferSize)) }); - - Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1]; - - var rect = new Rectangle<float>( - MathF.Min(dstRegion.X1, dstRegion.X2), - MathF.Min(dstRegion.Y1, dstRegion.Y2), - MathF.Abs(dstRegion.X2 - dstRegion.X1), - MathF.Abs(dstRegion.Y2 - dstRegion.Y1)); - - viewports[0] = new GAL.Viewport( - rect, - ViewportSwizzle.PositiveX, - ViewportSwizzle.PositiveY, - ViewportSwizzle.PositiveZ, - ViewportSwizzle.PositiveW, - 0f, - 1f); - - Span<Rectangle<int>> scissors = stackalloc Rectangle<int>[1]; - - scissors[0] = new Rectangle<int>(0, 0, dstWidth, dstHeight); - - if (dstIsDepthOrStencil) - { - _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit); - _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, GAL.CompareOp.Always)); - } - else if (src.Info.Target.IsMultisample()) - { - _pipeline.SetProgram(_programColorBlitMs); - } - else if (clearAlpha) - { - _pipeline.SetProgram(_programColorBlitClearAlpha); - } - else - { - _pipeline.SetProgram(_programColorBlit); - } - - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, (uint)dstSamples, dstIsDepthOrStencil, dstFormat); - _pipeline.SetRenderTargetColorMasks(new uint[] { 0xf }); - _pipeline.SetScissors(scissors); - - if (clearAlpha) - { - _pipeline.ClearRenderTargetColor(0, 0, 1, new ColorF(0f, 0f, 0f, 1f)); - } - - _pipeline.SetViewports(viewports, false); - _pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip); - _pipeline.Draw(4, 1, 0, 0); - - if (dstIsDepthOrStencil) - { - _pipeline.SetDepthTest(new DepthTestDescriptor(false, false, GAL.CompareOp.Always)); - } - - _pipeline.Finish(gd, cbs); - - gd.BufferManager.Delete(bufferHandle); - } - - private void BlitDepthStencil( - VulkanRenderer gd, - CommandBufferScoped cbs, - TextureView src, - Auto<DisposableImageView> dst, - int dstWidth, - int dstHeight, - int dstSamples, - VkFormat dstFormat, - Extents2D srcRegion, - Extents2D dstRegion) - { - _pipeline.SetCommandBuffer(cbs); - - const int RegionBufferSize = 16; - - Span<float> region = stackalloc float[RegionBufferSize / sizeof(float)]; - - region[0] = (float)srcRegion.X1 / src.Width; - region[1] = (float)srcRegion.X2 / src.Width; - region[2] = (float)srcRegion.Y1 / src.Height; - region[3] = (float)srcRegion.Y2 / src.Height; - - if (dstRegion.X1 > dstRegion.X2) - { - (region[0], region[1]) = (region[1], region[0]); - } - - if (dstRegion.Y1 > dstRegion.Y2) - { - (region[2], region[3]) = (region[3], region[2]); - } - - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, RegionBufferSize); - - gd.BufferManager.SetData<float>(bufferHandle, 0, region); - - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, RegionBufferSize)) }); - - Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1]; - - var rect = new Rectangle<float>( - MathF.Min(dstRegion.X1, dstRegion.X2), - MathF.Min(dstRegion.Y1, dstRegion.Y2), - MathF.Abs(dstRegion.X2 - dstRegion.X1), - MathF.Abs(dstRegion.Y2 - dstRegion.Y1)); - - viewports[0] = new GAL.Viewport( - rect, - ViewportSwizzle.PositiveX, - ViewportSwizzle.PositiveY, - ViewportSwizzle.PositiveZ, - ViewportSwizzle.PositiveW, - 0f, - 1f); - - Span<Rectangle<int>> scissors = stackalloc Rectangle<int>[1]; - - scissors[0] = new Rectangle<int>(0, 0, dstWidth, dstHeight); - - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, (uint)dstSamples, true, dstFormat); - _pipeline.SetScissors(scissors); - _pipeline.SetViewports(viewports, false); - _pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip); - - var aspectFlags = src.Info.Format.ConvertAspectFlags(); - - if (aspectFlags.HasFlag(ImageAspectFlags.DepthBit)) - { - var depthTexture = CreateDepthOrStencilView(src, DepthStencilMode.Depth); - - BlitDepthStencilDraw(depthTexture, isDepth: true); - - if (depthTexture != src) - { - depthTexture.Release(); - } - } - - if (aspectFlags.HasFlag(ImageAspectFlags.StencilBit) && _programStencilBlit != null) - { - var stencilTexture = CreateDepthOrStencilView(src, DepthStencilMode.Stencil); - - BlitDepthStencilDraw(stencilTexture, isDepth: false); - - if (stencilTexture != src) - { - stencilTexture.Release(); - } - } - - _pipeline.Finish(gd, cbs); - - gd.BufferManager.Delete(bufferHandle); - } - - private static TextureView CreateDepthOrStencilView(TextureView depthStencilTexture, DepthStencilMode depthStencilMode) - { - if (depthStencilTexture.Info.DepthStencilMode == depthStencilMode) - { - return depthStencilTexture; - } - - return (TextureView)depthStencilTexture.CreateView(new TextureCreateInfo( - depthStencilTexture.Info.Width, - depthStencilTexture.Info.Height, - depthStencilTexture.Info.Depth, - depthStencilTexture.Info.Levels, - depthStencilTexture.Info.Samples, - depthStencilTexture.Info.BlockWidth, - depthStencilTexture.Info.BlockHeight, - depthStencilTexture.Info.BytesPerPixel, - depthStencilTexture.Info.Format, - depthStencilMode, - depthStencilTexture.Info.Target, - SwizzleComponent.Red, - SwizzleComponent.Green, - SwizzleComponent.Blue, - SwizzleComponent.Alpha), 0, 0); - } - - private void BlitDepthStencilDraw(TextureView src, bool isDepth) - { - _pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, _samplerNearest); - - if (isDepth) - { - _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programDepthBlitMs : _programDepthBlit); - _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, GAL.CompareOp.Always)); - } - else - { - _pipeline.SetProgram(src.Info.Target.IsMultisample() ? _programStencilBlitMs : _programStencilBlit); - _pipeline.SetStencilTest(CreateStencilTestDescriptor(true)); - } - - _pipeline.Draw(4, 1, 0, 0); - - if (isDepth) - { - _pipeline.SetDepthTest(new DepthTestDescriptor(false, false, GAL.CompareOp.Always)); - } - else - { - _pipeline.SetStencilTest(CreateStencilTestDescriptor(false)); - } - } - - private static StencilTestDescriptor CreateStencilTestDescriptor(bool enabled) - { - return new StencilTestDescriptor( - enabled, - GAL.CompareOp.Always, - GAL.StencilOp.Replace, - GAL.StencilOp.Replace, - GAL.StencilOp.Replace, - 0, - 0xff, - 0xff, - GAL.CompareOp.Always, - GAL.StencilOp.Replace, - GAL.StencilOp.Replace, - GAL.StencilOp.Replace, - 0, - 0xff, - 0xff); - } - - public void Clear( - VulkanRenderer gd, - Auto<DisposableImageView> dst, - ReadOnlySpan<float> clearColor, - uint componentMask, - int dstWidth, - int dstHeight, - VkFormat dstFormat, - ComponentType type, - Rectangle<int> scissor) - { - const int ClearColorBufferSize = 16; - - gd.FlushAllCommands(); - - using var cbs = gd.CommandBufferPool.Rent(); - - _pipeline.SetCommandBuffer(cbs); - - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ClearColorBufferSize); - - gd.BufferManager.SetData<float>(bufferHandle, 0, clearColor); - - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, ClearColorBufferSize)) }); - - Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1]; - - viewports[0] = new GAL.Viewport( - new Rectangle<float>(0, 0, dstWidth, dstHeight), - ViewportSwizzle.PositiveX, - ViewportSwizzle.PositiveY, - ViewportSwizzle.PositiveZ, - ViewportSwizzle.PositiveW, - 0f, - 1f); - - Span<Rectangle<int>> scissors = stackalloc Rectangle<int>[1]; - - scissors[0] = scissor; - - IProgram program; - - if (type == ComponentType.SignedInteger) - { - program = _programColorClearSI; - } - else if (type == ComponentType.UnsignedInteger) - { - program = _programColorClearUI; - } - else - { - program = _programColorClearF; - } - - _pipeline.SetProgram(program); - _pipeline.SetRenderTarget(dst, (uint)dstWidth, (uint)dstHeight, false, dstFormat); - _pipeline.SetRenderTargetColorMasks(new uint[] { componentMask }); - _pipeline.SetViewports(viewports, false); - _pipeline.SetScissors(scissors); - _pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip); - _pipeline.Draw(4, 1, 0, 0); - _pipeline.Finish(); - - gd.BufferManager.Delete(bufferHandle); - } - - public void DrawTexture( - VulkanRenderer gd, - PipelineBase pipeline, - TextureView src, - ISampler srcSampler, - Extents2DF srcRegion, - Extents2DF dstRegion) - { - const int RegionBufferSize = 16; - - pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, srcSampler); - - Span<float> region = stackalloc float[RegionBufferSize / sizeof(float)]; - - region[0] = srcRegion.X1 / src.Width; - region[1] = srcRegion.X2 / src.Width; - region[2] = srcRegion.Y1 / src.Height; - region[3] = srcRegion.Y2 / src.Height; - - if (dstRegion.X1 > dstRegion.X2) - { - (region[0], region[1]) = (region[1], region[0]); - } - - if (dstRegion.Y1 > dstRegion.Y2) - { - (region[2], region[3]) = (region[3], region[2]); - } - - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, RegionBufferSize); - - gd.BufferManager.SetData<float>(bufferHandle, 0, region); - - pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(1, new BufferRange(bufferHandle, 0, RegionBufferSize)) }); - - Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1]; - - var rect = new Rectangle<float>( - MathF.Min(dstRegion.X1, dstRegion.X2), - MathF.Min(dstRegion.Y1, dstRegion.Y2), - MathF.Abs(dstRegion.X2 - dstRegion.X1), - MathF.Abs(dstRegion.Y2 - dstRegion.Y1)); - - viewports[0] = new GAL.Viewport( - rect, - ViewportSwizzle.PositiveX, - ViewportSwizzle.PositiveY, - ViewportSwizzle.PositiveZ, - ViewportSwizzle.PositiveW, - 0f, - 1f); - - Span<Rectangle<int>> scissors = stackalloc Rectangle<int>[1]; - - pipeline.SetProgram(_programColorBlit); - pipeline.SetViewports(viewports, false); - pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip); - pipeline.Draw(4, 1, 0, 0); - - gd.BufferManager.Delete(bufferHandle); - } - - public unsafe void ConvertI8ToI16(VulkanRenderer gd, CommandBufferScoped cbs, BufferHolder src, BufferHolder dst, int srcOffset, int size) - { - ChangeStride(gd, cbs, src, dst, srcOffset, size, 1, 2); - } - - public unsafe void ChangeStride(VulkanRenderer gd, CommandBufferScoped cbs, BufferHolder src, BufferHolder dst, int srcOffset, int size, int stride, int newStride) - { - bool supportsUint8 = gd.Capabilities.SupportsShaderInt8; - - int elems = size / stride; - int newSize = elems * newStride; - - var srcBufferAuto = src.GetBuffer(); - var dstBufferAuto = dst.GetBuffer(); - - var srcBuffer = srcBufferAuto.Get(cbs, srcOffset, size).Value; - var dstBuffer = dstBufferAuto.Get(cbs, 0, newSize).Value; - - var access = supportsUint8 ? AccessFlags.ShaderWriteBit : AccessFlags.TransferWriteBit; - var stage = supportsUint8 ? PipelineStageFlags.ComputeShaderBit : PipelineStageFlags.TransferBit; - - BufferHolder.InsertBufferBarrier( - gd, - cbs.CommandBuffer, - dstBuffer, - BufferHolder.DefaultAccessFlags, - access, - PipelineStageFlags.AllCommandsBit, - stage, - 0, - newSize); - - if (supportsUint8) - { - const int ParamsBufferSize = 16; - - Span<int> shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)]; - - shaderParams[0] = stride; - shaderParams[1] = newStride; - shaderParams[2] = size; - shaderParams[3] = srcOffset; - - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize); - - gd.BufferManager.SetData<int>(bufferHandle, 0, shaderParams); - - _pipeline.SetCommandBuffer(cbs); - - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); - - Span<Auto<DisposableBuffer>> sbRanges = new Auto<DisposableBuffer>[2]; - - sbRanges[0] = srcBufferAuto; - sbRanges[1] = dstBufferAuto; - - _pipeline.SetStorageBuffers(1, sbRanges); - - _pipeline.SetProgram(_programStrideChange); - _pipeline.DispatchCompute(1, 1, 1); - - gd.BufferManager.Delete(bufferHandle); - - _pipeline.Finish(gd, cbs); - } - else - { - gd.Api.CmdFillBuffer(cbs.CommandBuffer, dstBuffer, 0, Vk.WholeSize, 0); - - var bufferCopy = new BufferCopy[elems]; - - for (ulong i = 0; i < (ulong)elems; i++) - { - bufferCopy[i] = new BufferCopy((ulong)srcOffset + i * (ulong)stride, i * (ulong)newStride, (ulong)stride); - } - - fixed (BufferCopy* pBufferCopy = bufferCopy) - { - gd.Api.CmdCopyBuffer(cbs.CommandBuffer, srcBuffer, dstBuffer, (uint)elems, pBufferCopy); - } - } - - BufferHolder.InsertBufferBarrier( - gd, - cbs.CommandBuffer, - dstBuffer, - access, - BufferHolder.DefaultAccessFlags, - stage, - PipelineStageFlags.AllCommandsBit, - 0, - newSize); - } - - public unsafe void ConvertIndexBuffer(VulkanRenderer gd, - CommandBufferScoped cbs, - BufferHolder src, - BufferHolder dst, - IndexBufferPattern pattern, - int indexSize, - int srcOffset, - int indexCount) - { - // TODO: Support conversion with primitive restart enabled. - // TODO: Convert with a compute shader? - - int convertedCount = pattern.GetConvertedCount(indexCount); - int outputIndexSize = 4; - - var srcBuffer = src.GetBuffer().Get(cbs, srcOffset, indexCount * indexSize).Value; - var dstBuffer = dst.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value; - - gd.Api.CmdFillBuffer(cbs.CommandBuffer, dstBuffer, 0, Vk.WholeSize, 0); - - var bufferCopy = new List<BufferCopy>(); - int outputOffset = 0; - - // Try to merge copies of adjacent indices to reduce copy count. - int sequenceStart = 0; - int sequenceLength = 0; - - foreach (var index in pattern.GetIndexMapping(indexCount)) - { - if (sequenceLength > 0) - { - if (index == sequenceStart + sequenceLength && indexSize == outputIndexSize) - { - sequenceLength++; - continue; - } - - // Commit the copy so far. - bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength))); - outputOffset += outputIndexSize * sequenceLength; - } - - sequenceStart = index; - sequenceLength = 1; - } - - if (sequenceLength > 0) - { - // Commit final pending copy. - bufferCopy.Add(new BufferCopy((ulong)(srcOffset + sequenceStart * indexSize), (ulong)outputOffset, (ulong)(indexSize * sequenceLength))); - } - - var bufferCopyArray = bufferCopy.ToArray(); - - BufferHolder.InsertBufferBarrier( - gd, - cbs.CommandBuffer, - dstBuffer, - BufferHolder.DefaultAccessFlags, - AccessFlags.TransferWriteBit, - PipelineStageFlags.AllCommandsBit, - PipelineStageFlags.TransferBit, - 0, - convertedCount * outputIndexSize); - - fixed (BufferCopy* pBufferCopy = bufferCopyArray) - { - gd.Api.CmdCopyBuffer(cbs.CommandBuffer, srcBuffer, dstBuffer, (uint)bufferCopyArray.Length, pBufferCopy); - } - - BufferHolder.InsertBufferBarrier( - gd, - cbs.CommandBuffer, - dstBuffer, - AccessFlags.TransferWriteBit, - BufferHolder.DefaultAccessFlags, - PipelineStageFlags.TransferBit, - PipelineStageFlags.AllCommandsBit, - 0, - convertedCount * outputIndexSize); - } - - public void CopyIncompatibleFormats( - VulkanRenderer gd, - CommandBufferScoped cbs, - TextureView src, - TextureView dst, - int srcLayer, - int dstLayer, - int srcLevel, - int dstLevel, - int depth, - int levels) - { - const int ParamsBufferSize = 4; - - Span<int> shaderParams = stackalloc int[sizeof(int)]; - - int srcBpp = src.Info.BytesPerPixel; - int dstBpp = dst.Info.BytesPerPixel; - - int ratio = srcBpp < dstBpp ? dstBpp / srcBpp : srcBpp / dstBpp; - - shaderParams[0] = BitOperations.Log2((uint)ratio); - - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize); - - gd.BufferManager.SetData<int>(bufferHandle, 0, shaderParams); - - TextureView.InsertImageBarrier( - gd.Api, - cbs.CommandBuffer, - src.GetImage().Get(cbs).Value, - TextureStorage.DefaultAccessMask, - AccessFlags.ShaderReadBit, - PipelineStageFlags.AllCommandsBit, - PipelineStageFlags.ComputeShaderBit, - ImageAspectFlags.ColorBit, - src.FirstLayer + srcLayer, - src.FirstLevel + srcLevel, - depth, - levels); - - _pipeline.SetCommandBuffer(cbs); - - _pipeline.SetProgram(srcBpp < dstBpp ? _programColorCopyWidening : _programColorCopyShortening); - - // Calculate ideal component size, given our constraints: - // - Component size must not exceed bytes per pixel of source and destination image formats. - // - Maximum component size is 4 (R32). - int componentSize = Math.Min(Math.Min(srcBpp, dstBpp), 4); - - var srcFormat = GetFormat(componentSize, srcBpp / componentSize); - var dstFormat = GetFormat(componentSize, dstBpp / componentSize); - - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); - - for (int l = 0; l < levels; l++) - { - for (int z = 0; z < depth; z++) - { - var srcView = Create2DLayerView(src, srcLayer + z, srcLevel + l, srcFormat); - var dstView = Create2DLayerView(dst, dstLayer + z, dstLevel + l); - - _pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null); - _pipeline.SetImage(0, dstView, dstFormat); - - int dispatchX = (Math.Min(srcView.Info.Width, dstView.Info.Width) + 31) / 32; - int dispatchY = (Math.Min(srcView.Info.Height, dstView.Info.Height) + 31) / 32; - - _pipeline.DispatchCompute(dispatchX, dispatchY, 1); - - if (srcView != src) - { - srcView.Release(); - } - - if (dstView != dst) - { - dstView.Release(); - } - } - } - - gd.BufferManager.Delete(bufferHandle); - - _pipeline.Finish(gd, cbs); - - TextureView.InsertImageBarrier( - gd.Api, - cbs.CommandBuffer, - dst.GetImage().Get(cbs).Value, - AccessFlags.ShaderWriteBit, - TextureStorage.DefaultAccessMask, - PipelineStageFlags.ComputeShaderBit, - PipelineStageFlags.AllCommandsBit, - ImageAspectFlags.ColorBit, - dst.FirstLayer + dstLayer, - dst.FirstLevel + dstLevel, - depth, - levels); - } - - public void CopyMSToNonMS(VulkanRenderer gd, CommandBufferScoped cbs, TextureView src, TextureView dst, int srcLayer, int dstLayer, int depth) - { - const int ParamsBufferSize = 16; - - Span<int> shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)]; - - int samples = src.Info.Samples; - bool isDepthOrStencil = src.Info.Format.IsDepthOrStencil(); - var aspectFlags = src.Info.Format.ConvertAspectFlags(); - - // X and Y are the expected texture samples. - // Z and W are the actual texture samples used. - // They may differ if the GPU does not support the samples count requested and we had to use a lower amount. - (shaderParams[0], shaderParams[1]) = GetSampleCountXYLog2(samples); - (shaderParams[2], shaderParams[3]) = GetSampleCountXYLog2((int)TextureStorage.ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)samples)); - - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize); - - gd.BufferManager.SetData<int>(bufferHandle, 0, shaderParams); - - TextureView.InsertImageBarrier( - gd.Api, - cbs.CommandBuffer, - src.GetImage().Get(cbs).Value, - TextureStorage.DefaultAccessMask, - AccessFlags.ShaderReadBit, - PipelineStageFlags.AllCommandsBit, - isDepthOrStencil ? PipelineStageFlags.FragmentShaderBit : PipelineStageFlags.ComputeShaderBit, - aspectFlags, - src.FirstLayer + srcLayer, - src.FirstLevel, - depth, - 1); - - _pipeline.SetCommandBuffer(cbs); - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); - - if (isDepthOrStencil) - { - // We can't use compute for this case because compute can't modify depth textures. - - Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1]; - - var rect = new Rectangle<float>(0, 0, dst.Width, dst.Height); - - viewports[0] = new GAL.Viewport( - rect, - ViewportSwizzle.PositiveX, - ViewportSwizzle.PositiveY, - ViewportSwizzle.PositiveZ, - ViewportSwizzle.PositiveW, - 0f, - 1f); - - Span<Rectangle<int>> scissors = stackalloc Rectangle<int>[1]; - - scissors[0] = new Rectangle<int>(0, 0, dst.Width, dst.Height); - - _pipeline.SetScissors(scissors); - _pipeline.SetViewports(viewports, false); - _pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip); - - for (int z = 0; z < depth; z++) - { - var srcView = Create2DLayerView(src, srcLayer + z, 0); - var dstView = Create2DLayerView(dst, dstLayer + z, 0); - - _pipeline.SetRenderTarget( - ((TextureView)dstView).GetImageViewForAttachment(), - (uint)dst.Width, - (uint)dst.Height, - true, - dst.VkFormat); - - CopyMSDraw(srcView, aspectFlags, fromMS: true); - - if (srcView != src) - { - srcView.Release(); - } - - if (dstView != dst) - { - dstView.Release(); - } - } - } - else - { - var format = GetFormat(src.Info.BytesPerPixel); - - int dispatchX = (dst.Info.Width + 31) / 32; - int dispatchY = (dst.Info.Height + 31) / 32; - - _pipeline.SetProgram(_programColorCopyToNonMs); - - for (int z = 0; z < depth; z++) - { - var srcView = Create2DLayerView(src, srcLayer + z, 0, format); - var dstView = Create2DLayerView(dst, dstLayer + z, 0); - - _pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null); - _pipeline.SetImage(0, dstView, format); - - _pipeline.DispatchCompute(dispatchX, dispatchY, 1); - - if (srcView != src) - { - srcView.Release(); - } - - if (dstView != dst) - { - dstView.Release(); - } - } - } - - gd.BufferManager.Delete(bufferHandle); - - _pipeline.Finish(gd, cbs); - - TextureView.InsertImageBarrier( - gd.Api, - cbs.CommandBuffer, - dst.GetImage().Get(cbs).Value, - isDepthOrStencil ? AccessFlags.DepthStencilAttachmentWriteBit : AccessFlags.ShaderWriteBit, - TextureStorage.DefaultAccessMask, - isDepthOrStencil ? PipelineStageFlags.LateFragmentTestsBit : PipelineStageFlags.ComputeShaderBit, - PipelineStageFlags.AllCommandsBit, - aspectFlags, - dst.FirstLayer + dstLayer, - dst.FirstLevel, - depth, - 1); - } - - public void CopyNonMSToMS(VulkanRenderer gd, CommandBufferScoped cbs, TextureView src, TextureView dst, int srcLayer, int dstLayer, int depth) - { - const int ParamsBufferSize = 16; - - Span<int> shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)]; - - int samples = dst.Info.Samples; - bool isDepthOrStencil = src.Info.Format.IsDepthOrStencil(); - var aspectFlags = src.Info.Format.ConvertAspectFlags(); - - // X and Y are the expected texture samples. - // Z and W are the actual texture samples used. - // They may differ if the GPU does not support the samples count requested and we had to use a lower amount. - (shaderParams[0], shaderParams[1]) = GetSampleCountXYLog2(samples); - (shaderParams[2], shaderParams[3]) = GetSampleCountXYLog2((int)TextureStorage.ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)samples)); - - var bufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize); - - gd.BufferManager.SetData<int>(bufferHandle, 0, shaderParams); - - TextureView.InsertImageBarrier( - gd.Api, - cbs.CommandBuffer, - src.GetImage().Get(cbs).Value, - TextureStorage.DefaultAccessMask, - AccessFlags.ShaderReadBit, - PipelineStageFlags.AllCommandsBit, - PipelineStageFlags.FragmentShaderBit, - aspectFlags, - src.FirstLayer + srcLayer, - src.FirstLevel, - depth, - 1); - - _pipeline.SetCommandBuffer(cbs); - - Span<GAL.Viewport> viewports = stackalloc GAL.Viewport[1]; - - var rect = new Rectangle<float>(0, 0, dst.Width, dst.Height); - - viewports[0] = new GAL.Viewport( - rect, - ViewportSwizzle.PositiveX, - ViewportSwizzle.PositiveY, - ViewportSwizzle.PositiveZ, - ViewportSwizzle.PositiveW, - 0f, - 1f); - - Span<Rectangle<int>> scissors = stackalloc Rectangle<int>[1]; - - scissors[0] = new Rectangle<int>(0, 0, dst.Width, dst.Height); - - _pipeline.SetRenderTargetColorMasks(new uint[] { 0xf }); - _pipeline.SetScissors(scissors); - _pipeline.SetViewports(viewports, false); - _pipeline.SetPrimitiveTopology(GAL.PrimitiveTopology.TriangleStrip); - - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(bufferHandle, 0, ParamsBufferSize)) }); - - if (isDepthOrStencil) - { - for (int z = 0; z < depth; z++) - { - var srcView = Create2DLayerView(src, srcLayer + z, 0); - var dstView = Create2DLayerView(dst, dstLayer + z, 0); - - _pipeline.SetRenderTarget( - ((TextureView)dstView).GetImageViewForAttachment(), - (uint)dst.Width, - (uint)dst.Height, - (uint)samples, - true, - dst.VkFormat); - - CopyMSDraw(srcView, aspectFlags, fromMS: false); - - if (srcView != src) - { - srcView.Release(); - } - - if (dstView != dst) - { - dstView.Release(); - } - } - } - else - { - _pipeline.SetProgram(_programColorDrawToMs); - - var format = GetFormat(src.Info.BytesPerPixel); - var vkFormat = FormatTable.GetFormat(format); - - for (int z = 0; z < depth; z++) - { - var srcView = Create2DLayerView(src, srcLayer + z, 0, format); - var dstView = Create2DLayerView(dst, dstLayer + z, 0); - - _pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, srcView, null); - _pipeline.SetRenderTarget( - ((TextureView)dstView).GetView(format).GetImageViewForAttachment(), - (uint)dst.Width, - (uint)dst.Height, - (uint)samples, - false, - vkFormat); - - _pipeline.Draw(4, 1, 0, 0); - - if (srcView != src) - { - srcView.Release(); - } - - if (dstView != dst) - { - dstView.Release(); - } - } - } - - gd.BufferManager.Delete(bufferHandle); - - _pipeline.Finish(gd, cbs); - - TextureView.InsertImageBarrier( - gd.Api, - cbs.CommandBuffer, - dst.GetImage().Get(cbs).Value, - isDepthOrStencil ? AccessFlags.DepthStencilAttachmentWriteBit : AccessFlags.ColorAttachmentWriteBit, - TextureStorage.DefaultAccessMask, - isDepthOrStencil ? PipelineStageFlags.LateFragmentTestsBit : PipelineStageFlags.ColorAttachmentOutputBit, - PipelineStageFlags.AllCommandsBit, - aspectFlags, - dst.FirstLayer + dstLayer, - dst.FirstLevel, - depth, - 1); - } - - private void CopyMSDraw(TextureView src, ImageAspectFlags aspectFlags, bool fromMS) - { - if (aspectFlags.HasFlag(ImageAspectFlags.DepthBit)) - { - var depthTexture = CreateDepthOrStencilView(src, DepthStencilMode.Depth); - - CopyMSAspectDraw(depthTexture, fromMS, isDepth: true); - - if (depthTexture != src) - { - depthTexture.Release(); - } - } - - if (aspectFlags.HasFlag(ImageAspectFlags.StencilBit) && _programStencilDrawToMs != null) - { - var stencilTexture = CreateDepthOrStencilView(src, DepthStencilMode.Stencil); - - CopyMSAspectDraw(stencilTexture, fromMS, isDepth: false); - - if (stencilTexture != src) - { - stencilTexture.Release(); - } - } - } - - private void CopyMSAspectDraw(TextureView src, bool fromMS, bool isDepth) - { - _pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, _samplerNearest); - - if (isDepth) - { - _pipeline.SetProgram(fromMS ? _programDepthDrawToNonMs : _programDepthDrawToMs); - _pipeline.SetDepthTest(new DepthTestDescriptor(true, true, GAL.CompareOp.Always)); - } - else - { - _pipeline.SetProgram(fromMS ? _programStencilDrawToNonMs : _programStencilDrawToMs); - _pipeline.SetStencilTest(CreateStencilTestDescriptor(true)); - } - - _pipeline.Draw(4, 1, 0, 0); - - if (isDepth) - { - _pipeline.SetDepthTest(new DepthTestDescriptor(false, false, GAL.CompareOp.Always)); - } - else - { - _pipeline.SetStencilTest(CreateStencilTestDescriptor(false)); - } - } - - private static (int, int) GetSampleCountXYLog2(int samples) - { - int samplesInXLog2 = 0; - int samplesInYLog2 = 0; - - switch (samples) - { - case 2: // 2x1 - samplesInXLog2 = 1; - break; - case 4: // 2x2 - samplesInXLog2 = 1; - samplesInYLog2 = 1; - break; - case 8: // 4x2 - samplesInXLog2 = 2; - samplesInYLog2 = 1; - break; - case 16: // 4x4 - samplesInXLog2 = 2; - samplesInYLog2 = 2; - break; - case 32: // 8x4 - samplesInXLog2 = 3; - samplesInYLog2 = 2; - break; - case 64: // 8x8 - samplesInXLog2 = 3; - samplesInYLog2 = 3; - break; - } - - return (samplesInXLog2, samplesInYLog2); - } - - private static TextureView Create2DLayerView(TextureView from, int layer, int level, GAL.Format? format = null) - { - if (from.Info.Target == Target.Texture2D && level == 0 && (format == null || format.Value == from.Info.Format)) - { - return from; - } - - var target = from.Info.Target switch - { - Target.Texture1DArray => Target.Texture1D, - Target.Texture2DMultisampleArray => Target.Texture2DMultisample, - _ => Target.Texture2D - }; - - var info = new TextureCreateInfo( - from.Info.Width, - from.Info.Height, - from.Info.Depth, - 1, - from.Info.Samples, - from.Info.BlockWidth, - from.Info.BlockHeight, - from.Info.BytesPerPixel, - format ?? from.Info.Format, - from.Info.DepthStencilMode, - target, - from.Info.SwizzleR, - from.Info.SwizzleG, - from.Info.SwizzleB, - from.Info.SwizzleA); - - return from.CreateViewImpl(info, layer, level); - } - - private static GAL.Format GetFormat(int bytesPerPixel) - { - return bytesPerPixel switch - { - 1 => GAL.Format.R8Uint, - 2 => GAL.Format.R16Uint, - 4 => GAL.Format.R32Uint, - 8 => GAL.Format.R32G32Uint, - 16 => GAL.Format.R32G32B32A32Uint, - _ => throw new ArgumentException($"Invalid bytes per pixel {bytesPerPixel}.") - }; - } - - private static GAL.Format GetFormat(int componentSize, int componentsCount) - { - if (componentSize == 1) - { - return componentsCount switch - { - 1 => GAL.Format.R8Uint, - 2 => GAL.Format.R8G8Uint, - 4 => GAL.Format.R8G8B8A8Uint, - _ => throw new ArgumentException($"Invalid components count {componentsCount}.") - }; - } - else if (componentSize == 2) - { - return componentsCount switch - { - 1 => GAL.Format.R16Uint, - 2 => GAL.Format.R16G16Uint, - 4 => GAL.Format.R16G16B16A16Uint, - _ => throw new ArgumentException($"Invalid components count {componentsCount}.") - }; - } - else if (componentSize == 4) - { - return componentsCount switch - { - 1 => GAL.Format.R32Uint, - 2 => GAL.Format.R32G32Uint, - 4 => GAL.Format.R32G32B32A32Uint, - _ => throw new ArgumentException($"Invalid components count {componentsCount}.") - }; - } - else - { - throw new ArgumentException($"Invalid component size {componentSize}."); - } - } - - public void ConvertIndexBufferIndirect( - VulkanRenderer gd, - CommandBufferScoped cbs, - BufferHolder srcIndirectBuffer, - BufferHolder dstIndirectBuffer, - BufferRange drawCountBuffer, - BufferHolder srcIndexBuffer, - BufferHolder dstIndexBuffer, - IndexBufferPattern pattern, - int indexSize, - int srcIndexBufferOffset, - int srcIndexBufferSize, - int srcIndirectBufferOffset, - bool hasDrawCount, - int maxDrawCount, - int indirectDataStride) - { - // TODO: Support conversion with primitive restart enabled. - - BufferRange drawCountBufferAligned = new BufferRange( - drawCountBuffer.Handle, - drawCountBuffer.Offset & ~(UniformBufferAlignment - 1), - UniformBufferAlignment); - - int indirectDataSize = maxDrawCount * indirectDataStride; - - int indexCount = srcIndexBufferSize / indexSize; - int primitivesCount = pattern.GetPrimitiveCount(indexCount); - int convertedCount = pattern.GetConvertedCount(indexCount); - int outputIndexSize = 4; - - var srcBuffer = srcIndexBuffer.GetBuffer().Get(cbs, srcIndexBufferOffset, indexCount * indexSize).Value; - var dstBuffer = dstIndexBuffer.GetBuffer().Get(cbs, 0, convertedCount * outputIndexSize).Value; - - const int ParamsBufferSize = 24 * sizeof(int); - const int ParamsIndirectDispatchOffset = 16 * sizeof(int); - const int ParamsIndirectDispatchSize = 3 * sizeof(int); - - Span<int> shaderParams = stackalloc int[ParamsBufferSize / sizeof(int)]; - - shaderParams[8] = pattern.PrimitiveVertices; - shaderParams[9] = pattern.PrimitiveVerticesOut; - shaderParams[10] = indexSize; - shaderParams[11] = outputIndexSize; - shaderParams[12] = pattern.BaseIndex; - shaderParams[13] = pattern.IndexStride; - shaderParams[14] = srcIndexBufferOffset; - shaderParams[15] = primitivesCount; - shaderParams[16] = 1; - shaderParams[17] = 1; - shaderParams[18] = 1; - shaderParams[19] = hasDrawCount ? 1 : 0; - shaderParams[20] = maxDrawCount; - shaderParams[21] = (drawCountBuffer.Offset & (UniformBufferAlignment - 1)) / 4; - shaderParams[22] = indirectDataStride / 4; - shaderParams[23] = srcIndirectBufferOffset / 4; - - pattern.OffsetIndex.CopyTo(shaderParams.Slice(0, pattern.OffsetIndex.Length)); - - var patternBufferHandle = gd.BufferManager.CreateWithHandle(gd, ParamsBufferSize, out var patternBuffer); - var patternBufferAuto = patternBuffer.GetBuffer(); - - gd.BufferManager.SetData<int>(patternBufferHandle, 0, shaderParams); - - _pipeline.SetCommandBuffer(cbs); - - BufferHolder.InsertBufferBarrier( - gd, - cbs.CommandBuffer, - srcIndirectBuffer.GetBuffer().Get(cbs, srcIndirectBufferOffset, indirectDataSize).Value, - BufferHolder.DefaultAccessFlags, - AccessFlags.ShaderReadBit, - PipelineStageFlags.AllCommandsBit, - PipelineStageFlags.ComputeShaderBit, - srcIndirectBufferOffset, - indirectDataSize); - - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, drawCountBufferAligned) }); - _pipeline.SetStorageBuffers(1, new[] { srcIndirectBuffer.GetBuffer(), dstIndirectBuffer.GetBuffer(), patternBuffer.GetBuffer() }); - - _pipeline.SetProgram(_programConvertIndirectData); - _pipeline.DispatchCompute(1, 1, 1); - - BufferHolder.InsertBufferBarrier( - gd, - cbs.CommandBuffer, - patternBufferAuto.Get(cbs, ParamsIndirectDispatchOffset, ParamsIndirectDispatchSize).Value, - AccessFlags.ShaderWriteBit, - AccessFlags.IndirectCommandReadBit, - PipelineStageFlags.ComputeShaderBit, - PipelineStageFlags.DrawIndirectBit, - ParamsIndirectDispatchOffset, - ParamsIndirectDispatchSize); - - BufferHolder.InsertBufferBarrier( - gd, - cbs.CommandBuffer, - dstBuffer, - BufferHolder.DefaultAccessFlags, - AccessFlags.TransferWriteBit, - PipelineStageFlags.AllCommandsBit, - PipelineStageFlags.TransferBit, - 0, - convertedCount * outputIndexSize); - - _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(0, new BufferRange(patternBufferHandle, 0, ParamsBufferSize)) }); - _pipeline.SetStorageBuffers(1, new[] { srcIndexBuffer.GetBuffer(), dstIndexBuffer.GetBuffer() }); - - _pipeline.SetProgram(_programConvertIndexBuffer); - _pipeline.DispatchComputeIndirect(patternBufferAuto, ParamsIndirectDispatchOffset); - - BufferHolder.InsertBufferBarrier( - gd, - cbs.CommandBuffer, - dstBuffer, - AccessFlags.TransferWriteBit, - BufferHolder.DefaultAccessFlags, - PipelineStageFlags.TransferBit, - PipelineStageFlags.AllCommandsBit, - 0, - convertedCount * outputIndexSize); - - gd.BufferManager.Delete(patternBufferHandle); - - _pipeline.Finish(gd, cbs); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - _programColorBlitClearAlpha.Dispose(); - _programColorBlit.Dispose(); - _programColorBlitMs.Dispose(); - _programColorClearF.Dispose(); - _programColorClearSI.Dispose(); - _programColorClearUI.Dispose(); - _programStrideChange.Dispose(); - _programConvertIndexBuffer.Dispose(); - _programConvertIndirectData.Dispose(); - _programColorCopyShortening.Dispose(); - _programColorCopyToNonMs.Dispose(); - _programColorCopyWidening.Dispose(); - _programColorDrawToMs.Dispose(); - _programDepthBlit.Dispose(); - _programDepthBlitMs.Dispose(); - _programDepthDrawToMs.Dispose(); - _programDepthDrawToNonMs.Dispose(); - _programStencilBlit?.Dispose(); - _programStencilBlitMs?.Dispose(); - _programStencilDrawToMs?.Dispose(); - _programStencilDrawToNonMs?.Dispose(); - _samplerNearest.Dispose(); - _samplerLinear.Dispose(); - _pipeline.Dispose(); - } - } - - public void Dispose() - { - Dispose(true); - } - } -} |
