Program Listing for File AsyncModelParse.ixx#
↰ Return to documentation for file (Src/GraphicsEngineVulkan/scene/AsyncModelParse.ixx)
module;
#include <atomic>
#include <memory>
#include <string>
#include <thread>
export module kataglyphis.vulkan.async_model_parse;
import kataglyphis.vulkan.gltf_loader;
import kataglyphis.vulkan.obj_loader;
import kataglyphis.vulkan.model_file_kind;
export namespace Kataglyphis {
class AsyncModelParse
{
public:
AsyncModelParse() = default;
AsyncModelParse(const AsyncModelParse &) = delete;
AsyncModelParse &operator=(const AsyncModelParse &) = delete;
~AsyncModelParse() { waitForCompletion(); }
void start(const std::string &modelFile)
{
waitForCompletion();
finished.store(false, std::memory_order_release);
succeeded.store(false, std::memory_order_release);
loader.reset();
gltfLoader.reset();
path = modelFile;
// Dispatch by extension. The OBJ path is unchanged; glTF gets a parallel
// one so both load off the render thread.
if (isGltfModelPath(modelFile)) {
gltfLoader = std::make_unique<GltfLoader>();// device-free
worker = std::thread([this] {
const bool ok = gltfLoader->parseCpu(path);
succeeded.store(ok, std::memory_order_release);
finished.store(true, std::memory_order_release);
});
} else {
loader = std::make_unique<ObjLoader>();// device-free
worker = std::thread([this] {
const bool ok = loader->parseCpu(path);
succeeded.store(ok, std::memory_order_release);
// Release LAST: a reader that sees finished == true must also see
// every write the parse made, including `succeeded`.
finished.store(true, std::memory_order_release);
});
}
}
[[nodiscard]] bool isRunning() const { return worker.joinable() && !isFinished(); }
[[nodiscard]] bool isFinished() const { return finished.load(std::memory_order_acquire); }
[[nodiscard]] bool wasSuccessful() const { return succeeded.load(std::memory_order_acquire); }
std::unique_ptr<ObjLoader> takeResult()
{
waitForCompletion();
if (!succeeded.load(std::memory_order_acquire)) {
loader.reset();
return nullptr;
}
return std::move(loader);
}
[[nodiscard]] bool parsedGltf() const { return gltfLoader != nullptr; }
std::unique_ptr<GltfLoader> takeGltfResult()
{
waitForCompletion();
if (!succeeded.load(std::memory_order_acquire)) {
gltfLoader.reset();
return nullptr;
}
return std::move(gltfLoader);
}
void waitForCompletion()
{
if (worker.joinable()) { worker.join(); }
}
private:
std::thread worker;
std::atomic<bool> finished{ false };
std::atomic<bool> succeeded{ false };
std::unique_ptr<ObjLoader> loader;
std::unique_ptr<GltfLoader> gltfLoader;
std::string path;
};
}// namespace Kataglyphis