/ src / Ryujinx.Graphics.Vulkan / SamplerHolder.cs
SamplerHolder.cs
  1  using Ryujinx.Graphics.GAL;
  2  using Silk.NET.Vulkan;
  3  using SamplerCreateInfo = Ryujinx.Graphics.GAL.SamplerCreateInfo;
  4  
  5  namespace Ryujinx.Graphics.Vulkan
  6  {
  7      class SamplerHolder : ISampler
  8      {
  9          private readonly VulkanRenderer _gd;
 10          private readonly Auto<DisposableSampler> _sampler;
 11  
 12          public unsafe SamplerHolder(VulkanRenderer gd, Device device, SamplerCreateInfo info)
 13          {
 14              _gd = gd;
 15  
 16              gd.Samplers.Add(this);
 17  
 18              (Filter minFilter, SamplerMipmapMode mipFilter) = info.MinFilter.Convert();
 19  
 20              float minLod = info.MinLod;
 21              float maxLod = info.MaxLod;
 22  
 23              if (info.MinFilter == MinFilter.Nearest || info.MinFilter == MinFilter.Linear)
 24              {
 25                  minLod = 0;
 26                  maxLod = 0.25f;
 27              }
 28  
 29              var borderColor = GetConstrainedBorderColor(info.BorderColor, out var cantConstrain);
 30  
 31              var samplerCreateInfo = new Silk.NET.Vulkan.SamplerCreateInfo
 32              {
 33                  SType = StructureType.SamplerCreateInfo,
 34                  MagFilter = info.MagFilter.Convert(),
 35                  MinFilter = minFilter,
 36                  MipmapMode = mipFilter,
 37                  AddressModeU = info.AddressU.Convert(),
 38                  AddressModeV = info.AddressV.Convert(),
 39                  AddressModeW = info.AddressP.Convert(),
 40                  MipLodBias = info.MipLodBias,
 41                  AnisotropyEnable = info.MaxAnisotropy != 1f,
 42                  MaxAnisotropy = info.MaxAnisotropy,
 43                  CompareEnable = info.CompareMode == CompareMode.CompareRToTexture,
 44                  CompareOp = info.CompareOp.Convert(),
 45                  MinLod = minLod,
 46                  MaxLod = maxLod,
 47                  BorderColor = borderColor,
 48                  UnnormalizedCoordinates = false, // TODO: Use unnormalized coordinates.
 49              };
 50  
 51              SamplerCustomBorderColorCreateInfoEXT customBorderColor;
 52  
 53              if (cantConstrain && gd.Capabilities.SupportsCustomBorderColor)
 54              {
 55                  var color = new ClearColorValue(
 56                      info.BorderColor.Red,
 57                      info.BorderColor.Green,
 58                      info.BorderColor.Blue,
 59                      info.BorderColor.Alpha);
 60  
 61                  customBorderColor = new SamplerCustomBorderColorCreateInfoEXT
 62                  {
 63                      SType = StructureType.SamplerCustomBorderColorCreateInfoExt,
 64                      CustomBorderColor = color,
 65                  };
 66  
 67                  samplerCreateInfo.PNext = &customBorderColor;
 68                  samplerCreateInfo.BorderColor = BorderColor.FloatCustomExt;
 69              }
 70  
 71              gd.Api.CreateSampler(device, in samplerCreateInfo, null, out var sampler).ThrowOnError();
 72  
 73              _sampler = new Auto<DisposableSampler>(new DisposableSampler(gd.Api, device, sampler));
 74          }
 75  
 76          private static BorderColor GetConstrainedBorderColor(ColorF arbitraryBorderColor, out bool cantConstrain)
 77          {
 78              float r = arbitraryBorderColor.Red;
 79              float g = arbitraryBorderColor.Green;
 80              float b = arbitraryBorderColor.Blue;
 81              float a = arbitraryBorderColor.Alpha;
 82  
 83              if (r == 0f && g == 0f && b == 0f)
 84              {
 85                  if (a == 1f)
 86                  {
 87                      cantConstrain = false;
 88                      return BorderColor.FloatOpaqueBlack;
 89                  }
 90  
 91                  if (a == 0f)
 92                  {
 93                      cantConstrain = false;
 94                      return BorderColor.FloatTransparentBlack;
 95                  }
 96              }
 97              else if (r == 1f && g == 1f && b == 1f && a == 1f)
 98              {
 99                  cantConstrain = false;
100                  return BorderColor.FloatOpaqueWhite;
101              }
102  
103              cantConstrain = true;
104              return BorderColor.FloatOpaqueBlack;
105          }
106  
107          public Auto<DisposableSampler> GetSampler()
108          {
109              return _sampler;
110          }
111  
112          public void Dispose()
113          {
114              if (_gd.Samplers.Remove(this))
115              {
116                  _sampler.Dispose();
117              }
118          }
119      }
120  }