Path: blob/master/src/util/gpu_framebuffer_manager.h
4212 views
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#pragma once45#include "common/assert.h"67#include "gpu_device.h"8#include "gpu_texture.h"910#include <unordered_map>1112class GPUFramebufferManagerBase13{14protected:15struct Key16{17GPUTexture* rts[GPUDevice::MAX_RENDER_TARGETS];18GPUTexture* ds;19u32 num_rts;20u32 flags;2122bool operator==(const Key& rhs) const;23bool operator!=(const Key& rhs) const;2425bool ContainsRT(const GPUTexture* tex) const;26};2728struct KeyHash29{30size_t operator()(const Key& key) const;31};32};3334template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags),35void (*DestroyFunc)(FBOType fbo)>36class GPUFramebufferManager : public GPUFramebufferManagerBase37{38public:39GPUFramebufferManager() = default;40~GPUFramebufferManager();4142FBOType Lookup(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags);4344void RemoveReferences(const GPUTexture* tex);45void RemoveRTReferences(const GPUTexture* tex);46void RemoveDSReferences(const GPUTexture* tex);4748void Clear();4950private:51using MapType = std::unordered_map<Key, FBOType, KeyHash>;5253MapType m_map;54};5556template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags),57void (*DestroyFunc)(FBOType fbo)>58GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::~GPUFramebufferManager()59{60Clear();61}6263template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags),64void (*DestroyFunc)(FBOType fbo)>65FBOType GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::Lookup(GPUTexture* const* rts, u32 num_rts,66GPUTexture* ds, u32 flags)67{68Key key;69for (u32 i = 0; i < num_rts; i++)70key.rts[i] = rts[i];71for (u32 i = num_rts; i < GPUDevice::MAX_RENDER_TARGETS; i++)72key.rts[i] = nullptr;73key.ds = ds;74key.num_rts = num_rts;75key.flags = flags;7677auto it = m_map.find(key);78if (it == m_map.end())79{80FBOType fbo = FactoryFunc(rts, num_rts, ds, flags);81if (!fbo)82return fbo;8384it = m_map.emplace(key, fbo).first;85}8687return it->second;88}8990template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags),91void (*DestroyFunc)(FBOType fbo)>92void GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::RemoveRTReferences(const GPUTexture* tex)93{94DebugAssert(tex->IsRenderTarget());95for (auto it = m_map.begin(); it != m_map.end();)96{97if (!it->first.ContainsRT(tex))98{99++it;100continue;101}102103DestroyFunc(it->second);104it = m_map.erase(it);105}106}107108template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags),109void (*DestroyFunc)(FBOType fbo)>110void GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::RemoveDSReferences(const GPUTexture* tex)111{112DebugAssert(tex->IsDepthStencil());113for (auto it = m_map.begin(); it != m_map.end();)114{115if (it->first.ds != tex)116{117++it;118continue;119}120121DestroyFunc(it->second);122it = m_map.erase(it);123}124}125126template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags),127void (*DestroyFunc)(FBOType fbo)>128void GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::RemoveReferences(const GPUTexture* tex)129{130if (tex->IsRenderTarget())131RemoveRTReferences(tex);132else if (tex->IsDepthStencil())133RemoveDSReferences(tex);134}135136template<typename FBOType, FBOType (*FactoryFunc)(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags),137void (*DestroyFunc)(FBOType fbo)>138void GPUFramebufferManager<FBOType, FactoryFunc, DestroyFunc>::Clear()139{140for (const auto& it : m_map)141DestroyFunc(it.second);142m_map.clear();143}144145146