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 }