1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "BsGpuResourcePool.h"
4#include "RenderAPI/BsRenderTexture.h"
5#include "Image/BsTexture.h"
6#include "RenderAPI/BsGpuBuffer.h"
7
8namespace bs { namespace ct
9{
10 PooledRenderTexture::PooledRenderTexture(GpuResourcePool* pool)
11 :mPool(pool)
12 { }
13
14 PooledRenderTexture::~PooledRenderTexture()
15 {
16 if (mPool != nullptr)
17 mPool->_unregisterTexture(this);
18 }
19
20 PooledStorageBuffer::PooledStorageBuffer(GpuResourcePool* pool)
21 :mPool(pool)
22 { }
23
24 PooledStorageBuffer::~PooledStorageBuffer()
25 {
26 if (mPool != nullptr)
27 mPool->_unregisterBuffer(this);
28 }
29
30 GpuResourcePool::~GpuResourcePool()
31 {
32 for (auto& texture : mTextures)
33 texture.second.lock()->mPool = nullptr;
34
35 for (auto& buffer : mBuffers)
36 buffer.second.lock()->mPool = nullptr;
37 }
38
39 SPtr<PooledRenderTexture> GpuResourcePool::get(const POOLED_RENDER_TEXTURE_DESC& desc)
40 {
41 for (auto& texturePair : mTextures)
42 {
43 SPtr<PooledRenderTexture> textureData = texturePair.second.lock();
44
45 if (!textureData->mIsFree)
46 continue;
47
48 if (textureData->texture == nullptr)
49 continue;
50
51 if (matches(textureData->texture, desc))
52 {
53 textureData->mIsFree = false;
54 return textureData;
55 }
56 }
57
58 SPtr<PooledRenderTexture> newTextureData = bs_shared_ptr_new<PooledRenderTexture>(this);
59 _registerTexture(newTextureData);
60
61 TEXTURE_DESC texDesc;
62 texDesc.type = desc.type;
63 texDesc.width = desc.width;
64 texDesc.height = desc.height;
65 texDesc.depth = desc.depth;
66 texDesc.format = desc.format;
67 texDesc.usage = desc.flag;
68 texDesc.hwGamma = desc.hwGamma;
69 texDesc.numSamples = desc.numSamples;
70 texDesc.numMips = desc.numMipLevels;
71
72 if (desc.type != TEX_TYPE_3D)
73 texDesc.numArraySlices = desc.arraySize;
74
75 newTextureData->texture = Texture::create(texDesc);
76
77 if ((desc.flag & (TU_RENDERTARGET | TU_DEPTHSTENCIL)) != 0)
78 {
79 RENDER_TEXTURE_DESC rtDesc;
80
81 if ((desc.flag & TU_RENDERTARGET) != 0)
82 {
83 rtDesc.colorSurfaces[0].texture = newTextureData->texture;
84 rtDesc.colorSurfaces[0].face = 0;
85 rtDesc.colorSurfaces[0].numFaces = newTextureData->texture->getProperties().getNumFaces();
86 rtDesc.colorSurfaces[0].mipLevel = 0;
87 }
88
89 if ((desc.flag & TU_DEPTHSTENCIL) != 0)
90 {
91 rtDesc.depthStencilSurface.texture = newTextureData->texture;
92 rtDesc.depthStencilSurface.face = 0;
93 rtDesc.depthStencilSurface.numFaces = newTextureData->texture->getProperties().getNumFaces();
94 rtDesc.depthStencilSurface.mipLevel = 0;
95 }
96
97 newTextureData->renderTexture = RenderTexture::create(rtDesc);
98 }
99
100 return newTextureData;
101 }
102
103 SPtr<PooledStorageBuffer> GpuResourcePool::get(const POOLED_STORAGE_BUFFER_DESC& desc)
104 {
105 for (auto& bufferPair : mBuffers)
106 {
107 SPtr<PooledStorageBuffer> bufferData = bufferPair.second.lock();
108
109 if (!bufferData->mIsFree)
110 continue;
111
112 if (bufferData->buffer == nullptr)
113 continue;
114
115 if (matches(bufferData->buffer, desc))
116 {
117 bufferData->mIsFree = false;
118 return bufferData;
119 }
120 }
121
122 SPtr<PooledStorageBuffer> newBufferData = bs_shared_ptr_new<PooledStorageBuffer>(this);
123 _registerBuffer(newBufferData);
124
125 GPU_BUFFER_DESC bufferDesc;
126 bufferDesc.type = desc.type;
127 bufferDesc.elementSize = desc.elementSize;
128 bufferDesc.elementCount = desc.numElements;
129 bufferDesc.format = desc.format;
130 bufferDesc.usage = desc.usage;
131
132 newBufferData->buffer = GpuBuffer::create(bufferDesc);
133
134 return newBufferData;
135 }
136
137 void GpuResourcePool::release(const SPtr<PooledRenderTexture>& texture)
138 {
139 auto iterFind = mTextures.find(texture.get());
140 iterFind->second.lock()->mIsFree = true;
141 }
142
143 void GpuResourcePool::release(const SPtr<PooledStorageBuffer>& buffer)
144 {
145 auto iterFind = mBuffers.find(buffer.get());
146 iterFind->second.lock()->mIsFree = true;
147 }
148
149 bool GpuResourcePool::matches(const SPtr<Texture>& texture, const POOLED_RENDER_TEXTURE_DESC& desc)
150 {
151 const TextureProperties& texProps = texture->getProperties();
152
153 bool match = texProps.getTextureType() == desc.type
154 && texProps.getFormat() == desc.format
155 && texProps.getWidth() == desc.width
156 && texProps.getHeight() == desc.height
157 && (texProps.getUsage() & desc.flag) == desc.flag
158 && (
159 (desc.type == TEX_TYPE_2D
160 && texProps.isHardwareGammaEnabled() == desc.hwGamma
161 && texProps.getNumSamples() == desc.numSamples)
162 || (desc.type == TEX_TYPE_3D
163 && texProps.getDepth() == desc.depth)
164 || (desc.type == TEX_TYPE_CUBE_MAP)
165 )
166 && texProps.getNumArraySlices() == desc.arraySize
167 && texProps.getNumMipmaps() == desc.numMipLevels
168 ;
169
170 return match;
171 }
172
173 bool GpuResourcePool::matches(const SPtr<GpuBuffer>& buffer, const POOLED_STORAGE_BUFFER_DESC& desc)
174 {
175 const GpuBufferProperties& props = buffer->getProperties();
176
177 bool match = props.getType() == desc.type && props.getElementCount() == desc.numElements;
178 if(match)
179 {
180 if (desc.type == GBT_STANDARD)
181 match = props.getFormat() == desc.format;
182 else // Structured
183 match = props.getElementSize() == desc.elementSize;
184
185 if(match)
186 match = props.getUsage() == desc.usage;
187 }
188
189 return match;
190 }
191
192 void GpuResourcePool::_registerTexture(const SPtr<PooledRenderTexture>& texture)
193 {
194 mTextures.insert(std::make_pair(texture.get(), texture));
195 }
196
197 void GpuResourcePool::_unregisterTexture(PooledRenderTexture* texture)
198 {
199 mTextures.erase(texture);
200 }
201
202 void GpuResourcePool::_registerBuffer(const SPtr<PooledStorageBuffer>& buffer)
203 {
204 mBuffers.insert(std::make_pair(buffer.get(), buffer));
205 }
206
207 void GpuResourcePool::_unregisterBuffer(PooledStorageBuffer* buffer)
208 {
209 mBuffers.erase(buffer);
210 }
211
212 POOLED_RENDER_TEXTURE_DESC POOLED_RENDER_TEXTURE_DESC::create2D(PixelFormat format, UINT32 width, UINT32 height,
213 INT32 usage, UINT32 samples, bool hwGamma, UINT32 arraySize, UINT32 mipCount)
214 {
215 POOLED_RENDER_TEXTURE_DESC desc;
216 desc.width = width;
217 desc.height = height;
218 desc.depth = 1;
219 desc.format = format;
220 desc.numSamples = samples;
221 desc.flag = (TextureUsage)usage;
222 desc.hwGamma = hwGamma;
223 desc.type = TEX_TYPE_2D;
224 desc.arraySize = arraySize;
225 desc.numMipLevels = mipCount;
226
227 return desc;
228 }
229
230 POOLED_RENDER_TEXTURE_DESC POOLED_RENDER_TEXTURE_DESC::create3D(PixelFormat format, UINT32 width, UINT32 height,
231 UINT32 depth, INT32 usage)
232 {
233 POOLED_RENDER_TEXTURE_DESC desc;
234 desc.width = width;
235 desc.height = height;
236 desc.depth = depth;
237 desc.format = format;
238 desc.numSamples = 1;
239 desc.flag = (TextureUsage)usage;
240 desc.hwGamma = false;
241 desc.type = TEX_TYPE_3D;
242 desc.arraySize = 1;
243 desc.numMipLevels = 0;
244
245 return desc;
246 }
247
248 POOLED_RENDER_TEXTURE_DESC POOLED_RENDER_TEXTURE_DESC::createCube(PixelFormat format, UINT32 width, UINT32 height,
249 INT32 usage, UINT32 arraySize)
250 {
251 POOLED_RENDER_TEXTURE_DESC desc;
252 desc.width = width;
253 desc.height = height;
254 desc.depth = 1;
255 desc.format = format;
256 desc.numSamples = 1;
257 desc.flag = (TextureUsage)usage;
258 desc.hwGamma = false;
259 desc.type = TEX_TYPE_CUBE_MAP;
260 desc.arraySize = arraySize;
261 desc.numMipLevels = 0;
262
263 return desc;
264 }
265
266 POOLED_STORAGE_BUFFER_DESC POOLED_STORAGE_BUFFER_DESC::createStandard(GpuBufferFormat format, UINT32 numElements,
267 GpuBufferUsage usage)
268 {
269 POOLED_STORAGE_BUFFER_DESC desc;
270 desc.type = GBT_STANDARD;
271 desc.format = format;
272 desc.numElements = numElements;
273 desc.elementSize = 0;
274 desc.usage = usage;
275
276 return desc;
277 }
278
279 POOLED_STORAGE_BUFFER_DESC POOLED_STORAGE_BUFFER_DESC::createStructured(UINT32 elementSize, UINT32 numElements,
280 GpuBufferUsage usage)
281 {
282 POOLED_STORAGE_BUFFER_DESC desc;
283 desc.type = GBT_STRUCTURED;
284 desc.format = BF_UNKNOWN;
285 desc.numElements = numElements;
286 desc.elementSize = elementSize;
287 desc.usage = usage;
288
289 return desc;
290 }
291}}