Sampler.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using Ryujinx.Graphics.GAL;
  2. using System;
  3. using System.Numerics;
  4. namespace Ryujinx.Graphics.Gpu.Image
  5. {
  6. /// <summary>
  7. /// Cached sampler entry for sampler pools.
  8. /// </summary>
  9. class Sampler : IDisposable
  10. {
  11. private const int MinLevelsForAnisotropic = 5;
  12. /// <summary>
  13. /// Host sampler object.
  14. /// </summary>
  15. private readonly ISampler _hostSampler;
  16. /// <summary>
  17. /// Host sampler object, with anisotropy forced.
  18. /// </summary>
  19. private readonly ISampler _anisoSampler;
  20. /// <summary>
  21. /// Creates a new instance of the cached sampler.
  22. /// </summary>
  23. /// <param name="context">The GPU context the sampler belongs to</param>
  24. /// <param name="descriptor">The Maxwell sampler descriptor</param>
  25. public Sampler(GpuContext context, SamplerDescriptor descriptor)
  26. {
  27. MinFilter minFilter = descriptor.UnpackMinFilter();
  28. MagFilter magFilter = descriptor.UnpackMagFilter();
  29. bool seamlessCubemap = descriptor.UnpackSeamlessCubemap();
  30. AddressMode addressU = descriptor.UnpackAddressU();
  31. AddressMode addressV = descriptor.UnpackAddressV();
  32. AddressMode addressP = descriptor.UnpackAddressP();
  33. CompareMode compareMode = descriptor.UnpackCompareMode();
  34. CompareOp compareOp = descriptor.UnpackCompareOp();
  35. ColorF color = new ColorF(
  36. descriptor.BorderColorR,
  37. descriptor.BorderColorG,
  38. descriptor.BorderColorB,
  39. descriptor.BorderColorA);
  40. float minLod = descriptor.UnpackMinLod();
  41. float maxLod = descriptor.UnpackMaxLod();
  42. float mipLodBias = descriptor.UnpackMipLodBias();
  43. float maxRequestedAnisotropy = descriptor.UnpackMaxAnisotropy();
  44. float maxSupportedAnisotropy = context.Capabilities.MaximumSupportedAnisotropy;
  45. _hostSampler = context.Renderer.CreateSampler(new SamplerCreateInfo(
  46. minFilter,
  47. magFilter,
  48. seamlessCubemap,
  49. addressU,
  50. addressV,
  51. addressP,
  52. compareMode,
  53. compareOp,
  54. color,
  55. minLod,
  56. maxLod,
  57. mipLodBias,
  58. Math.Min(maxRequestedAnisotropy, maxSupportedAnisotropy)));
  59. if (GraphicsConfig.MaxAnisotropy >= 0 && GraphicsConfig.MaxAnisotropy <= 16 && (minFilter == MinFilter.LinearMipmapNearest || minFilter == MinFilter.LinearMipmapLinear))
  60. {
  61. maxRequestedAnisotropy = GraphicsConfig.MaxAnisotropy;
  62. _anisoSampler = context.Renderer.CreateSampler(new SamplerCreateInfo(
  63. minFilter,
  64. magFilter,
  65. seamlessCubemap,
  66. addressU,
  67. addressV,
  68. addressP,
  69. compareMode,
  70. compareOp,
  71. color,
  72. minLod,
  73. maxLod,
  74. mipLodBias,
  75. Math.Min(maxRequestedAnisotropy, maxSupportedAnisotropy)));
  76. }
  77. }
  78. /// <summary>
  79. /// Gets a host sampler for the given texture.
  80. /// </summary>
  81. /// <param name="texture">Texture to be sampled</param>
  82. /// <returns>A host sampler</returns>
  83. public ISampler GetHostSampler(Texture texture)
  84. {
  85. return _anisoSampler != null && AllowForceAnisotropy(texture) ? _anisoSampler : _hostSampler;
  86. }
  87. /// <summary>
  88. /// Determine if the given texture can have anisotropic filtering forced.
  89. /// Filtered textures that we might want to force anisotropy on should have a lot of mip levels.
  90. /// </summary>
  91. /// <param name="texture">The texture</param>
  92. /// <returns>True if anisotropic filtering can be forced, false otherwise</returns>
  93. private static bool AllowForceAnisotropy(Texture texture)
  94. {
  95. if (texture == null || !(texture.Target == Target.Texture2D || texture.Target == Target.Texture2DArray))
  96. {
  97. return false;
  98. }
  99. int maxSize = Math.Max(texture.Info.Width, texture.Info.Height);
  100. int maxLevels = BitOperations.Log2((uint)maxSize) + 1;
  101. return texture.Info.Levels >= Math.Min(MinLevelsForAnisotropic, maxLevels);
  102. }
  103. /// <summary>
  104. /// Disposes the host sampler object.
  105. /// </summary>
  106. public void Dispose()
  107. {
  108. _hostSampler.Dispose();
  109. _anisoSampler?.Dispose();
  110. }
  111. }
  112. }