FormatCapabilities.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.Graphics.GAL;
  3. using Silk.NET.Vulkan;
  4. using System;
  5. using VkFormat = Silk.NET.Vulkan.Format;
  6. namespace Ryujinx.Graphics.Vulkan
  7. {
  8. class FormatCapabilities
  9. {
  10. private readonly FormatFeatureFlags[] _table;
  11. private readonly Vk _api;
  12. private readonly PhysicalDevice _physicalDevice;
  13. public FormatCapabilities(Vk api, PhysicalDevice physicalDevice)
  14. {
  15. _api = api;
  16. _physicalDevice = physicalDevice;
  17. _table = new FormatFeatureFlags[Enum.GetNames(typeof(GAL.Format)).Length];
  18. }
  19. public bool FormatsSupports(FormatFeatureFlags flags, params GAL.Format[] formats)
  20. {
  21. foreach (GAL.Format format in formats)
  22. {
  23. if (!FormatSupports(flags, format))
  24. {
  25. return false;
  26. }
  27. }
  28. return true;
  29. }
  30. public bool FormatSupports(FormatFeatureFlags flags, GAL.Format format)
  31. {
  32. var formatFeatureFlags = _table[(int)format];
  33. if (formatFeatureFlags == 0)
  34. {
  35. _api.GetPhysicalDeviceFormatProperties(_physicalDevice, FormatTable.GetFormat(format), out var fp);
  36. formatFeatureFlags = fp.OptimalTilingFeatures;
  37. _table[(int)format] = formatFeatureFlags;
  38. }
  39. return (formatFeatureFlags & flags) == flags;
  40. }
  41. public VkFormat ConvertToVkFormat(GAL.Format srcFormat)
  42. {
  43. var format = FormatTable.GetFormat(srcFormat);
  44. var requiredFeatures = FormatFeatureFlags.FormatFeatureSampledImageBit |
  45. FormatFeatureFlags.FormatFeatureTransferSrcBit |
  46. FormatFeatureFlags.FormatFeatureTransferDstBit;
  47. if (srcFormat.IsDepthOrStencil())
  48. {
  49. requiredFeatures |= FormatFeatureFlags.FormatFeatureDepthStencilAttachmentBit;
  50. }
  51. else if (srcFormat.IsRtColorCompatible())
  52. {
  53. requiredFeatures |= FormatFeatureFlags.FormatFeatureColorAttachmentBit;
  54. }
  55. if (srcFormat.IsImageCompatible())
  56. {
  57. requiredFeatures |= FormatFeatureFlags.FormatFeatureStorageImageBit;
  58. }
  59. if (!FormatSupports(requiredFeatures, srcFormat) || (IsD24S8(srcFormat) && VulkanConfiguration.ForceD24S8Unsupported))
  60. {
  61. // The format is not supported. Can we convert it to a higher precision format?
  62. if (IsD24S8(srcFormat))
  63. {
  64. format = VkFormat.D32SfloatS8Uint;
  65. }
  66. else
  67. {
  68. Logger.Error?.Print(LogClass.Gpu, $"Format {srcFormat} is not supported by the host.");
  69. }
  70. }
  71. return format;
  72. }
  73. public static bool IsD24S8(GAL.Format format)
  74. {
  75. return format == GAL.Format.D24UnormS8Uint || format == GAL.Format.S8UintD24Unorm;
  76. }
  77. }
  78. }