1
1
#include " DrawResourcesFiller.h"
2
2
3
- DrawResourcesFiller::DrawResourcesFiller (smart_refctd_ptr<IUtilities>&& utils, IQueue* copyQueue)
4
- {
5
- m_utilities = utils;
6
- m_copyQueue = copyQueue;
7
- }
3
+ DrawResourcesFiller::DrawResourcesFiller () :
4
+ textureLRUCache(1024u )
5
+ {}
6
+
7
+ DrawResourcesFiller::DrawResourcesFiller (smart_refctd_ptr<IUtilities>&& utils, IQueue* copyQueue) :
8
+ textureLRUCache(1024u ),
9
+ m_utilities(utils),
10
+ m_copyQueue(copyQueue)
11
+ {}
8
12
9
13
// function is called when buffer is filled and we should submit draws and clear the buffers and continue filling
10
14
@@ -118,6 +122,10 @@ void DrawResourcesFiller::allocateStylesBuffer(ILogicalDevice* logicalDevice, ui
118
122
119
123
void DrawResourcesFiller::allocateMSDFTextures (ILogicalDevice* logicalDevice, uint32_t maxMSDFs)
120
124
{
125
+ // TODO[Erfan]: Fix resize TextureLRUCache
126
+ // assert(maxMSDFs == textureLRUCache.capacity);
127
+ // textureLRUCache = TextureLRUCache(maxMSDFs);
128
+
121
129
asset::E_FORMAT msdfFormat = asset::EF_R8G8B8A8_UNORM; // @Lucas change the format to what MSDFs use
122
130
constexpr asset::VkExtent3D MSDFsExtent = { 32u , 32u , 1u }; // 32x32 images, TODO: maybe make this a paramerter
123
131
assert (maxMSDFs <= logicalDevice->getPhysicalDevice ()->getLimits ().maxImageArrayLayers );
@@ -221,7 +229,7 @@ void DrawResourcesFiller::drawHatch(
221
229
const Hatch& hatch,
222
230
const float32_t4& foregroundColor,
223
231
const float32_t4& backgroundColor,
224
- const uint32_t msdfTextureIdx ,
232
+ const texture_hash msdfTexture ,
225
233
SIntendedSubmitInfo& intendedNextSubmit)
226
234
{
227
235
// TODO[Optimization Idea]: don't draw hatch twice if both colors are visible: instead do the msdf inside the alpha resolve by detecting mainObj being a hatch
@@ -237,12 +245,23 @@ void DrawResourcesFiller::drawHatch(
237
245
void DrawResourcesFiller::drawHatch (
238
246
const Hatch& hatch,
239
247
const float32_t4& color,
240
- const uint32_t msdfTextureIdx ,
248
+ const texture_hash msdfTexture ,
241
249
SIntendedSubmitInfo& intendedNextSubmit)
242
250
{
251
+ uint32_t textureIdx = InvalidTextureIdx;
252
+ if (msdfTexture != InvalidTextureHash)
253
+ {
254
+ TextureReference* tRef = textureLRUCache.get (msdfTexture);
255
+ if (tRef)
256
+ {
257
+ textureIdx = tRef->alloc_idx ;
258
+ tRef->lastUsedSemaphoreValue = intendedNextSubmit.getScratchSemaphoreNextWait ().value ; // update this because the texture will get used on the next submit
259
+ }
260
+ }
261
+
243
262
LineStyleInfo lineStyle = {};
244
263
lineStyle.color = color;
245
- lineStyle.screenSpaceLineWidth = nbl::hlsl::bit_cast<float , uint32_t >(msdfTextureIdx );
264
+ lineStyle.screenSpaceLineWidth = nbl::hlsl::bit_cast<float , uint32_t >(textureIdx );
246
265
// @Lucas we use LineStyle struct for hatches too but we aliased a member with textureId, So you need to do asuint(lineStyle.screenSpaceLineWidth) to get you the index into msdfTextureArray
247
266
248
267
const uint32_t styleIdx = addLineStyle_SubmitIfNeeded (lineStyle, intendedNextSubmit);
@@ -264,38 +283,50 @@ void DrawResourcesFiller::drawHatch(
264
283
265
284
void DrawResourcesFiller::drawHatch (const Hatch& hatch, const float32_t4& color, SIntendedSubmitInfo& intendedNextSubmit)
266
285
{
267
- drawHatch (hatch, color, InvalidTextureIdx , intendedNextSubmit);
286
+ drawHatch (hatch, color, InvalidTextureHash , intendedNextSubmit);
268
287
}
269
288
270
- uint32_t DrawResourcesFiller::addMSDFTexture (ICPUBuffer const * srcBuffer, const asset::IImage::SBufferCopy& region, texture_hash hash)
289
+ void DrawResourcesFiller::addMSDFTexture (ICPUBuffer const * srcBuffer, const asset::IImage::SBufferCopy& region, texture_hash hash, SIntendedSubmitInfo& intendedNextSubmit )
271
290
{
272
- uint32_t ret = InvalidTextureIdx;
291
+ // TextureReferences hold the semaValue related to the "scratch semaphore" in IntendedSubmitInfo
292
+ // Every single submit increases this value by 1
293
+ // The reason for hiolding on to the lastUsedSema is deferred dealloc, which we call in the case of eviction, making sure we get rid of the entry inside the allocator only when the texture is done being used
294
+ uint64_t nextSemaValue = intendedNextSubmit.getScratchSemaphoreNextWait ().value ;
295
+ const auto * signalSema = intendedNextSubmit.getScratchSemaphoreNextWait ().semaphore ;
273
296
274
- // @Lucas TODO: Here should rely the main logic for allocating an index from our allocator and evicting based on LRU Cache if we failed
275
- /*
276
- * look into `textureIdToIndexMap` if we already have the `texture_hash` in the texture array slices (skip if hash is InvalidTextureHash)
277
- * If we found a match we return that index;
278
- * Else:
279
- * LRUIndexAllocator try allocate
280
- * Failure to Alloc Index (Auto-Submission logic):
281
- 1. evict something from LRU cache + remove entry from lookup unordered_map ->
282
- 2. dealloc with deferred (based on next submit signal val) ->
283
- 3. resetGeometryCounters(); (because geometries using previous glyphs are done rendering and should be invalidated)
284
- 4. ret = try alloc again (+ assert it should succeed because we evicted and dealloced)
285
- * Success to Alloc Index: ret = index; add entry to lookup unordered_map
286
- */
287
-
288
- // asuming allocator gave us 0 as index
289
- ret = 0u ;
290
-
291
- // We queue copy and finalize all on `finalizeTextureCopies` function called before draw calls to make sure it's in mem
292
- textureCopies.push_back ({
293
- .srcBuffer = srcBuffer,
294
- .region = region,
295
- .index = ret,
296
- });
297
+ auto evictionCallback = [&](const TextureReference& evicted)
298
+ {
299
+ // @Lucas TODO:
300
+
301
+ // Dealloc:
302
+ // allocator.multi_deallocate(1u,&evicted.alloc_idx,{signalSema,evicted.lastUsedSemaphoreValue});
303
+
304
+ // Overflow Handling:
305
+ // finalizeAllCopiesToGPU(intendedNextSubmit);
306
+ // submitDraws(intendedNextSubmit);
307
+ // resetGeometryCounters();
308
+ // resetMainObjectCounters();
309
+ };
310
+
311
+ // We pass nextSemaValue instead of constructing a new TextureReference and passing it into `insert` that's because we might get a cache hit and only update the value of the nextSema
312
+ TextureReference* inserted = textureLRUCache.insert (hash, nextSemaValue, evictionCallback);
313
+
314
+ // if inserted->alloc_idx was not InvalidTextureIdx then it means we had a cache hit and updated the value of our sema, in which case we don't queue anything for upload, and return the idx
315
+ if (inserted->alloc_idx == InvalidTextureIdx)
316
+ {
317
+ // New insertion == cache miss happened and insertion was successfull
318
+ // allocator.multi_allocate(1u,&inserted->alloc_idx);
319
+ inserted->alloc_idx = 0u ; // temp
320
+
321
+ // We queue copy and finalize all on `finalizeTextureCopies` function called before draw calls to make sure it's in mem
322
+ textureCopies.push_back ({
323
+ .srcBuffer = srcBuffer,
324
+ .region = region,
325
+ .index = inserted->alloc_idx ,
326
+ });
327
+ }
297
328
298
- return ret ;
329
+ assert (inserted-> alloc_idx != InvalidTextureIdx) ;
299
330
}
300
331
301
332
void DrawResourcesFiller::finalizeAllCopiesToGPU (SIntendedSubmitInfo& intendedNextSubmit)
0 commit comments