aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Vulkan/Effects/AreaScalingFilter.cs
diff options
context:
space:
mode:
authorZenoArrows <129334871+ZenoArrows@users.noreply.github.com>2024-09-17 20:30:50 +0200
committerGitHub <noreply@github.com>2024-09-17 15:30:50 -0300
commitf39e89ece79436f5058bb58d50a1a4dcd6823f4e (patch)
tree079cd6cd332b1f2691bb13f587789e191ddf2c6d /src/Ryujinx.Graphics.Vulkan/Effects/AreaScalingFilter.cs
parentcf77c011e4f90efd93509c3852350c48f2597344 (diff)
Add area sampling scaler to allow for super-sampled anti-aliasing. (#7304)
* Add area sampling scaler to allow for super-sampled anti-aliasing. * Area scaling filter doesn't have a scaling level. * Add further clarification to the tooltip on how to achieve supersampling. * ShaderHelper: Merge the two CompileProgram functions. * Convert tabs to spaces in area scaling shaders * Fixup Vulkan and OpenGL project files. * AreaScaling: Replace texture() by texelFetch() and use integer vectors. No functional difference, but it cleans up the code a bit. * AreaScaling: Delete unused sharpening level member. Also rename _scale to _sharpeningLevel for clarity and consistency. * AreaScaling: Delete unused scaleX/scaleY uniforms. * AreaScaling: Force the alpha to 1 when storing the pixel. * AreaScaling: Remove left-over sharpening buffer.
Diffstat (limited to 'src/Ryujinx.Graphics.Vulkan/Effects/AreaScalingFilter.cs')
-rw-r--r--src/Ryujinx.Graphics.Vulkan/Effects/AreaScalingFilter.cs101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/Effects/AreaScalingFilter.cs b/src/Ryujinx.Graphics.Vulkan/Effects/AreaScalingFilter.cs
new file mode 100644
index 00000000..87b46df8
--- /dev/null
+++ b/src/Ryujinx.Graphics.Vulkan/Effects/AreaScalingFilter.cs
@@ -0,0 +1,101 @@
+using Ryujinx.Common;
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Shader;
+using Ryujinx.Graphics.Shader.Translation;
+using Silk.NET.Vulkan;
+using System;
+using Extent2D = Ryujinx.Graphics.GAL.Extents2D;
+using Format = Silk.NET.Vulkan.Format;
+using SamplerCreateInfo = Ryujinx.Graphics.GAL.SamplerCreateInfo;
+
+namespace Ryujinx.Graphics.Vulkan.Effects
+{
+ internal class AreaScalingFilter : IScalingFilter
+ {
+ private readonly VulkanRenderer _renderer;
+ private PipelineHelperShader _pipeline;
+ private ISampler _sampler;
+ private ShaderCollection _scalingProgram;
+ private Device _device;
+
+ public float Level { get; set; }
+
+ public AreaScalingFilter(VulkanRenderer renderer, Device device)
+ {
+ _device = device;
+ _renderer = renderer;
+
+ Initialize();
+ }
+
+ public void Dispose()
+ {
+ _pipeline.Dispose();
+ _scalingProgram.Dispose();
+ _sampler.Dispose();
+ }
+
+ public void Initialize()
+ {
+ _pipeline = new PipelineHelperShader(_renderer, _device);
+
+ _pipeline.Initialize();
+
+ var scalingShader = EmbeddedResources.Read("Ryujinx.Graphics.Vulkan/Effects/Shaders/AreaScaling.spv");
+
+ var scalingResourceLayout = new ResourceLayoutBuilder()
+ .Add(ResourceStages.Compute, ResourceType.UniformBuffer, 2)
+ .Add(ResourceStages.Compute, ResourceType.TextureAndSampler, 1)
+ .Add(ResourceStages.Compute, ResourceType.Image, 0, true).Build();
+
+ _sampler = _renderer.CreateSampler(SamplerCreateInfo.Create(MinFilter.Linear, MagFilter.Linear));
+
+ _scalingProgram = _renderer.CreateProgramWithMinimalLayout(new[]
+ {
+ new ShaderSource(scalingShader, ShaderStage.Compute, TargetLanguage.Spirv),
+ }, scalingResourceLayout);
+ }
+
+ public void Run(
+ TextureView view,
+ CommandBufferScoped cbs,
+ Auto<DisposableImageView> destinationTexture,
+ Format format,
+ int width,
+ int height,
+ Extent2D source,
+ Extent2D destination)
+ {
+ _pipeline.SetCommandBuffer(cbs);
+ _pipeline.SetProgram(_scalingProgram);
+ _pipeline.SetTextureAndSampler(ShaderStage.Compute, 1, view, _sampler);
+
+ ReadOnlySpan<float> dimensionsBuffer = stackalloc float[]
+ {
+ source.X1,
+ source.X2,
+ source.Y1,
+ source.Y2,
+ destination.X1,
+ destination.X2,
+ destination.Y1,
+ destination.Y2,
+ };
+
+ int rangeSize = dimensionsBuffer.Length * sizeof(float);
+ using var buffer = _renderer.BufferManager.ReserveOrCreate(_renderer, cbs, rangeSize);
+ buffer.Holder.SetDataUnchecked(buffer.Offset, dimensionsBuffer);
+
+ int threadGroupWorkRegionDim = 16;
+ int dispatchX = (width + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
+ int dispatchY = (height + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
+
+ _pipeline.SetUniformBuffers(stackalloc[] { new BufferAssignment(2, buffer.Range) });
+ _pipeline.SetImage(0, destinationTexture);
+ _pipeline.DispatchCompute(dispatchX, dispatchY, 1);
+ _pipeline.ComputeBarrier();
+
+ _pipeline.Finish();
+ }
+ }
+}