56 enum class Arena : uint8_t
85 static constexpr uint32_t kInvalidIndex = 0xFFFFFFFFu;
87 Arena arena{Arena::RawCamera};
88 uint32_t slot_index{kInvalidIndex};
90 uint32_t generation{};
92 bool valid()
const noexcept {
return slot_index != kInvalidIndex; }
114 void init(QRhi& rhi, QRhiResourceUpdateBatch& batch);
144 void seedDefaults(QRhiResourceUpdateBatch& batch);
185 Slot allocate(Arena arena, uint32_t size);
190 void free(Slot& slot);
198 QRhiBuffer* buffer(Arena arena)
const noexcept;
203 uint32_t slotOffset(
const Slot& slot)
const noexcept;
210 uint32_t arenaSlotStride(Arena arena)
const noexcept;
215 uint32_t arenaSlotCount(Arena arena)
const noexcept;
226 QRhiResourceUpdateBatch& res,
const Slot& slot,
const void* data,
227 uint32_t size)
noexcept;
241 ossia::gpu_slot_ref r;
242 r.arena = (uint32_t)slot.arena;
243 r.offset = slotOffset(slot);
245 r.internal_index = slot.slot_index;
246 r.generation = slot.generation;
264 bool isLiveIn(
const ossia::gpu_slot_ref& r, Arena expected)
const noexcept
266 return r.arena == (uint32_t)expected && isLive(r);
276 bool isLive(
const ossia::gpu_slot_ref& r)
const noexcept
278 if(r.arena >= (uint32_t)Arena::Count_ || r.size == 0)
280 const auto& a = m_arenas[r.arena];
281 if(r.internal_index >= a.slot_generations.size())
283 return a.slot_generations[r.internal_index] == r.generation;
297 enum class TextureChannel : uint8_t
310 static constexpr int kTextureLayerSize = 1024;
315 static constexpr int kMaxDynamicSlots = 4;
331 static constexpr int kMaxBuckets = 16;
350 QRhiTexture* array{};
351 QRhiTexture::Format format{QRhiTexture::RGBA8};
359 ossia::texture_sampler_config sampler_config{};
360 QRhiSampler* sampler{};
365 ossia::flat_map<const ossia::texture_source*, int> layerMap;
370 std::vector<Bucket> buckets;
380 ossia::flat_map<quint64, int> dynamicSlotMap;
381 std::vector<QRhiTexture*> dynamicTextures;
382 std::vector<uint64_t> dynamicSlotLastUse;
383 uint64_t dynamicSlotCounter{0};
388 uint64_t dynamicSweepCheckpoint{0};
392 QRhiTexture* primaryArray() const noexcept
394 return buckets.empty() ? nullptr : buckets[0].array;
396 int primaryLayers() const noexcept
398 return buckets.empty() ? 0 : buckets[0].layers;
405 Bucket& ensurePrimary(QRhiTexture::Format fmt, QSize sz)
408 buckets.emplace_back();
409 auto& b = buckets[0];
419 std::pair<int, Bucket*>
420 findOrCreateBucket(QRhiTexture::Format fmt, QSize sz)
422 for(std::size_t i = 0; i < buckets.size(); ++i)
424 if(buckets[i].format == fmt && buckets[i].pixelSize == sz)
425 return {(int)i, &buckets[i]};
427 if((
int)buckets.size() >= kMaxBuckets)
428 return {-1,
nullptr};
429 buckets.emplace_back();
430 auto& b = buckets.back();
433 return {(int)buckets.size() - 1, &b};
440 std::pair<int, Bucket*>
442 QRhiTexture::Format fmt, QSize sz,
443 const ossia::texture_sampler_config& sampler_cfg)
445 for(std::size_t i = 0; i < buckets.size(); ++i)
447 if(buckets[i].format == fmt && buckets[i].pixelSize == sz
448 && buckets[i].sampler_config == sampler_cfg)
449 return {(int)i, &buckets[i]};
451 if((
int)buckets.size() >= kMaxBuckets)
452 return {-1,
nullptr};
453 buckets.emplace_back();
454 auto& b = buckets.back();
457 b.sampler_config = sampler_cfg;
458 return {(int)buckets.size() - 1, &b};
470 return m_textureChannels[(std::size_t)ch];
472 const TextureChannelState& textureChannel(TextureChannel ch)
const noexcept
474 return m_textureChannels[(std::size_t)ch];
482 static const char* textureChannelArrayName(TextureChannel ch)
noexcept;
490 static const char* textureChannelDynBaseName(TextureChannel ch)
noexcept;
497 static QRhiTexture::Flags textureChannelFlags(TextureChannel ch)
noexcept;
511 int resolveDynamicSlot(TextureChannel channel,
void* native_handle)
noexcept;
541 enum class MeshStream : uint8_t
557 static constexpr uint32_t kMeshStride[(std::size_t)MeshStream::Count_]
558 = {16, 16, 8, 16, 16, 8, 4};
564 static constexpr uint32_t kMeshCapBytes[(std::size_t)MeshStream::Count_]
566 128u * 1024u * 1024u,
567 128u * 1024u * 1024u,
569 128u * 1024u * 1024u,
570 128u * 1024u * 1024u,
592 uint64_t stable_id{};
593 OffsetAllocator::Allocation vertex_slot{};
594 OffsetAllocator::Allocation index_slot{};
595 uint32_t vertex_count{};
596 uint32_t index_count{};
597 uint32_t last_seen_frame{};
598 bool freshly_allocated{};
611 uint32_t vertex_count,
612 uint32_t index_count,
613 uint32_t current_frame)
noexcept;
616 void markMeshSlabSeen(uint64_t stable_id, uint32_t current_frame)
noexcept;
620 void sweepMeshSlabs(uint32_t current_frame, uint32_t grace = 2) noexcept;
628 void sweepStaleDynamicTextureSlots() noexcept;
635 void drainExpiredPendingReleases(
636 uint32_t current_frame, uint32_t grace = 2) noexcept;
643 void releaseMeshSlab(uint64_t stable_id, uint32_t current_frame) noexcept;
647 uint32_t meshSlabOffsetBytes(
648 const
MeshSlab& slab, MeshStream stream) const noexcept;
652 QRhiBuffer* meshStreamBuffer(MeshStream s) const noexcept;
657 void uploadMeshStream(
658 QRhiResourceUpdateBatch& res, const
MeshSlab& slab,
659 MeshStream s, const
void* data, uint32_t size) noexcept;
662 uint32_t meshStreamUsedBytes(MeshStream s) const noexcept;
663 uint32_t meshStreamFreeBytes(MeshStream s) const noexcept;
668 QRhiBuffer* buffer{};
669 uint32_t slot_stride{0};
671 uint32_t slot_count{0};
672 QRhiBuffer::UsageFlags usage{};
673 QRhiBuffer::Type type{QRhiBuffer::Dynamic};
677 std::vector<uint32_t> free_slots;
683 std::vector<uint32_t> slot_generations;
686 std::array<ArenaState, (std::size_t)Arena::Count_> m_arenas{};
688 std::array<TextureChannelState, (std::size_t)TextureChannel::Count_>
695 struct MeshStreamState
697 QRhiBuffer* buffer{};
698 uint32_t capacity_bytes{};
699 QRhiBuffer::UsageFlags usage{};
701 std::array<MeshStreamState, (std::size_t)MeshStream::Count_> m_meshStreams{};
707 std::unique_ptr<OffsetAllocator::Allocator> m_vertexAllocator;
708 std::unique_ptr<OffsetAllocator::Allocator> m_indexAllocator;
709 uint32_t m_vertexSlotsCapacity{};
710 uint32_t m_indexSlotsCapacity{};
711 uint32_t m_vertexSlotsUsed{};
712 uint32_t m_indexSlotsUsed{};
714 ossia::hash_map<uint64_t, MeshSlab> m_meshSlabs;
720 struct PendingRelease
722 uint64_t stable_id{};
723 uint32_t released_frame{};
724 OffsetAllocator::Allocation vertex_slot{};
725 OffsetAllocator::Allocation index_slot{};
727 std::vector<PendingRelease> m_pendingReleases;
734 bool m_defaults_seeded{
false};
Channel texture state with multi-bucket support.
Definition GpuResourceRegistry.hpp:347