standalone: VoxelForgeCore library -- the fast generator behind a clean C++20 API, output unchanged
- Standalone/Core: public header VoxelForgeCore.h (no Unreal types), static library target, ResolvedWorldSnapshot (from the schema-v1 JSON), World (compile, generateTile, density/sign, point/segment solid, classifyBox), host-supplied JobScheduler (the core starts no threads), sequenced, idempotent EditTransaction returning affected tiles per LOD. - The viewer, benchmarks, edits and audits run on Core; StreamingWorld stays host code. - Same as round 11: 11 hash rows at W1 and W8, routes 5642/5642, look/passage/far audits pass, bad-shell control fails, six fixed captures byte-identical; cold W8 1.025 s vs 1.041 s reference. - SHARED_CPP_LIBRARY_PLAN.md rewritten for a UBT module compiling the same sources via shims. Open issue before Unreal: Core's implementation still compiles the Compat stand-ins named like Unreal types (TArray, FVector...); inside a UE binary that is an ODR clash. Must be namespaced. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
631dd57eb4
commit
557f6aac30
22 files changed
+6185
-5063
No files matched your search
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "VoxelForgeCore/VoxelForgeCore.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
// This executor belongs to the standalone host. VoxelForgeCore submits indexed work but never
|
||||
// creates or owns worker threads.
|
||||
class FStandaloneCoreScheduler final : public VoxelForgeCore::JobScheduler
|
||||
{
|
||||
public:
|
||||
double parallel_for(std::size_t count,std::size_t batchSize,std::size_t workerLimit,
|
||||
void* context,Task task,double* workerActiveSeconds,
|
||||
std::size_t workerActiveCapacity) const override
|
||||
{
|
||||
if(count==0)return 0.0;
|
||||
const std::size_t workers=std::clamp<std::size_t>(workerLimit,1,
|
||||
std::min<std::size_t>(8,std::max<std::size_t>(1,count)));
|
||||
const std::size_t grain=std::max<std::size_t>(1,batchSize);
|
||||
std::atomic<std::size_t> next{0};
|
||||
std::vector<double> active(workers,0.0);
|
||||
std::vector<std::thread> threads;
|
||||
threads.reserve(workers);
|
||||
for(std::size_t worker=0;worker<workers;++worker)
|
||||
threads.emplace_back([&,worker]
|
||||
{
|
||||
const auto started=std::chrono::steady_clock::now();
|
||||
for(;;)
|
||||
{
|
||||
const std::size_t first=next.fetch_add(grain,std::memory_order_relaxed);
|
||||
if(first>=count)break;
|
||||
const std::size_t end=first+std::min(grain,count-first);
|
||||
for(std::size_t index=first;index<end;++index)task(context,index,worker);
|
||||
}
|
||||
active[worker]=std::chrono::duration<double>(
|
||||
std::chrono::steady_clock::now()-started).count();
|
||||
});
|
||||
for(std::thread& thread:threads)thread.join();
|
||||
double total=0.0;
|
||||
for(std::size_t worker=0;worker<workers;++worker)
|
||||
{
|
||||
total+=active[worker];
|
||||
if(workerActiveSeconds&&worker<workerActiveCapacity)
|
||||
workerActiveSeconds[worker]=active[worker];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
};
|
||||
Reference in new issue
Block a user