Created
May 10, 2025 15:55
-
-
Save pollend/6b8ac571b90377035fe297a769700a0c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "graphics/RIDescriptorSetAllocator.h" | |
#include "system/stb_ds.h" | |
#include <cassert> | |
struct RIDescriptorSetSlot *AllocDescriptorsetSlot( struct RIDescriptorSetAlloc *alloc ) | |
{ | |
if( alloc->blocks == NULL || alloc->blockIndex == RESERVE_BLOCK_SIZE ) { | |
struct RIDescriptorSetSlot *block = (struct RIDescriptorSetSlot*)calloc( RESERVE_BLOCK_SIZE, sizeof( struct RIDescriptorSetSlot ) ); | |
alloc->blockIndex = 0; | |
arrpush( alloc->blocks, block ); | |
return block + ( alloc->blockIndex++ ); | |
} | |
return alloc->blocks[arrlen( alloc->blocks ) - 1] + ( alloc->blockIndex++ ); | |
} | |
void AttachDescriptorSlot( struct RIDescriptorSetAlloc *alloc, struct RIDescriptorSetSlot *slot ) | |
{ | |
assert( slot ); | |
{ | |
slot->quNext = NULL; | |
slot->quPrev = alloc->queueEnd; | |
if( alloc->queueEnd ) { | |
alloc->queueEnd->quNext = slot; | |
} | |
alloc->queueEnd = slot; | |
if( !alloc->queueBegin ) { | |
alloc->queueBegin = slot; | |
} | |
} | |
{ | |
const size_t hashIndex = slot->hash % ALLOC_HASH_RESERVE; | |
slot->hPrev = NULL; | |
slot->hNext = NULL; | |
if( alloc->hashSlots[hashIndex] ) { | |
alloc->hashSlots[hashIndex]->hPrev = slot; | |
slot->hNext = alloc->hashSlots[hashIndex]; | |
} | |
alloc->hashSlots[hashIndex] = slot; | |
} | |
} | |
void DetachDescriptorSlot( struct RIDescriptorSetAlloc *alloc, struct RIDescriptorSetSlot *slot ) | |
{ | |
assert( slot ); | |
// remove from queue | |
{ | |
if( alloc->queueBegin == slot ) { | |
alloc->queueBegin = slot->quNext; | |
if( slot->quNext ) { | |
slot->quNext->quPrev = NULL; | |
} | |
} else if( alloc->queueEnd == slot ) { | |
alloc->queueEnd = slot->quPrev; | |
if( slot->quPrev ) { | |
slot->quPrev->quNext = NULL; | |
} | |
} else { | |
if( slot->quPrev ) { | |
slot->quPrev->quNext = slot->quNext; | |
} | |
if( slot->quNext ) { | |
slot->quNext->quPrev = slot->quPrev; | |
} | |
} | |
} | |
// free from hashTable | |
{ | |
const size_t hashIndex = slot->hash % ALLOC_HASH_RESERVE; | |
if( alloc->hashSlots[hashIndex] == slot ) { | |
alloc->hashSlots[hashIndex] = slot->hNext; | |
if( slot->hNext ) { | |
slot->hPrev = NULL; | |
} | |
} else { | |
if( slot->hPrev ) { | |
slot->hPrev->hNext = slot->hNext; | |
} | |
if( slot->hNext ) { | |
slot->hNext->hPrev = slot->hPrev; | |
} | |
} | |
} | |
} | |
struct RIDescriptorSetResult ResolveDescriptorSet( struct RIDevice_s *device, struct RIDescriptorSetAlloc *alloc, uint32_t frameCount, uint32_t hash ) | |
{ | |
struct RIDescriptorSetResult result = { 0 }; | |
const size_t hashIndex = hash % ALLOC_HASH_RESERVE; | |
for( struct RIDescriptorSetSlot *c = alloc->hashSlots[hashIndex]; c; c = c->hNext ) { | |
if( c->hash == hash ) { | |
if( alloc->queueEnd == c ) { | |
// already at the end of the queue | |
} else if (alloc->queueBegin == c) { | |
alloc->queueBegin = c->quNext; | |
if( c->quNext ) { | |
c->quNext->quPrev = NULL; | |
} | |
} else { | |
if( c->quPrev ) { | |
c->quPrev->quNext = c->quNext; | |
} | |
if( c->quNext ) { | |
c->quNext->quPrev = c->quPrev; | |
} | |
} | |
c->quNext = NULL; | |
c->quPrev = alloc->queueEnd; | |
if( alloc->queueEnd ) { | |
alloc->queueEnd->quNext = c; | |
} | |
alloc->queueEnd = c; | |
c->frameCount = frameCount; | |
result.set = c; | |
result.found = true; | |
assert(result.set); | |
return result; | |
} | |
} | |
if( alloc->queueBegin && frameCount > alloc->queueBegin->frameCount + alloc->framesInFlight) { | |
struct RIDescriptorSetSlot *slot = alloc->queueBegin; | |
DetachDescriptorSlot( alloc, slot ); | |
slot->frameCount = frameCount; | |
slot->hash = hash; | |
AttachDescriptorSlot( alloc, slot ); | |
result.set = slot; | |
result.found = false; | |
assert(result.set); | |
return result; | |
} | |
if( arrlen( alloc->reservedSlots ) == 0 ) { | |
alloc->descriptorAllocator(device, alloc); | |
assert(arrlen(alloc->reservedSlots) > 0); // we didn't reserve any slots ... | |
} | |
struct RIDescriptorSetSlot *slot = arrpop( alloc->reservedSlots ); | |
slot->hash = hash; | |
slot->frameCount = frameCount; | |
AttachDescriptorSlot( alloc, slot ); | |
result.set = slot; | |
result.found = false; | |
assert(result.set); | |
return result; | |
} | |
void FreeDescriptorSetAlloc( struct RIDevice_s *device, struct RIDescriptorSetAlloc *alloc ) | |
{ | |
#if ( DEVICE_IMPL_VULKAN ) | |
for( size_t i = 0; i < arrlen( alloc->blocks ); i++ ) { | |
// TODO: do i need to free indivudal descriptor sets or can i just free the entire pool | |
// for(size_t blockIdx = 0; blockIdx < RESERVE_BLOCK_SIZE; blockIdx++) { | |
// vkFreeDescriptorSets(device->vk.device, alloc->blocks[i]->vk.pool, ) | |
//} | |
free( alloc->blocks[i] ); | |
} | |
arrfree( alloc->blocks ); | |
for( size_t i = 0; i < arrlen( alloc->pools ); i++ ) { | |
vkDestroyDescriptorPool( device->vk.device, alloc->pools[i].vk.handle, NULL ); | |
} | |
arrfree( alloc->pools ); | |
#endif | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef R_DESCRIPTOR_POOL_H | |
#define R_DESCRIPTOR_POOL_H | |
#include <cstddef> | |
#include <stdint.h> | |
#include "graphics/RITypes.h" | |
#define RESERVE_BLOCK_SIZE 1024 | |
#define ALLOC_HASH_RESERVE 256 | |
#define DESCRIPTOR_MAX_SIZE 64 | |
#define DESCRIPTOR_RESERVED_SIZE 64 | |
struct RIDescriptorSetSlot { | |
uint32_t hash; | |
uint32_t frameCount; | |
// queue | |
struct RIDescriptorSetSlot *quNext; | |
struct RIDescriptorSetSlot *quPrev; | |
// hash | |
struct RIDescriptorSetSlot *hNext; | |
struct RIDescriptorSetSlot *hPrev; | |
union { | |
#if ( DEVICE_IMPL_VULKAN ) | |
struct { | |
VkDescriptorPool pool; | |
VkDescriptorSet handle; | |
} vk; | |
#endif | |
}; | |
}; | |
struct RIDescriptorPoolAllocSlot { | |
union { | |
#if ( DEVICE_IMPL_VULKAN ) | |
struct { | |
VkDescriptorPool handle; | |
} vk; | |
#endif | |
}; | |
}; | |
struct RIDescriptorSetAlloc; | |
typedef void ( *RIDescriptorSetAlloc_Create )( struct RIDevice_s *device, struct RIDescriptorSetAlloc *alloc ); | |
struct RIDescriptorSetAlloc { | |
RIDescriptorSetAlloc_Create descriptorAllocator; | |
uint8_t framesInFlight; // the number of frames in flight | |
struct RIDescriptorSetSlot *hashSlots[ALLOC_HASH_RESERVE]; | |
struct RIDescriptorSetSlot *queueBegin; | |
struct RIDescriptorSetSlot *queueEnd; | |
struct RIDescriptorSetSlot **reservedSlots; // stb arrays | |
struct RIDescriptorPoolAllocSlot* pools; // stb arrays | |
struct RIDescriptorSetSlot **blocks; | |
size_t blockIndex; | |
}; | |
struct RIDescriptorSetResult { | |
bool found; | |
struct RIDescriptorSetSlot *set; // the associated slot | |
}; | |
struct RIDescriptorSetResult ResolveDescriptorSet( struct RIDevice_s *device, | |
struct RIDescriptorSetAlloc *alloc, | |
uint32_t frameCount, | |
uint32_t hash ); | |
void FreeDescriptorSetAlloc( struct RIDevice_s *device, struct RIDescriptorSetAlloc *alloc ); | |
// utility | |
struct RIDescriptorSetSlot *AllocDescriptorsetSlot( struct RIDescriptorSetAlloc *alloc ); | |
void AttachDescriptorSlot( struct RIDescriptorSetAlloc *alloc, struct RIDescriptorSetSlot *slot ); | |
void DetachDescriptorSlot( struct RIDescriptorSetAlloc *alloc, struct RIDescriptorSetSlot *slot ); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment