Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/util/gpu_framebuffer_manager.h
4212 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.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());
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
}
145
146