MTLObjectCache.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright 2022 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <Metal/Metal.h>
  5. #include <memory>
  6. #include "VideoBackends/Metal/MRCHelpers.h"
  7. #include "VideoCommon/BPMemory.h"
  8. #include "VideoCommon/RenderState.h"
  9. struct AbstractPipelineConfig;
  10. class AbstractPipeline;
  11. namespace Metal
  12. {
  13. class Shader;
  14. extern MRCOwned<id<MTLDevice>> g_device;
  15. extern MRCOwned<id<MTLCommandQueue>> g_queue;
  16. struct DepthStencilSelector
  17. {
  18. u8 value;
  19. DepthStencilSelector() : value(0) {}
  20. DepthStencilSelector(bool update_enable, enum CompareMode cmp)
  21. : value(update_enable | (static_cast<u32>(cmp) << 1))
  22. {
  23. }
  24. DepthStencilSelector(DepthState state)
  25. : DepthStencilSelector(state.testenable ? state.updateenable : false,
  26. state.testenable ? state.func : CompareMode::Always)
  27. {
  28. }
  29. bool UpdateEnable() const { return value & 1; }
  30. enum CompareMode CompareMode() const { return static_cast<enum CompareMode>(value >> 1); }
  31. bool operator==(const DepthStencilSelector& other) const { return value == other.value; }
  32. static constexpr size_t N_VALUES = 1 << 4;
  33. };
  34. struct SamplerSelector
  35. {
  36. u8 value;
  37. SamplerSelector() : value(0) {}
  38. SamplerSelector(SamplerState state)
  39. {
  40. value = (static_cast<u32>(state.tm0.min_filter.Value()) << 0) |
  41. (static_cast<u32>(state.tm0.mag_filter.Value()) << 1) |
  42. (static_cast<u32>(state.tm0.mipmap_filter.Value()) << 2) |
  43. (static_cast<u32>(state.tm0.anisotropic_filtering) << 3);
  44. value |= (static_cast<u32>(state.tm0.wrap_u.Value()) +
  45. 3 * static_cast<u32>(state.tm0.wrap_v.Value()))
  46. << 4;
  47. }
  48. FilterMode MinFilter() const { return static_cast<FilterMode>(value & 1); }
  49. FilterMode MagFilter() const { return static_cast<FilterMode>((value >> 1) & 1); }
  50. FilterMode MipFilter() const { return static_cast<FilterMode>((value >> 2) & 1); }
  51. WrapMode WrapU() const { return static_cast<WrapMode>((value >> 4) % 3); }
  52. WrapMode WrapV() const { return static_cast<WrapMode>((value >> 4) / 3); }
  53. bool AnisotropicFiltering() const { return ((value >> 3) & 1); }
  54. bool operator==(const SamplerSelector& other) const { return value == other.value; }
  55. static constexpr size_t N_VALUES = (1 << 4) * 9;
  56. };
  57. class ObjectCache
  58. {
  59. ObjectCache();
  60. public:
  61. ~ObjectCache();
  62. static void Initialize(MRCOwned<id<MTLDevice>> device);
  63. static void Shutdown();
  64. id<MTLDepthStencilState> GetDepthStencil(DepthStencilSelector sel) { return m_dss[sel.value]; }
  65. id<MTLSamplerState> GetSampler(SamplerSelector sel)
  66. {
  67. if (!m_samplers[sel.value]) [[unlikely]]
  68. m_samplers[sel.value] = CreateSampler(sel);
  69. return m_samplers[sel.value];
  70. }
  71. id<MTLSamplerState> GetSampler(SamplerState state) { return GetSampler(SamplerSelector(state)); }
  72. void ReloadSamplers();
  73. std::unique_ptr<AbstractPipeline> CreatePipeline(const AbstractPipelineConfig& config);
  74. void ShaderDestroyed(const Shader* shader);
  75. private:
  76. class Internal;
  77. std::unique_ptr<Internal> m_internal;
  78. MRCOwned<id<MTLSamplerState>> CreateSampler(SamplerSelector sel);
  79. MRCOwned<id<MTLDepthStencilState>> m_dss[DepthStencilSelector::N_VALUES];
  80. MRCOwned<id<MTLSamplerState>> m_samplers[SamplerSelector::N_VALUES];
  81. };
  82. extern std::unique_ptr<ObjectCache> g_object_cache;
  83. } // namespace Metal