gpu_framebuffer_manager.h (4054B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0) 3 4 #pragma once 5 6 #include "common/assert.h" 7 8 #include "gpu_device.h" 9 #include "gpu_texture.h" 10 11 #include <unordered_map> 12 13 class GPUFramebufferManagerBase 14 { 15 protected: 16 struct Key 17 { 18 GPUTexture* rts[GPUDevice::MAX_RENDER_TARGETS]; 19 GPUTexture* ds; 20 u32 num_rts; 21 u32 flags; 22 23 bool operator==(const Key& rhs) const; 24 bool operator!=(const Key& rhs) const; 25 26 bool ContainsRT(const GPUTexture* tex) const; 27 }; 28 29 struct KeyHash 30 { 31 size_t operator()(const Key& key) const; 32 }; 33 }; 34 35 template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags), 36 void (*DestroyFunc)(FBOType fbo)> 37 class GPUFramebufferManager : public GPUFramebufferManagerBase 38 { 39 public: 40 GPUFramebufferManager() = default; 41 ~GPUFramebufferManager(); 42 43 FBOType Lookup(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags); 44 45 void RemoveReferences(const GPUTexture* tex); 46 void RemoveRTReferences(const GPUTexture* tex); 47 void RemoveDSReferences(const GPUTexture* tex); 48 49 void Clear(); 50 51 private: 52 using MapType = std::unordered_map<Key, FBOType, KeyHash>; 53 54 MapType m_map; 55 }; 56 57 template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags), 58 void (*DestroyFunc)(FBOType fbo)> 59 GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::~GPUFramebufferManager() 60 { 61 Clear(); 62 } 63 64 template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags), 65 void (*DestroyFunc)(FBOType fbo)> 66 FBOType GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::Lookup(GPUTexture* const* rts, u32 num_rts, 67 GPUTexture* ds, u32 flags) 68 { 69 Key key; 70 for (u32 i = 0; i < num_rts; i++) 71 key.rts[i] = rts[i]; 72 for (u32 i = num_rts; i < GPUDevice::MAX_RENDER_TARGETS; i++) 73 key.rts[i] = nullptr; 74 key.ds = ds; 75 key.num_rts = num_rts; 76 key.flags = flags; 77 78 auto it = m_map.find(key); 79 if (it == m_map.end()) 80 { 81 FBOType fbo = FactoryFunc(rts, num_rts, ds, flags); 82 if (!fbo) 83 return fbo; 84 85 it = m_map.emplace(key, fbo).first; 86 } 87 88 return it->second; 89 } 90 91 template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags), 92 void (*DestroyFunc)(FBOType fbo)> 93 void GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::RemoveRTReferences(const GPUTexture* tex) 94 { 95 DebugAssert(tex->IsRenderTarget() || tex->IsRWTexture()); 96 for (auto it = m_map.begin(); it != m_map.end();) 97 { 98 if (!it->first.ContainsRT(tex)) 99 { 100 ++it; 101 continue; 102 } 103 104 DestroyFunc(it->second); 105 it = m_map.erase(it); 106 } 107 } 108 109 template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags), 110 void (*DestroyFunc)(FBOType fbo)> 111 void GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::RemoveDSReferences(const GPUTexture* tex) 112 { 113 DebugAssert(tex->IsDepthStencil()); 114 for (auto it = m_map.begin(); it != m_map.end();) 115 { 116 if (it->first.ds != tex) 117 { 118 ++it; 119 continue; 120 } 121 122 DestroyFunc(it->second); 123 it = m_map.erase(it); 124 } 125 } 126 127 template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags), 128 void (*DestroyFunc)(FBOType fbo)> 129 void GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::RemoveReferences(const GPUTexture* tex) 130 { 131 if (tex->IsRenderTarget()) 132 RemoveRTReferences(tex); 133 else if (tex->IsDepthStencil()) 134 RemoveDSReferences(tex); 135 } 136 137 template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags), 138 void (*DestroyFunc)(FBOType fbo)> 139 void GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::Clear() 140 { 141 for (const auto& it : m_map) 142 DestroyFunc(it.second); 143 m_map.clear(); 144 }