aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Vulkan/SamplerHolder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/SamplerHolder.cs')
-rw-r--r--Ryujinx.Graphics.Vulkan/SamplerHolder.cs117
1 files changed, 117 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Vulkan/SamplerHolder.cs b/Ryujinx.Graphics.Vulkan/SamplerHolder.cs
new file mode 100644
index 00000000..a8f7c944
--- /dev/null
+++ b/Ryujinx.Graphics.Vulkan/SamplerHolder.cs
@@ -0,0 +1,117 @@
+using Ryujinx.Graphics.GAL;
+using Silk.NET.Vulkan;
+
+namespace Ryujinx.Graphics.Vulkan
+{
+ class SamplerHolder : ISampler
+ {
+ private readonly VulkanRenderer _gd;
+ private readonly Auto<DisposableSampler> _sampler;
+
+ public unsafe SamplerHolder(VulkanRenderer gd, Device device, GAL.SamplerCreateInfo info)
+ {
+ _gd = gd;
+
+ gd.Samplers.Add(this);
+
+ (Filter minFilter, SamplerMipmapMode mipFilter) = EnumConversion.Convert(info.MinFilter);
+
+ float minLod = info.MinLod;
+ float maxLod = info.MaxLod;
+
+ if (info.MinFilter == MinFilter.Nearest || info.MinFilter == MinFilter.Linear)
+ {
+ minLod = 0;
+ maxLod = 0.25f;
+ }
+
+ var borderColor = GetConstrainedBorderColor(info.BorderColor, out var cantConstrain);
+
+ var samplerCreateInfo = new Silk.NET.Vulkan.SamplerCreateInfo()
+ {
+ SType = StructureType.SamplerCreateInfo,
+ MagFilter = info.MagFilter.Convert(),
+ MinFilter = minFilter,
+ MipmapMode = mipFilter,
+ AddressModeU = info.AddressU.Convert(),
+ AddressModeV = info.AddressV.Convert(),
+ AddressModeW = info.AddressP.Convert(),
+ MipLodBias = info.MipLodBias,
+ AnisotropyEnable = info.MaxAnisotropy != 1f,
+ MaxAnisotropy = info.MaxAnisotropy,
+ CompareEnable = info.CompareMode == CompareMode.CompareRToTexture,
+ CompareOp = info.CompareOp.Convert(),
+ MinLod = minLod,
+ MaxLod = maxLod,
+ BorderColor = borderColor,
+ UnnormalizedCoordinates = false // TODO: Use unnormalized coordinates.
+ };
+
+ SamplerCustomBorderColorCreateInfoEXT customBorderColor;
+
+ if (cantConstrain && gd.Capabilities.SupportsCustomBorderColor)
+ {
+ var color = new ClearColorValue(
+ info.BorderColor.Red,
+ info.BorderColor.Green,
+ info.BorderColor.Blue,
+ info.BorderColor.Alpha);
+
+ customBorderColor = new SamplerCustomBorderColorCreateInfoEXT()
+ {
+ SType = StructureType.SamplerCustomBorderColorCreateInfoExt,
+ CustomBorderColor = color
+ };
+
+ samplerCreateInfo.PNext = &customBorderColor;
+ }
+
+ gd.Api.CreateSampler(device, samplerCreateInfo, null, out var sampler).ThrowOnError();
+
+ _sampler = new Auto<DisposableSampler>(new DisposableSampler(gd.Api, device, sampler));
+ }
+
+ private static BorderColor GetConstrainedBorderColor(ColorF arbitraryBorderColor, out bool cantConstrain)
+ {
+ float r = arbitraryBorderColor.Red;
+ float g = arbitraryBorderColor.Green;
+ float b = arbitraryBorderColor.Blue;
+ float a = arbitraryBorderColor.Alpha;
+
+ if (r == 0f && g == 0f && b == 0f)
+ {
+ if (a == 1f)
+ {
+ cantConstrain = false;
+ return BorderColor.FloatOpaqueBlack;
+ }
+ else if (a == 0f)
+ {
+ cantConstrain = false;
+ return BorderColor.FloatTransparentBlack;
+ }
+ }
+ else if (r == 1f && g == 1f && b == 1f && a == 1f)
+ {
+ cantConstrain = false;
+ return BorderColor.FloatOpaqueWhite;
+ }
+
+ cantConstrain = true;
+ return BorderColor.FloatOpaqueBlack;
+ }
+
+ public Auto<DisposableSampler> GetSampler()
+ {
+ return _sampler;
+ }
+
+ public void Dispose()
+ {
+ if (_gd.Samplers.Remove(this))
+ {
+ _sampler.Dispose();
+ }
+ }
+ }
+}