7using namespace Tempest;
10 scratch.header.reserve(1024);
11 scratch.patch .reserve(1024);
18 if(commandId==uint16_t(-1))
21 const auto ret = implAlloc(meshletCount);
22 for(
size_t i=0; i<meshletCount; ++i) {
35 clustersDurty.resize((clusters.size() + 32 - 1)/32);
40uint32_t
DrawClusters::alloc(
const Bucket& bucket,
size_t firstMeshlet,
size_t meshletCount, uint16_t bucketId, uint16_t commandId) {
41 const auto ret = implAlloc(1);
53 clustersDurty.resize((clusters.size() + 32 - 1)/32);
59 for(
size_t i=0; i<numCluster; ++i) {
61 clusters[
id + i].r = -1;
62 clusters[
id + i].meshletCount = 0;
66 Range r = {id,
id+numCluster};
67 auto at = std::lower_bound(freeList.begin(),freeList.end(),r,[](
const Range& l,
const Range& r){
68 return l.begin<r.begin;
70 at = freeList.insert(at,r);
72 if(next!=freeList.end() && at->end==next->begin) {
73 next->begin = at->begin;
74 at = freeList.erase(at);
76 if(at!=freeList.begin() && at->begin==(at-1)->end) {
79 at = freeList.erase(at);
86 clustersDurtyBit =
false;
88 std::atomic_thread_fence(std::memory_order_acquire);
89 size_t csize = clusters.size()*
sizeof(clusters[0]);
90 csize = (csize + 0xFFF) &
size_t(~0xFFF);
93 if(clustersGpu.byteSize() == csize) {
94 patchClusters(cmd, fId);
99 clustersGpu = device.ssbo(Tempest::Uninitialized, csize);
100 clustersGpu.update(clusters);
101 std::fill(clustersDurty.begin(), clustersDurty.end(), 0x0);
105size_t DrawClusters::implAlloc(
size_t count) {
106 size_t bestFit = size_t(-1), bfDiff = size_t(-1);
107 for(
size_t i=0; i<freeList.size(); ++i) {
108 auto f = freeList[i];
109 auto sz = (f.end - f.begin);
111 freeList.erase(freeList.begin()+int(i));
116 if(sz-count < bfDiff)
120 if(bestFit !=
size_t(-1)) {
121 auto& f = freeList[bestFit];
126 size_t ret = clusters.size();
127 clusters.resize(clusters.size() + count);
131void DrawClusters::patchClusters(Encoder<CommandBuffer>& cmd, uint8_t fId) {
132 std::vector<uint32_t>& header = scratch.header;
133 std::vector<Cluster>& patch = scratch.patch;
138 for(
size_t i=0; i<clustersDurty.size(); ++i) {
139 if(clustersDurty[i]==0x0)
141 const uint32_t mask = clustersDurty[i];
142 clustersDurty[i] = 0x0;
144 for(
size_t r=0; r<32; ++r) {
145 if((mask & (1u<<r))==0)
147 size_t idx = i*32 + r;
148 if(idx>=clusters.size())
150 patch.push_back(clusters[idx]);
151 header.push_back(uint32_t(idx));
159 auto& p = this->patch[fId];
161 if(header.size()*
sizeof(header[0]) < p.indices.byteSize()) {
162 p.indices.update(header);
164 p.indices = device.ssbo(BufferHeap::Upload, header);
167 if(patch.size()*
sizeof(patch[0]) < p.data.byteSize()) {
168 p.data.update(patch);
170 p.data = device.ssbo(BufferHeap::Upload, patch);
173 const uint32_t count = uint32_t(header.size());
174 cmd.setFramebuffer({});
175 cmd.setBinding(0, clustersGpu);
176 cmd.setBinding(1, p.data);
177 cmd.setBinding(2, p.indices);
178 cmd.setPushData(count);
180 cmd.dispatchThreads(count);
184 for(
size_t i=0; i<count; ++i) {
185 static_assert(
sizeof(std::atomic<uint32_t>)==
sizeof(uint32_t));
186 auto& bits = clustersDurty[
id/32];
187 reinterpret_cast<std::atomic<uint32_t>&
>(bits).fetch_or(1u << (
id%32), std::memory_order_relaxed);
190 clustersDurtyBit.store(
true);
bool commit(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t fId)
uint32_t alloc(const PackedMesh::Cluster *cluster, size_t firstMeshlet, size_t meshletCount, uint16_t bucketId, uint16_t commandId)
void free(uint32_t id, uint32_t numCluster)
void markClusters(size_t id, size_t count=1)
static Tempest::Device & device()
static void recycle(Tempest::DescriptorArray &&arr)
const StaticMesh * staticMesh
const AnimMesh * animMesh