From e68a60fb2683afb79b92884caac09fe870c456ba Mon Sep 17 00:00:00 2001 From: Romain BOULLARD Date: Sun, 30 Aug 2026 00:54:53 +0200 Subject: [PATCH] Preparing SerializationManager --- .../Engine/Asset/AssetContainer.cpp | 97 ++-- Bigfoot/Benchmarks/Engine/Asset/Reference.cpp | 167 ++++-- Bigfoot/Benchmarks/Engine/BigFile/BigFile.cpp | 76 +-- .../Benchmarks/Engine/Sasquatch/Sasquatch.cpp | 9 +- .../Tools/SasquatchBaker/SasquatchBaker.cpp | 13 +- Bigfoot/Sources/Engine/Asset/AssetLibrary.cpp | 54 ++ Bigfoot/Sources/Engine/BigFile/BigFile.cpp | 326 +++++------ .../Sources/Engine/BigFile/BigFileSchema.sql | 11 - .../Engine/Include/Engine/Asset/Asset.hpp | 72 ++- .../Include/Engine/Asset/AssetContainer.hpp | 109 ++-- .../Include/Engine/Asset/AssetLibrary.hpp | 36 +- .../Engine/Include/Engine/BigFile/BigFile.hpp | 65 ++- .../Engine/DataAccessor/DataAccessor.hpp | 48 +- .../Include/Engine/Sasquatch/Sasquatch.hpp | 20 +- .../Sources/Engine/Sasquatch/Sasquatch.cpp | 20 +- Bigfoot/Tests/Engine/Asset/Asset.cpp | 2 +- Bigfoot/Tests/Engine/Asset/AssetContainer.cpp | 63 +-- Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp | 26 + Bigfoot/Tests/Engine/Asset/Reference.cpp | 489 ++++++----------- Bigfoot/Tests/Engine/BigFile/BigFile.cpp | 512 ++++++++---------- .../Engine/DataAccessor/DataAccessor.cpp | 36 +- .../Include/EngineTests/DataAccessorMock.hpp | 44 ++ Bigfoot/Tests/Engine/Sasquatch/Sasquatch.cpp | 70 +-- .../Tools/SasquatchBaker/SasquatchBaker.cpp | 34 +- 24 files changed, 1097 insertions(+), 1302 deletions(-) create mode 100644 Bigfoot/Tests/Engine/Include/EngineTests/DataAccessorMock.hpp diff --git a/Bigfoot/Benchmarks/Engine/Asset/AssetContainer.cpp b/Bigfoot/Benchmarks/Engine/Asset/AssetContainer.cpp index 7cac9e6..1e7bfae 100644 --- a/Bigfoot/Benchmarks/Engine/Asset/AssetContainer.cpp +++ b/Bigfoot/Benchmarks/Engine/Asset/AssetContainer.cpp @@ -20,9 +20,30 @@ namespace using Random = effolkronium::random_static; } // namespace +class AssetContainerFixture: public benchmark::Fixture +{ + protected: + [[nodiscard]] + static eastl::vector InsertRandomAssets(AssetContainer& p_container, + const std::uint32_t p_count) + { + eastl::vector uuids; + uuids.reserve(p_count); + for (std::uint32_t i = 0; i < p_count; ++i) + { + uuids.push_back(p_container.Insert()->GetAsset()->GetHeader().uuid); + } + Random::shuffle(uuids); + + return uuids; + } + + AssetContainer m_container; +}; + /****************************************************************************************/ -void Insert(benchmark::State& state) +BENCHMARK_DEFINE_F(AssetContainerFixture, Insert)(benchmark::State& state) { const auto count = static_cast(state.range(0)); @@ -41,29 +62,29 @@ void Insert(benchmark::State& state) state.SetBytesProcessed(static_cast(state.iterations() * count * sizeof(BenchmarkAsset))); } -BENCHMARK(Insert)->Name("AssetContainer/Insert")->Arg(512)->Arg(8192)->Arg(131'072); +BENCHMARK_REGISTER_F(AssetContainerFixture, Insert)->Name("AssetContainer/Insert")->Arg(512)->Arg(8192)->Arg(131'072); /****************************************************************************************/ -void Get(benchmark::State& state) +BENCHMARK_DEFINE_F(AssetContainerFixture, Get)(benchmark::State& state) { const auto count = static_cast(state.range(0)); - AssetContainer container; - eastl::vector> keys; - keys.reserve(count); - for (std::uint32_t i = 0; i < count; ++i) + const eastl::vector uuids = InsertRandomAssets(m_container, count); + + eastl::vector handles; + handles.reserve(count); + for (const UUID& uuid: uuids) { - keys.push_back(container.Insert()); + handles.push_back(m_container.AcquireContainerHandle(uuid)); } - Random::shuffle(keys); for (auto _: state) { std::uint64_t sum = 0; - for (const SlotMapKey<> key: keys) + for (ContainerHandle* const handle: handles) { - if (const BenchmarkAsset* const asset = container.Get(key)) + if (const auto* const asset = static_cast(handle->GetAsset())) { sum += asset->GetHeader().type_id; } @@ -74,30 +95,22 @@ void Get(benchmark::State& state) state.SetItemsProcessed(state.iterations() * count); } -BENCHMARK(Get)->Name("AssetContainer/Get")->Arg(512)->Arg(8192)->Arg(131'072); +BENCHMARK_REGISTER_F(AssetContainerFixture, Get)->Name("AssetContainer/Get")->Arg(512)->Arg(8192)->Arg(131'072); /****************************************************************************************/ -void Has(benchmark::State& state) +BENCHMARK_DEFINE_F(AssetContainerFixture, Has)(benchmark::State& state) { const auto count = static_cast(state.range(0)); - AssetContainer container; - eastl::vector uuids; - uuids.reserve(count); - for (std::uint32_t i = 0; i < count; ++i) - { - const SlotMapKey<> key = container.Insert(); - uuids.push_back(container.Get(key)->GetHeader().uuid); - } - Random::shuffle(uuids); + const eastl::vector uuids = InsertRandomAssets(m_container, count); for (auto _: state) { bool result = true; for (const UUID& uuid: uuids) { - result = result && container.Has(uuid); + result = result && m_container.Has(uuid); } benchmark::DoNotOptimize(result); } @@ -105,30 +118,22 @@ void Has(benchmark::State& state) state.SetItemsProcessed(state.iterations() * count); } -BENCHMARK(Has)->Name("AssetContainer/Has")->Arg(512)->Arg(8192)->Arg(131'072); +BENCHMARK_REGISTER_F(AssetContainerFixture, Has)->Name("AssetContainer/Has")->Arg(512)->Arg(8192)->Arg(131'072); /****************************************************************************************/ -void AcquireContainerHandle(benchmark::State& state) +BENCHMARK_DEFINE_F(AssetContainerFixture, AcquireContainerHandle)(benchmark::State& state) { const auto count = static_cast(state.range(0)); - AssetContainer container; - eastl::vector uuids; - uuids.reserve(count); - for (std::uint32_t i = 0; i < count; ++i) - { - const SlotMapKey<> key = container.Insert(); - uuids.push_back(container.Get(key)->GetHeader().uuid); - } - Random::shuffle(uuids); + const eastl::vector uuids = InsertRandomAssets(m_container, count); for (auto _: state) { std::uint64_t sum = 0; for (const UUID& uuid: uuids) { - sum += container.AcquireContainerHandle(uuid)->GetHardRefCount(); + sum += m_container.AcquireContainerHandle(uuid)->GetHardRefCount(); } benchmark::DoNotOptimize(sum); } @@ -136,33 +141,29 @@ void AcquireContainerHandle(benchmark::State& state) state.SetItemsProcessed(state.iterations() * count); } -BENCHMARK(AcquireContainerHandle)->Name("AssetContainer/AcquireContainerHandle")->Arg(512)->Arg(8192)->Arg(131'072); +BENCHMARK_REGISTER_F(AssetContainerFixture, AcquireContainerHandle) + ->Name("AssetContainer/AcquireContainerHandle") + ->Arg(512) + ->Arg(8192) + ->Arg(131'072); /****************************************************************************************/ -void Remove(benchmark::State& state) +BENCHMARK_DEFINE_F(AssetContainerFixture, Remove)(benchmark::State& state) { const auto count = static_cast(state.range(0)); - AssetContainer container; eastl::vector uuids; - uuids.reserve(count); for (auto _: state) { state.PauseTiming(); - uuids.clear(); - for (std::uint32_t i = 0; i < count; ++i) - { - const SlotMapKey<> key = container.Insert(); - uuids.push_back(container.Get(key)->GetHeader().uuid); - } - Random::shuffle(uuids); + uuids = InsertRandomAssets(m_container, count); state.ResumeTiming(); for (const UUID& uuid: uuids) { - container.Remove(uuid); + m_container.Remove(uuid); } } @@ -170,5 +171,5 @@ void Remove(benchmark::State& state) state.SetBytesProcessed(static_cast(state.iterations() * count * sizeof(BenchmarkAsset))); } -BENCHMARK(Remove)->Name("AssetContainer/Remove")->Arg(512)->Arg(8192)->Arg(131'072); +BENCHMARK_REGISTER_F(AssetContainerFixture, Remove)->Name("AssetContainer/Remove")->Arg(512)->Arg(8192)->Arg(131'072); } // namespace Bigfoot diff --git a/Bigfoot/Benchmarks/Engine/Asset/Reference.cpp b/Bigfoot/Benchmarks/Engine/Asset/Reference.cpp index e61af86..f0ac226 100644 --- a/Bigfoot/Benchmarks/Engine/Asset/Reference.cpp +++ b/Bigfoot/Benchmarks/Engine/Asset/Reference.cpp @@ -10,6 +10,7 @@ #include +#include #include #include @@ -19,96 +20,119 @@ namespace Bigfoot { template class REFERENCE> -void Construct(benchmark::State& state) +class ReferenceFixture: public benchmark::Fixture { - AssetLibrary library; - AssetContainer container; - std::ignore = library.Insert(&container); - ScopedActiveAssetLibrary scopedLibrary {&library}; + protected: + using ReferenceType = REFERENCE; - const SlotMapKey<> key = container.Insert(); - const UUID uuid = container.Get(key)->GetHeader().uuid; + void SetUp(benchmark::State&) override + { + SetActiveAssetLibrary(&m_library); + std::ignore = m_library.Insert(&m_container); + m_uuid = m_container.Insert()->GetAsset()->GetHeader().uuid; + m_reference.emplace(m_uuid); + } + + void TearDown(benchmark::State&) override + { + SetActiveAssetLibrary(&g_assetLibrary); + } + + AssetLibrary m_library; + AssetContainer m_container; + UUID m_uuid; + eastl::optional m_reference; +}; + +/****************************************************************************************/ + +BENCHMARK_TEMPLATE_DEFINE_F(ReferenceFixture, HardReferenceConstruct, HardReference)(benchmark::State& state) +{ for (auto _: state) { - REFERENCE reference {uuid}; + ReferenceType reference {m_uuid}; benchmark::DoNotOptimize(reference); } state.SetItemsProcessed(state.iterations()); } -BENCHMARK_TEMPLATE(Construct, HardReference)->Name("Reference/HardReference/Construct"); -BENCHMARK_TEMPLATE(Construct, SoftReference)->Name("Reference/SoftReference/Construct"); +BENCHMARK_REGISTER_F(ReferenceFixture, HardReferenceConstruct)->Name("Reference/HardReference/Construct"); -/****************************************************************************************/ - -template class REFERENCE> -void Get(benchmark::State& state) +BENCHMARK_TEMPLATE_DEFINE_F(ReferenceFixture, SoftReferenceConstruct, SoftReference)(benchmark::State& state) { - AssetLibrary library; - AssetContainer container; - std::ignore = library.Insert(&container); - ScopedActiveAssetLibrary scopedLibrary {&library}; - - const SlotMapKey<> key = container.Insert(); - const UUID uuid = container.Get(key)->GetHeader().uuid; - - REFERENCE reference {uuid}; - for (auto _: state) { - benchmark::DoNotOptimize(reference.Get()); + ReferenceType reference {m_uuid}; + benchmark::DoNotOptimize(reference); } state.SetItemsProcessed(state.iterations()); } -BENCHMARK_TEMPLATE(Get, HardReference)->Name("Reference/HardReference/Get"); -BENCHMARK_TEMPLATE(Get, SoftReference)->Name("Reference/SoftReference/Get"); +BENCHMARK_REGISTER_F(ReferenceFixture, SoftReferenceConstruct)->Name("Reference/SoftReference/Construct"); /****************************************************************************************/ -template class REFERENCE> -void Copy(benchmark::State& state) +BENCHMARK_TEMPLATE_DEFINE_F(ReferenceFixture, HardReferenceGet, HardReference)(benchmark::State& state) { - AssetLibrary library; - AssetContainer container; - std::ignore = library.Insert(&container); - ScopedActiveAssetLibrary scopedLibrary {&library}; - - const SlotMapKey<> key = container.Insert(); - const UUID uuid = container.Get(key)->GetHeader().uuid; - - REFERENCE reference {uuid}; - for (auto _: state) { - REFERENCE copy {reference}; + benchmark::DoNotOptimize(m_reference->Get()); + } + + state.SetItemsProcessed(state.iterations()); +} + +BENCHMARK_REGISTER_F(ReferenceFixture, HardReferenceGet)->Name("Reference/HardReference/Get"); + +BENCHMARK_TEMPLATE_DEFINE_F(ReferenceFixture, SoftReferenceGet, SoftReference)(benchmark::State& state) +{ + for (auto _: state) + { + benchmark::DoNotOptimize(m_reference->Get()); + } + + state.SetItemsProcessed(state.iterations()); +} + +BENCHMARK_REGISTER_F(ReferenceFixture, SoftReferenceGet)->Name("Reference/SoftReference/Get"); + +/****************************************************************************************/ + +BENCHMARK_TEMPLATE_DEFINE_F(ReferenceFixture, HardReferenceCopy, HardReference)(benchmark::State& state) +{ + for (auto _: state) + { + ReferenceType copy {*m_reference}; benchmark::DoNotOptimize(copy); } state.SetItemsProcessed(state.iterations()); } -BENCHMARK_TEMPLATE(Copy, HardReference)->Name("Reference/HardReference/Copy"); -BENCHMARK_TEMPLATE(Copy, SoftReference)->Name("Reference/SoftReference/Copy"); +BENCHMARK_REGISTER_F(ReferenceFixture, HardReferenceCopy)->Name("Reference/HardReference/Copy"); + +BENCHMARK_TEMPLATE_DEFINE_F(ReferenceFixture, SoftReferenceCopy, SoftReference)(benchmark::State& state) +{ + for (auto _: state) + { + ReferenceType copy {*m_reference}; + benchmark::DoNotOptimize(copy); + } + + state.SetItemsProcessed(state.iterations()); +} + +BENCHMARK_REGISTER_F(ReferenceFixture, SoftReferenceCopy)->Name("Reference/SoftReference/Copy"); /****************************************************************************************/ -template class REFERENCE> -void Move(benchmark::State& state) +BENCHMARK_TEMPLATE_DEFINE_F(ReferenceFixture, HardReferenceMove, HardReference)(benchmark::State& state) { - AssetLibrary library; - AssetContainer container; - std::ignore = library.Insert(&container); - ScopedActiveAssetLibrary scopedLibrary {&library}; - - const SlotMapKey<> key = container.Insert(); - const UUID uuid = container.Get(key)->GetHeader().uuid; - constexpr std::size_t BATCH_SIZE = 128; - eastl::vector> batch; + eastl::vector batch; batch.reserve(BATCH_SIZE); for (auto _: state) @@ -117,13 +141,13 @@ void Move(benchmark::State& state) batch.clear(); for (std::size_t i = 0; i < BATCH_SIZE; ++i) { - batch.emplace_back(uuid); + batch.emplace_back(m_uuid); } state.ResumeTiming(); - for (REFERENCE& reference: batch) + for (ReferenceType& reference: batch) { - REFERENCE moved {std::move(reference)}; + ReferenceType moved {std::move(reference)}; benchmark::DoNotOptimize(moved); } } @@ -131,6 +155,33 @@ void Move(benchmark::State& state) state.SetItemsProcessed(state.iterations() * BATCH_SIZE); } -BENCHMARK_TEMPLATE(Move, HardReference)->Name("Reference/HardReference/Move"); -BENCHMARK_TEMPLATE(Move, SoftReference)->Name("Reference/SoftReference/Move"); +BENCHMARK_REGISTER_F(ReferenceFixture, HardReferenceMove)->Name("Reference/HardReference/Move"); + +BENCHMARK_TEMPLATE_DEFINE_F(ReferenceFixture, SoftReferenceMove, SoftReference)(benchmark::State& state) +{ + constexpr std::size_t BATCH_SIZE = 128; + eastl::vector batch; + batch.reserve(BATCH_SIZE); + + for (auto _: state) + { + state.PauseTiming(); + batch.clear(); + for (std::size_t i = 0; i < BATCH_SIZE; ++i) + { + batch.emplace_back(m_uuid); + } + state.ResumeTiming(); + + for (ReferenceType& reference: batch) + { + ReferenceType moved {std::move(reference)}; + benchmark::DoNotOptimize(moved); + } + } + + state.SetItemsProcessed(state.iterations() * BATCH_SIZE); +} + +BENCHMARK_REGISTER_F(ReferenceFixture, SoftReferenceMove)->Name("Reference/SoftReference/Move"); } // namespace Bigfoot diff --git a/Bigfoot/Benchmarks/Engine/BigFile/BigFile.cpp b/Bigfoot/Benchmarks/Engine/BigFile/BigFile.cpp index ae57ecd..4ab3ef3 100644 --- a/Bigfoot/Benchmarks/Engine/BigFile/BigFile.cpp +++ b/Bigfoot/Benchmarks/Engine/BigFile/BigFile.cpp @@ -39,10 +39,8 @@ class BigFileFixture: public benchmark::Fixture m_uuids.clear(); m_uuids.reserve(ASSET_COUNT); - eastl::vector metadatas; eastl::vector> flatbuffers; eastl::vector> hardReferences; - metadatas.reserve(ASSET_COUNT); flatbuffers.reserve(ASSET_COUNT); hardReferences.reserve(ASSET_COUNT); @@ -59,17 +57,13 @@ class BigFileFixture: public benchmark::Fixture asset.GetAsset().refs.emplace_back(assetReferred.GetHeader().uuid); } - metadatas.push_back(AssetMetadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}); const eastl::vector flatbuffer = asset.Pack(); flatbuffers.push_back(flatbuffer); - hardReferences.push_back(BenchmarkAsset::GetHardReferences(flatbuffer)); + hardReferences.push_back(asset.GetHardReferences(flatbuffer)); m_uuids.push_back(asset.GetHeader().uuid); } - m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers, hardReferences); + m_bigFile.SaveAssetFlatbuffers(m_uuids, flatbuffers, hardReferences); } [[nodiscard]] @@ -111,14 +105,11 @@ BENCHMARK_DEFINE_F(BigFileFixture, GetAssetFlatbuffer)(benchmark::State& state) for (auto _: state) { - eastl::optional> flatbuffer = m_bigFile.GetAssetFlatbuffer( + eastl::vector flatbuffer = m_bigFile.GetAssetFlatbuffer( m_uuids[Random::get(0, m_uuids.size() - 1)]); benchmark::DoNotOptimize(flatbuffer); - if (flatbuffer.has_value()) - { - bytesProcessed += static_cast(flatbuffer->size()); - } + bytesProcessed += static_cast(flatbuffer.size()); } state.SetItemsProcessed(state.iterations()); @@ -166,47 +157,6 @@ BENCHMARK_REGISTER_F(BigFileFixture, GetAssetFlatbuffers) /****************************************************************************************/ -BENCHMARK_DEFINE_F(BigFileFixture, GetAssetMetadata)(benchmark::State& state) -{ - for (auto _: state) - { - benchmark::DoNotOptimize(m_bigFile.GetAssetMetadata(m_uuids[Random::get(0, m_uuids.size() - 1)])); - } - - state.SetItemsProcessed(state.iterations()); -} - -BENCHMARK_REGISTER_F(BigFileFixture, GetAssetMetadata)->Name("BigFile/GetAssetMetadata"); - -/****************************************************************************************/ - -BENCHMARK_DEFINE_F(BigFileFixture, GetAssetMetadatas)(benchmark::State& state) -{ - const auto batchSize = static_cast(state.range(0)); - - constexpr std::size_t BATCH_POOL_SIZE = 64; - const eastl::vector> batchPool = RandomBatchPool(batchSize, BATCH_POOL_SIZE); - - std::size_t batchIndex = 0; - for (auto _: state) - { - benchmark::DoNotOptimize(m_bigFile.GetAssetMetadatas(batchPool[batchIndex])); - batchIndex = (batchIndex + 1) % BATCH_POOL_SIZE; - } - - state.SetItemsProcessed(state.iterations() * batchSize); -} - -BENCHMARK_REGISTER_F(BigFileFixture, GetAssetMetadatas) - ->Name("BigFile/GetAssetMetadatas") - ->Arg(1) - ->Arg(8) - ->Arg(64) - ->Arg(512) - ->Arg(4096); - -/****************************************************************************************/ - BENCHMARK_DEFINE_F(BigFileFixture, GetAssetHardReferences)(benchmark::State& state) { for (auto _: state) @@ -260,16 +210,12 @@ BENCHMARK_DEFINE_F(BigFileFixture, SaveAssetFlatbuffer)(benchmark::State& state) asset.SetName(asset.GetHeader().uuid.ToString().c_str()); asset.GetAsset().payload.assign(ASSET_PAYLOAD_SIZE, std::uint8_t {0xAB}); - const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}; const eastl::vector flatbuffer = asset.Pack(); - const eastl::vector hardReferences = BenchmarkAsset::GetHardReferences(flatbuffer); + const eastl::vector hardReferences = asset.GetHardReferences(flatbuffer); bytesProcessed += static_cast(flatbuffer.size()); state.ResumeTiming(); - m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer, hardReferences); + m_bigFile.SaveAssetFlatbuffer(asset.GetHeader().uuid, flatbuffer, hardReferences); } state.SetItemsProcessed(state.iterations()); @@ -288,10 +234,8 @@ BENCHMARK_DEFINE_F(BigFileFixture, SaveAssetFlatbuffers)(benchmark::State& state for (auto _: state) { state.PauseTiming(); - eastl::vector metadatas; eastl::vector> flatbuffers; eastl::vector> hardReferences; - metadatas.reserve(batchSize); flatbuffers.reserve(batchSize); hardReferences.reserve(batchSize); @@ -301,18 +245,14 @@ BENCHMARK_DEFINE_F(BigFileFixture, SaveAssetFlatbuffers)(benchmark::State& state asset.SetName(asset.GetHeader().uuid.ToString().c_str()); asset.GetAsset().payload.assign(ASSET_PAYLOAD_SIZE, std::uint8_t {0xAB}); - metadatas.push_back(AssetMetadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}); const eastl::vector flatbuffer = asset.Pack(); flatbuffers.push_back(flatbuffer); - hardReferences.push_back(BenchmarkAsset::GetHardReferences(flatbuffer)); + hardReferences.push_back(asset.GetHardReferences(flatbuffer)); bytesProcessed += static_cast(flatbuffer.size()); } state.ResumeTiming(); - m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers, hardReferences); + m_bigFile.SaveAssetFlatbuffers(m_uuids, flatbuffers, hardReferences); } state.SetItemsProcessed(state.iterations() * batchSize); diff --git a/Bigfoot/Benchmarks/Engine/Sasquatch/Sasquatch.cpp b/Bigfoot/Benchmarks/Engine/Sasquatch/Sasquatch.cpp index 47a6cbb..9255b31 100644 --- a/Bigfoot/Benchmarks/Engine/Sasquatch/Sasquatch.cpp +++ b/Bigfoot/Benchmarks/Engine/Sasquatch/Sasquatch.cpp @@ -67,7 +67,7 @@ class SasquatchFixture: public benchmark::Fixture const eastl::vector flatbuffer = asset.Pack(); flatbuffers.push_back(flatbuffer); - hardReferences.push_back(BenchmarkAsset::GetHardReferences(flatbuffer)); + hardReferences.push_back(asset.GetHardReferences(flatbuffer)); m_uuids.push_back(asset.GetHeader().uuid); } @@ -188,14 +188,11 @@ BENCHMARK_DEFINE_F(SasquatchFixture, GetAssetFlatbuffer)(benchmark::State& state for (auto _: state) { - eastl::optional> flatbuffer = m_sasquatch->GetAssetFlatbuffer( + eastl::vector flatbuffer = m_sasquatch->GetAssetFlatbuffer( m_uuids[Random::get(0, m_uuids.size() - 1)]); benchmark::DoNotOptimize(flatbuffer); - if (flatbuffer.has_value()) - { - bytesProcessed += static_cast(flatbuffer->size()); - } + bytesProcessed += static_cast(flatbuffer.size()); } state.SetItemsProcessed(state.iterations()); diff --git a/Bigfoot/Benchmarks/Tools/SasquatchBaker/SasquatchBaker.cpp b/Bigfoot/Benchmarks/Tools/SasquatchBaker/SasquatchBaker.cpp index 392f7ce..d08a912 100644 --- a/Bigfoot/Benchmarks/Tools/SasquatchBaker/SasquatchBaker.cpp +++ b/Bigfoot/Benchmarks/Tools/SasquatchBaker/SasquatchBaker.cpp @@ -34,10 +34,10 @@ class SasquatchBakerFixture: public benchmark::Fixture m_bigFile.Clear(); m_outputFile.Delete(); - eastl::vector metadatas; + eastl::vector uuids; eastl::vector> flatbuffers; eastl::vector> hardReferences; - metadatas.reserve(ASSET_COUNT); + uuids.reserve(ASSET_COUNT); flatbuffers.reserve(ASSET_COUNT); hardReferences.reserve(ASSET_COUNT); @@ -47,16 +47,13 @@ class SasquatchBakerFixture: public benchmark::Fixture asset.SetName(asset.GetHeader().uuid.ToString().c_str()); asset.GetAsset().payload.assign(ASSET_PAYLOAD_SIZE, std::uint8_t {0xAB}); - metadatas.push_back(AssetMetadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}); const eastl::vector flatbuffer = asset.Pack(); flatbuffers.push_back(flatbuffer); - hardReferences.push_back(BenchmarkAsset::GetHardReferences(flatbuffer)); + hardReferences.push_back(asset.GetHardReferences(flatbuffer)); + uuids.push_back(asset.GetHeader().uuid); } - m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers, hardReferences); + m_bigFile.SaveAssetFlatbuffers(uuids, flatbuffers, hardReferences); } void TearDown(benchmark::State&) override diff --git a/Bigfoot/Sources/Engine/Asset/AssetLibrary.cpp b/Bigfoot/Sources/Engine/Asset/AssetLibrary.cpp index e78d2f4..382c952 100644 --- a/Bigfoot/Sources/Engine/Asset/AssetLibrary.cpp +++ b/Bigfoot/Sources/Engine/Asset/AssetLibrary.cpp @@ -8,6 +8,60 @@ namespace Bigfoot { +AssetContainerBase* AssetLibrary::GetAssetContainer(const AssetTypeID p_typeID) +{ + if (const auto container = m_assetContainers.find(p_typeID); container != m_assetContainers.end()) + { + return container->second; + } + + return nullptr; +} + +/****************************************************************************************/ + +const AssetContainerBase* AssetLibrary::GetAssetContainer(const AssetTypeID p_typeID) const +{ + if (const auto container = m_assetContainers.find(p_typeID); container != m_assetContainers.end()) + { + return container->second; + } + + return nullptr; +} + +/****************************************************************************************/ + +const AssetContainerBase* AssetLibrary::GetAssetContainer(const UUID& p_uuid) const +{ + for (const auto [typeId, container]: m_assetContainers) + { + if (container->Has(p_uuid)) + { + return container; + } + } + + return nullptr; +} + +/****************************************************************************************/ + +AssetContainerBase* AssetLibrary::GetAssetContainer(const UUID& p_uuid) +{ + for (const auto [typeId, container]: m_assetContainers) + { + if (container->Has(p_uuid)) + { + return container; + } + } + + return nullptr; +} + +/****************************************************************************************/ + void SetActiveAssetLibrary(AssetLibrary* p_assetLibrary) { g_activeAssetLibrary = p_assetLibrary; diff --git a/Bigfoot/Sources/Engine/BigFile/BigFile.cpp b/Bigfoot/Sources/Engine/BigFile/BigFile.cpp index d61ffb5..5df338b 100644 --- a/Bigfoot/Sources/Engine/BigFile/BigFile.cpp +++ b/Bigfoot/Sources/Engine/BigFile/BigFile.cpp @@ -9,7 +9,6 @@ #include #include -#include #include namespace Bigfoot @@ -109,58 +108,74 @@ eastl::vector BigFile::GetAssetFlatbuffer(const UUID& p_uuid) const eastl::vector> BigFile::GetAssetFlatbuffers(const eastl::span p_uuids) const { - eastl::vector> flatbuffers; + eastl::vector> flatbuffers(p_uuids.size()); + if (p_uuids.empty()) { return flatbuffers; } - flatbuffers.reserve(p_uuids.size()); - - if (p_uuids.size() == 1) + ankerl::unordered_dense::map> uuidToIndices; + uuidToIndices.reserve(p_uuids.size()); + for (std::size_t i = 0; i < p_uuids.size(); ++i) { - if (eastl::optional> flatbuffer = GetAssetFlatbuffer(p_uuids[0]); - flatbuffer.has_value()) - { - flatbuffers.push_back(std::move(*flatbuffer)); - } - - return flatbuffers; + uuidToIndices[p_uuids[i]].push_back(i); } - eastl::vector uniqueUUIDs {p_uuids.begin(), p_uuids.end()}; - eastl::sort(uniqueUUIDs.begin(), uniqueUUIDs.end()); - uniqueUUIDs.erase(eastl::unique(uniqueUUIDs.begin(), uniqueUUIDs.end()), uniqueUUIDs.end()); - - eastl::string placeholders; - placeholders.reserve(uniqueUUIDs.size() * 3); - for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i) + eastl::vector distinctUUIDs; + distinctUUIDs.reserve(uuidToIndices.size()); + for (const auto& [uuid, indices]: uuidToIndices) { - if (i > 0) - { - placeholders += ", "; - } - placeholders += "?"; + distinctUUIDs.push_back(uuid); } - const std::string sqlRequest = fmt::format("SELECT Asset FROM Asset WHERE UUID IN ({});", placeholders); + constexpr std::size_t PARAMS_PER_ROW = 1; + const std::size_t maxRowsPerStatement = static_cast( + sqlite3_limit(m_db, SQLITE_LIMIT_VARIABLE_NUMBER, -1)) / + PARAMS_PER_ROW; - BigFile::Request assetRequest {*this, sqlRequest.c_str()}; - for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i) + for (std::size_t chunkStart = 0; chunkStart < distinctUUIDs.size(); chunkStart += maxRowsPerStatement) { - assetRequest.Bind(static_cast(i + 1), uniqueUUIDs[i].ToBytes()); - } + const std::size_t chunkSize = eastl::min(maxRowsPerStatement, distinctUUIDs.size() - chunkStart); - flatbuffers.reserve(uniqueUUIDs.size()); - for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i) - { - if (!assetRequest.Step()) + eastl::string placeholders; + placeholders.reserve(chunkSize * 2); + for (std::size_t i = 0; i < chunkSize; ++i) { - break; + if (i > 0) + { + placeholders += ", "; + } + placeholders += "?"; } - const eastl::span flatbuffer = assetRequest.Get(0); - flatbuffers.emplace_back(flatbuffer.begin(), flatbuffer.end()); + const std::string sql = fmt::format("SELECT UUID, Asset FROM Asset WHERE UUID IN ({});", placeholders); + + BigFile::Request assetRequest {*this, sql.c_str()}; + for (std::size_t i = 0; i < chunkSize; ++i) + { + assetRequest.Bind(static_cast(i + 1), distinctUUIDs[chunkStart + i].ToBytes()); + } + + while (assetRequest.Step()) + { + const eastl::span rawUUID = + static_cast>(assetRequest.Get(0)); + const UUID uuid {std::span {rawUUID.begin(), rawUUID.end()}}; + + const auto it = uuidToIndices.find(uuid); + ASSERT(EngineAssertHandler, + it != uuidToIndices.end(), + "Returned UUID {} not found in requested UUIDs", + uuid); + + const eastl::span flatbuffer = assetRequest.Get(1); + + for (const std::size_t index: it->second) + { + flatbuffers[index].assign(flatbuffer.begin(), flatbuffer.end()); + } + } } return flatbuffers; @@ -168,99 +183,6 @@ eastl::vector> BigFile::GetAssetFlatbuffers(const eastl /****************************************************************************************/ -AssetMetadata BigFile::GetAssetMetadata(const UUID& p_uuid) const -{ - BigFile::Request assetRequest { - *this, - "SELECT UUID, Name, TypeID, TypeName, CreateTime, ModificationTime FROM AssetMetadata WHERE UUID = ?1;"}; - assetRequest.Bind(1, p_uuid.ToBytes()); - - if (!assetRequest.Step()) - { - return {}; - } - - return AssetMetadata {.m_uuid = UUID {std::span { - static_cast>(assetRequest.Get(0)).data(), - UUID::UUID_BYTE_SIZE}}, - .m_name = eastl::string {static_cast(assetRequest.Get(1))}, - .m_typeID = assetRequest.Get(2), - .m_typeName = eastl::string {static_cast(assetRequest.Get(3))}, - .m_creationTime = Time {static_cast(assetRequest.Get(4))}, - .m_modificationTime = Time {static_cast(assetRequest.Get(5))}}; -} - -/****************************************************************************************/ - -eastl::vector BigFile::GetAssetMetadatas(const eastl::span p_uuids) const -{ - eastl::vector metadatas; - if (p_uuids.empty()) - { - return metadatas; - } - - metadatas.reserve(p_uuids.size()); - - if (p_uuids.size() == 1) - { - if (eastl::optional metadata = GetAssetMetadata(p_uuids[0]); metadata.has_value()) - { - metadatas.push_back(std::move(*metadata)); - } - - return metadatas; - } - - eastl::vector uniqueUUIDs {p_uuids.begin(), p_uuids.end()}; - eastl::sort(uniqueUUIDs.begin(), uniqueUUIDs.end()); - uniqueUUIDs.erase(eastl::unique(uniqueUUIDs.begin(), uniqueUUIDs.end()), uniqueUUIDs.end()); - - eastl::string placeholders; - placeholders.reserve(uniqueUUIDs.size() * 3); - for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i) - { - if (i > 0) - { - placeholders += ", "; - } - placeholders += "?"; - } - - const std::string sqlRequest = fmt::format("SELECT UUID, Name, TypeID, TypeName, CreateTime, ModificationTime " - "FROM AssetMetadata WHERE UUID IN ({});", - placeholders); - - BigFile::Request assetRequest {*this, sqlRequest.c_str()}; - for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i) - { - assetRequest.Bind(static_cast(i + 1), uniqueUUIDs[i].ToBytes()); - } - - metadatas.reserve(uniqueUUIDs.size()); - for (std::size_t i = 0; i < uniqueUUIDs.size(); ++i) - { - if (!assetRequest.Step()) - { - break; - } - - metadatas.push_back( - AssetMetadata {.m_uuid = UUID {std::span { - static_cast>(assetRequest.Get(0)).data(), - UUID::UUID_BYTE_SIZE}}, - .m_name = eastl::string {static_cast(assetRequest.Get(1))}, - .m_typeID = assetRequest.Get(2), - .m_typeName = eastl::string {static_cast(assetRequest.Get(3))}, - .m_creationTime = Time {static_cast(assetRequest.Get(4))}, - .m_modificationTime = Time {static_cast(assetRequest.Get(5))}}); - } - - return metadatas; -} - -/****************************************************************************************/ - eastl::vector BigFile::GetAssetHardReferences(const UUID& p_uuid) const { BigFile::Request hardReferencesRequest {*this, "SELECT HardReference FROM AssetHardReference WHERE UUID = ?1;"}; @@ -361,31 +283,123 @@ eastl::vector> BigFile::GetAssetsHardReferences(eastl::span< /****************************************************************************************/ -void BigFile::SaveAssetFlatbuffer(const AssetMetadata& p_metadata, +eastl::optional BigFile::GetAssetTime(const UUID& p_uuid) const +{ + BigFile::Request timeRequest {*this, "SELECT CreateTime, ModificationTime FROM AssetMetadata WHERE UUID = ?1;"}; + timeRequest.Bind(1, p_uuid.ToBytes()); + + if (!timeRequest.Step()) + { + return eastl::nullopt; + } + + return AssetTime {.m_creationTime = Time {static_cast(timeRequest.Get(0))}, + .m_modificationTime = Time {static_cast(timeRequest.Get(1))}}; +} + +/****************************************************************************************/ + +eastl::vector> BigFile::GetAssetsTime(const eastl::span p_uuids) const +{ + eastl::vector> times(p_uuids.size()); + + if (p_uuids.empty()) + { + return times; + } + + ankerl::unordered_dense::map> uuidToIndices; + uuidToIndices.reserve(p_uuids.size()); + for (std::size_t i = 0; i < p_uuids.size(); ++i) + { + uuidToIndices[p_uuids[i]].push_back(i); + } + + eastl::vector distinctUUIDs; + distinctUUIDs.reserve(uuidToIndices.size()); + for (const auto& [uuid, indices]: uuidToIndices) + { + distinctUUIDs.push_back(uuid); + } + + constexpr std::size_t PARAMS_PER_ROW = 1; + const std::size_t maxRowsPerStatement = static_cast( + sqlite3_limit(m_db, SQLITE_LIMIT_VARIABLE_NUMBER, -1)) / + PARAMS_PER_ROW; + + for (std::size_t chunkStart = 0; chunkStart < distinctUUIDs.size(); chunkStart += maxRowsPerStatement) + { + const std::size_t chunkSize = eastl::min(maxRowsPerStatement, distinctUUIDs.size() - chunkStart); + + eastl::string placeholders; + placeholders.reserve(chunkSize * 2); + for (std::size_t i = 0; i < chunkSize; ++i) + { + if (i > 0) + { + placeholders += ", "; + } + placeholders += "?"; + } + + const std::string sql = fmt::format( + "SELECT UUID, CreateTime, ModificationTime FROM AssetMetadata WHERE UUID IN ({});", + placeholders); + + BigFile::Request timeRequest {*this, sql.c_str()}; + for (std::size_t i = 0; i < chunkSize; ++i) + { + timeRequest.Bind(static_cast(i + 1), distinctUUIDs[chunkStart + i].ToBytes()); + } + + while (timeRequest.Step()) + { + const eastl::span rawUUID = + static_cast>(timeRequest.Get(0)); + const UUID uuid {std::span {rawUUID.begin(), rawUUID.end()}}; + + const auto it = uuidToIndices.find(uuid); + ASSERT(EngineAssertHandler, + it != uuidToIndices.end(), + "Returned UUID {} not found in requested UUIDs", + uuid); + + const AssetTime assetTime {.m_creationTime = Time {static_cast(timeRequest.Get(1))}, + .m_modificationTime = Time {static_cast(timeRequest.Get(2))}}; + + for (const std::size_t index: it->second) + { + times[index] = assetTime; + } + } + } + + return times; +} + +/****************************************************************************************/ + +void BigFile::SaveAssetFlatbuffer(const UUID& p_uuid, const eastl::span p_flatbuffer, const eastl::span p_hardReferences) { BeginTransaction(); - BigFile::Request metadataRequest { - *this, - "INSERT INTO AssetMetadata (UUID, Name, TypeID, TypeName) VALUES (?1, ?2, ?3, ?4) " - "ON CONFLICT(UUID) DO UPDATE SET Name = excluded.Name, TypeID = excluded.TypeID, TypeName = excluded.TypeName;"}; - metadataRequest.Bind(1, p_metadata.m_uuid.ToBytes()); - metadataRequest.Bind(2, p_metadata.m_name); - metadataRequest.Bind(3, p_metadata.m_typeID); - metadataRequest.Bind(4, p_metadata.m_typeName); + BigFile::Request metadataRequest {*this, + "INSERT INTO AssetMetadata (UUID) VALUES (?1) " + "ON CONFLICT(UUID) DO NOTHING;"}; + metadataRequest.Bind(1, p_uuid.ToBytes()); metadataRequest.Execute(); BigFile::Request assetRequest {*this, "INSERT INTO Asset (UUID, Asset) VALUES (?1, ?2) " "ON CONFLICT(UUID) DO UPDATE SET Asset = excluded.Asset;"}; - assetRequest.Bind(1, p_metadata.m_uuid.ToBytes()); + assetRequest.Bind(1, p_uuid.ToBytes()); assetRequest.Bind(2, p_flatbuffer); assetRequest.Execute(); BigFile::Request deleteHardReferencesRequest {*this, "DELETE FROM AssetHardReference WHERE UUID = ?1;"}; - deleteHardReferencesRequest.Bind(1, p_metadata.m_uuid.ToBytes()); + deleteHardReferencesRequest.Bind(1, p_uuid.ToBytes()); deleteHardReferencesRequest.Execute(); constexpr std::size_t HARDREF_PARAMS_PER_ROW = 2; @@ -417,7 +431,7 @@ void BigFile::SaveAssetFlatbuffer(const AssetMetadata& p_metadata, std::uint32_t bindIndex = 1; for (std::size_t i = 0; i < chunkSize; ++i) { - hardReferenceRequest.Bind(bindIndex++, p_metadata.m_uuid.ToBytes()); + hardReferenceRequest.Bind(bindIndex++, p_uuid.ToBytes()); hardReferenceRequest.Bind(bindIndex++, p_hardReferences[chunkStart + i].ToBytes()); } hardReferenceRequest.Execute(); @@ -428,15 +442,15 @@ void BigFile::SaveAssetFlatbuffer(const AssetMetadata& p_metadata, /****************************************************************************************/ -void BigFile::SaveAssetFlatbuffers(const eastl::span p_metadatas, +void BigFile::SaveAssetFlatbuffers(const eastl::span p_uuids, const eastl::span> p_flatbuffers, const eastl::span> p_hardReferences) { ASSERT(EngineAssertHandler, - p_metadatas.size() == p_flatbuffers.size() && p_metadatas.size() == p_hardReferences.size(), + p_uuids.size() == p_flatbuffers.size() && p_uuids.size() == p_hardReferences.size(), "p_metadatas and p_flatbuffers and p_hardReferences must have the same size"); - if (p_metadatas.empty()) + if (p_uuids.empty()) { return; } @@ -448,9 +462,9 @@ void BigFile::SaveAssetFlatbuffers(const eastl::span p_meta sqlite3_limit(m_db, SQLITE_LIMIT_VARIABLE_NUMBER, -1)) / METADATA_PARAMS_PER_ROW; - for (std::size_t chunkStart = 0; chunkStart < p_metadatas.size(); chunkStart += maxRowsPerStatement) + for (std::size_t chunkStart = 0; chunkStart < p_uuids.size(); chunkStart += maxRowsPerStatement) { - const std::size_t chunkSize = eastl::min(maxRowsPerStatement, p_metadatas.size() - chunkStart); + const std::size_t chunkSize = eastl::min(maxRowsPerStatement, p_uuids.size() - chunkStart); eastl::string metadataPlaceholders; metadataPlaceholders.reserve(chunkSize * 14); @@ -460,24 +474,18 @@ void BigFile::SaveAssetFlatbuffers(const eastl::span p_meta { metadataPlaceholders += ", "; } - metadataPlaceholders += "(?, ?, ?, ?)"; + metadataPlaceholders += "(?)"; } const std::string metadataSQL = fmt::format( - "INSERT INTO AssetMetadata (UUID, Name, TypeID, TypeName) VALUES {} " - "ON CONFLICT(UUID) DO UPDATE SET Name = excluded.Name, TypeID = excluded.TypeID, TypeName = " - "excluded.TypeName;", + "INSERT INTO AssetMetadata (UUID) VALUES {} ON CONFLICT(UUID) DO NOTHING;", metadataPlaceholders); BigFile::Request metadataRequest {*this, metadataSQL.c_str()}; std::uint32_t metadataBindIndex = 1; for (std::size_t i = 0; i < chunkSize; ++i) { - const AssetMetadata& metadata = p_metadatas[chunkStart + i]; - metadataRequest.Bind(metadataBindIndex++, metadata.m_uuid.ToBytes()); - metadataRequest.Bind(metadataBindIndex++, metadata.m_name); - metadataRequest.Bind(metadataBindIndex++, metadata.m_typeID); - metadataRequest.Bind(metadataBindIndex++, metadata.m_typeName); + metadataRequest.Bind(metadataBindIndex++, p_uuids[chunkStart + i].ToBytes()); } metadataRequest.Execute(); @@ -500,7 +508,7 @@ void BigFile::SaveAssetFlatbuffers(const eastl::span p_meta std::uint32_t assetBindIndex = 1; for (std::size_t i = 0; i < chunkSize; ++i) { - assetRequest.Bind(assetBindIndex++, p_metadatas[chunkStart + i].m_uuid.ToBytes()); + assetRequest.Bind(assetBindIndex++, p_uuids[chunkStart + i].ToBytes()); assetRequest.Bind(assetBindIndex++, p_flatbuffers[chunkStart + i]); } assetRequest.Execute(); @@ -523,18 +531,16 @@ void BigFile::SaveAssetFlatbuffers(const eastl::span p_meta BigFile::Request deleteHardReferencesRequest {*this, deleteHardReferencesSQL.c_str()}; for (std::size_t i = 0; i < chunkSize; ++i) { - deleteHardReferencesRequest.Bind(static_cast(i + 1), - p_metadatas[chunkStart + i].m_uuid.ToBytes()); + deleteHardReferencesRequest.Bind(static_cast(i + 1), p_uuids[chunkStart + i].ToBytes()); } deleteHardReferencesRequest.Execute(); eastl::vector> hardReferencePairs; for (std::size_t i = 0; i < chunkSize; ++i) { - const UUID& assetUUID = p_metadatas[chunkStart + i].m_uuid; for (const UUID& hardReference: p_hardReferences[chunkStart + i]) { - hardReferencePairs.emplace_back(assetUUID, hardReference); + hardReferencePairs.emplace_back(p_uuids[chunkStart + i], hardReference); } } diff --git a/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql b/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql index 62882de..209dd73 100644 --- a/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql +++ b/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql @@ -2,9 +2,6 @@ PRAGMA journal_mode=WAL; CREATE TABLE IF NOT EXISTS AssetMetadata ( UUID BLOB NOT NULL, - Name TEXT NOT NULL, - TypeID INTEGER NOT NULL, - TypeName TEXT NOT NULL, CreateTime INTEGER NOT NULL DEFAULT(CAST(unixepoch('subsec') * 1000000 AS INTEGER)), ModificationTime INTEGER NOT NULL DEFAULT(CAST(unixepoch('subsec') * 1000000 AS INTEGER)), @@ -12,14 +9,6 @@ CREATE TABLE IF NOT EXISTS AssetMetadata ( PRIMARY KEY(UUID) ) WITHOUT ROWID; -CREATE TRIGGER IF NOT EXISTS AssetMetadata_UpdateTime -AFTER UPDATE OF Name, TypeID, TypeName ON AssetMetadata FOR EACH ROW -BEGIN - UPDATE AssetMetadata - SET ModificationTime = CAST(unixepoch('subsec') * 1000000 AS INTEGER) - WHERE UUID = NEW.UUID; -END; - CREATE TABLE IF NOT EXISTS Asset ( UUID BLOB NOT NULL, diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp index 4d2f450..6b54468 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/Asset.hpp @@ -23,37 +23,37 @@ class AssetBase public: virtual ~AssetBase() = default; + /** + * Get the header of the asset + * + * \return The header of the asset + */ + [[nodiscard]] + virtual const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const = 0; + /** * Get the HardReferences the flatbuffer has * - * \tparam ASSET The asset to walk * \param p_flatbuffer The flatbuffer * \return The UUIDs of the HardReferences */ - template - requires AssetTraits [[nodiscard]] - static eastl::vector GetHardReferences(const eastl::span p_flatbuffer) - { -#ifdef BIGFOOT_NOT_OPTIMIZED - flatbuffers::Verifier verifier {std::bit_cast(p_flatbuffer.data()), p_flatbuffer.size()}; - const bool assetVerified = ::Flat::Bigfoot::VerifyAssetBuffer(verifier); - CRITICAL_ASSERT(EngineAssertHandler, assetVerified, "Given asset could not be verified!"); -#endif + virtual eastl::vector GetHardReferences(const eastl::span p_flatbuffer) const = 0; - const ::Flat::Bigfoot::Asset* asset = flatbuffers::GetRoot<::Flat::Bigfoot::Asset>(p_flatbuffer.data()); + /** + * Unpack a flatbuffer to the asset + * + * \param p_flatbuffer The flatbuffer to unpack + */ + virtual void Unpack(const eastl::span p_flatbuffer) = 0; -#ifdef BIGFOOT_NOT_OPTIMIZED - flatbuffers::Verifier innerAssetVerifier {asset->inner_asset()->data(), asset->inner_asset()->size()}; - const bool innerAssetVerified = innerAssetVerifier.VerifyBuffer(); - CRITICAL_ASSERT(EngineAssertHandler, innerAssetVerified, "Given asset could not be verified!"); -#endif - - HardReferenceVisitor visitor; - - flatbuffers::IterateFlatBuffer(asset->inner_asset()->data(), ASSET::FLAT::MiniReflectTypeTable(), &visitor); - return visitor.GetUUIDs(); - } + /** + * Pack the asset to a flatbuffer + * + * \return The packed asset + */ + [[nodiscard]] + virtual eastl::vector Pack() const = 0; protected: AssetBase() = default; @@ -64,7 +64,6 @@ class AssetBase AssetBase& operator=(const AssetBase& p_asset) = delete; AssetBase& operator=(AssetBase&& p_asset) = default; - private: class HardReferenceVisitor: public flatbuffers::IterationVisitor { public: @@ -133,7 +132,7 @@ class Asset: public AssetBase * \return The header of the asset */ [[nodiscard]] - const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const + const ::Flat::Bigfoot::AssetHeaderT& GetHeader() const override { return m_header; } @@ -175,7 +174,7 @@ class Asset: public AssetBase * * \param p_flatbuffer The flatbuffer to unpack */ - void Unpack(const eastl::span p_flatbuffer) + void Unpack(const eastl::span p_flatbuffer) override { #ifdef BIGFOOT_NOT_OPTIMIZED flatbuffers::Verifier verifier {std::bit_cast(p_flatbuffer.data()), p_flatbuffer.size()}; @@ -201,7 +200,7 @@ class Asset: public AssetBase * \return The packed asset */ [[nodiscard]] - eastl::vector Pack() const + eastl::vector Pack() const override { flatbuffers::FlatBufferBuilder innerAssetFbb; innerAssetFbb.Finish(FLAT_ASSET::Pack(innerAssetFbb, &m_asset)); @@ -222,9 +221,26 @@ class Asset: public AssetBase * \return The UUIDs of the HardReferences */ [[nodiscard]] - static eastl::vector GetHardReferences(const eastl::span p_flatbuffer) + eastl::vector GetHardReferences(const eastl::span p_flatbuffer) const override { - return AssetBase::GetHardReferences(p_flatbuffer); +#ifdef BIGFOOT_NOT_OPTIMIZED + flatbuffers::Verifier verifier {std::bit_cast(p_flatbuffer.data()), p_flatbuffer.size()}; + const bool assetVerified = ::Flat::Bigfoot::VerifyAssetBuffer(verifier); + CRITICAL_ASSERT(EngineAssertHandler, assetVerified, "Given asset could not be verified!"); +#endif + + const ::Flat::Bigfoot::Asset* asset = flatbuffers::GetRoot<::Flat::Bigfoot::Asset>(p_flatbuffer.data()); + +#ifdef BIGFOOT_NOT_OPTIMIZED + flatbuffers::Verifier innerAssetVerifier {asset->inner_asset()->data(), asset->inner_asset()->size()}; + const bool innerAssetVerified = innerAssetVerifier.VerifyBuffer(); + CRITICAL_ASSERT(EngineAssertHandler, innerAssetVerified, "Given asset could not be verified!"); +#endif + + HardReferenceVisitor visitor; + + flatbuffers::IterateFlatBuffer(asset->inner_asset()->data(), FLAT_ASSET::MiniReflectTypeTable(), &visitor); + return visitor.GetUUIDs(); } /** diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp index a0fa807..1e4d591 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetContainer.hpp @@ -141,6 +141,23 @@ class AssetContainerBase public: virtual ~AssetContainerBase() = default; + /* + * Inserts an Asset to the AssetContainer + * + * \param p_flatbuffer The flatbuffer to unpack to the asset + * \return The handle of the inserted asset + */ + [[nodiscard]] + virtual ContainerHandle* Insert(const eastl::span p_flatbuffer) = 0; + + /* + * Inserts an Asset to the AssetContainer + * + * \return The handle of the inserted asset + */ + [[nodiscard]] + virtual ContainerHandle* Insert() = 0; + /* * Check if an Asset is in the AssetContainer or not * @@ -172,10 +189,16 @@ class AssetContainerBase * * \param p_uuid The UUID to remove */ - virtual void Remove(const UUID& p_uuid) + void Remove(const UUID& p_uuid) { if (Entry* entry = FindEntry(p_uuid); entry != nullptr) { + if (entry->m_assetSlotKey.Valid()) + { + entry->m_handle->SetAsset(nullptr); + RemoveAsset(entry->m_assetSlotKey); + entry->m_assetSlotKey = SlotMapKey {}; + } m_handles.Remove(entry->m_handleSlotKey); m_uuidToEntry.erase(p_uuid); } @@ -252,6 +275,13 @@ class AssetContainerBase return it->second; } + /* + * Remove an asset + * + * \param p_key The key to the asset + */ + virtual void RemoveAsset(SlotMapKey p_slotKey) = 0; + private: /* * HandleContainers @@ -277,16 +307,42 @@ class AssetContainer: public AssetContainerBase /* * Inserts an Asset to the AssetContainer * - * \tparam ARGS Arguments to construct the asset - * \param p_args The arguments - * \return The key to the inserted asset. + * \param p_flatbuffer The flatbuffer to unpack to the asset + * \return The handle of the inserted asset */ - template [[nodiscard]] - SlotMapKey Insert(ARGS&&... p_args) + ContainerHandle* Insert(const eastl::span p_flatbuffer) override { - SlotMapKey slotKey = m_assets.Insert(std::forward(p_args)...); + return InsertInternal(&p_flatbuffer); + } + + /* + * Inserts an Asset to the AssetContainer + * + * \return The handle of the inserted asset + */ + [[nodiscard]] + ContainerHandle* Insert() override + { + return InsertInternal(nullptr); + } + + private: + /* + * Inserts an Asset to the AssetContainer, unpacking it from a flatbuffer if given one + * + * \param p_flatbuffer The flatbuffer to unpack to the asset, nullptr to default-construct the asset + * \return The handle of the inserted asset + */ + [[nodiscard]] + ContainerHandle* InsertInternal(const eastl::span* p_flatbuffer) + { + SlotMapKey slotKey = m_assets.Insert(); ASSET* asset = m_assets.Get(slotKey); + if (p_flatbuffer != nullptr) + { + asset->Unpack(*p_flatbuffer); + } Entry& entry = GetOrCreateEntry(asset->GetHeader().uuid); if (entry.m_assetSlotKey.Valid()) @@ -300,48 +356,17 @@ class AssetContainer: public AssetContainerBase entry.m_handle->SetAsset(asset); } - return slotKey; + return entry.m_handle; } /* - * Get the Asset + * Remove an asset * * \param p_key The key to the asset - * \return Pointer to the Asset */ - [[nodiscard]] - ASSET* Get(const SlotMapKey p_key) + void RemoveAsset(SlotMapKey p_key) override { - return m_assets.Get(p_key); - } - - /* - * Get the Asset - * - * \param p_key The key to the asset - * \return Pointer to the Asset - */ - [[nodiscard]] - const ASSET* Get(const SlotMapKey p_key) const - { - return m_assets.Get(p_key); - } - - /* - * Remove an Asset from the AssetContainer - * - * \param p_uuid The UUID to remove - */ - void Remove(const UUID& p_uuid) override - { - if (Entry* entry = FindEntry(p_uuid); entry != nullptr && entry->m_assetSlotKey.Valid()) - { - entry->m_handle->SetAsset(nullptr); - m_assets.Remove(entry->m_assetSlotKey); - entry->m_assetSlotKey = SlotMapKey {}; - } - - AssetContainerBase::Remove(p_uuid); + m_assets.Remove(p_key); } private: diff --git a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetLibrary.hpp b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetLibrary.hpp index 87932cb..5a4652d 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetLibrary.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Asset/AssetLibrary.hpp @@ -52,15 +52,7 @@ class AssetLibrary * \return The AssetContainer for the AssetType. Nullptr if not found */ [[nodiscard]] - AssetContainerBase* GetAssetContainer(const AssetTypeID p_typeID) - { - if (const auto container = m_assetContainers.find(p_typeID); container != m_assetContainers.end()) - { - return container->second; - } - - return nullptr; - } + AssetContainerBase* GetAssetContainer(const AssetTypeID p_typeID); /** * Get the AssetContainer for a given AssetType @@ -69,15 +61,25 @@ class AssetLibrary * \return The AssetContainer for the AssetType. Nullptr if not found */ [[nodiscard]] - const AssetContainerBase* GetAssetContainer(const AssetTypeID p_typeID) const - { - if (const auto container = m_assetContainers.find(p_typeID); container != m_assetContainers.end()) - { - return container->second; - } + const AssetContainerBase* GetAssetContainer(const AssetTypeID p_typeID) const; - return nullptr; - } + /** + * Get the AssetContainer for a given UUID + * + * \param p_uuid The asset + * \return The AssetContainer for the UUID. Nullptr if not found + */ + [[nodiscard]] + const AssetContainerBase* GetAssetContainer(const UUID& p_uuid) const; + + /** + * Get the AssetContainer for a given UUID + * + * \param p_uuid The asset + * \return The AssetContainer for the UUID. Nullptr if not found + */ + [[nodiscard]] + AssetContainerBase* GetAssetContainer(const UUID& p_uuid); AssetLibrary& operator=(const AssetLibrary& p_library) = default; AssetLibrary& operator=(AssetLibrary&& p_library) = delete; diff --git a/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp b/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp index 53d34e2..3225d18 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp @@ -9,9 +9,11 @@ #include #include +#include #include +#include #include #include @@ -61,7 +63,7 @@ class BigFile: public DataAccessor * Get an Asset flatbuffer * * \param p_uuid The asset to get the flatbuffer of - * \return The flatbuffer, or nullopt if the asset was not found + * \return The flatbuffer, or an empty vector if the asset was not found */ [[nodiscard]] eastl::vector GetAssetFlatbuffer(const UUID& p_uuid) const override; @@ -75,24 +77,6 @@ class BigFile: public DataAccessor [[nodiscard]] eastl::vector> GetAssetFlatbuffers(eastl::span p_uuids) const override; - /** - * Get an Asset metadata - * - * \param p_uuid The asset to get the metadata of - * \return The metadata, or nullopt if the asset was not found - */ - [[nodiscard]] - AssetMetadata GetAssetMetadata(const UUID& p_uuid) const override; - - /** - * Get several Asset metadatas - * - * \param p_uuids The assets to get the metadatas of - * \return The metadatas that were found - */ - [[nodiscard]] - eastl::vector GetAssetMetadatas(eastl::span p_uuids) const override; - /** * Get the HardReferences of a given asset * @@ -111,27 +95,54 @@ class BigFile: public DataAccessor [[nodiscard]] eastl::vector> GetAssetsHardReferences(eastl::span p_uuids) const override; + struct AssetTime + { + Time m_creationTime; + Time m_modificationTime; + + [[nodiscard]] + bool operator==(const AssetTime& p_other) const = default; + }; + + /** + * Get the creation and modification time of an asset + * + * \param p_uuid The asset to get the time of + * \return The time of the asset, nullopt if the asset was not found + */ + [[nodiscard]] + eastl::optional GetAssetTime(const UUID& p_uuid) const; + + /** + * Get the creation and modification time of several assets + * + * \param p_uuids The assets to get the time of + * \return The time of the assets. nullopt for assets not found + */ + [[nodiscard]] + eastl::vector> GetAssetsTime(eastl::span p_uuids) const; + /** * Save an asset * - * \p_metadata The metadata - * \p_flatbuffer The flatbuffer of the asset + * \param p_uuid The UUID + * \param p_flatbuffer The flatbuffer of the asset * \param p_hardReferences The HardReferences the asset points to */ - void SaveAssetFlatbuffer(const AssetMetadata& p_metadata, + void SaveAssetFlatbuffer(const UUID& p_uuid, const eastl::span p_flatbuffer, const eastl::span p_hardReferences) override; /** * Save several assets * - * \p_metadatas The metadatas - * \p_flatbuffers The flatbuffers of the assets, matching p_metadatas by index + * \param p_uuids The UUIDs + * \param p_flatbuffers The flatbuffers of the assets, matching p_metadatas by index * \param p_hardReferences The HardReferences the asset points to */ - void SaveAssetFlatbuffers(eastl::span p_metadatas, - eastl::span> p_flatbuffers, - const eastl::span> p_uuids) override; + void SaveAssetFlatbuffers(const eastl::span p_uuids, + const eastl::span> p_flatbuffers, + const eastl::span> p_hardReferences) override; /** * Check if the Asset exists diff --git a/Bigfoot/Sources/Engine/Include/Engine/DataAccessor/DataAccessor.hpp b/Bigfoot/Sources/Engine/Include/Engine/DataAccessor/DataAccessor.hpp index 5ea16f5..a9ddf40 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/DataAccessor/DataAccessor.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/DataAccessor/DataAccessor.hpp @@ -17,18 +17,6 @@ namespace Bigfoot { -struct AssetMetadata -{ - UUID m_uuid = UUID::NULL_UUID; - eastl::string m_name {}; - - AssetTypeID m_typeID = 0; - eastl::string m_typeName {}; - - Time m_creationTime = 0; - Time m_modificationTime = 0; -}; - class DataAccessor { public: @@ -43,7 +31,7 @@ class DataAccessor * Get an Asset flatbuffer * * \param p_uuid The asset to get the flatbuffer of - * \return The flatbuffer, or nullopt if the asset was not found + * \return The flatbuffer, or an empty vector if the asset was not found */ [[nodiscard]] virtual eastl::vector GetAssetFlatbuffer(const UUID& p_uuid) const = 0; @@ -57,24 +45,6 @@ class DataAccessor [[nodiscard]] virtual eastl::vector> GetAssetFlatbuffers(eastl::span p_uuids) const = 0; - /** - * Get an Asset metadata - * - * \param p_uuid The asset to get the metadata of - * \return The metadata, or nullopt if the asset was not found - */ - [[nodiscard]] - virtual AssetMetadata GetAssetMetadata(const UUID& p_uuid) const = 0; - - /** - * Get several Asset metadatas - * - * \param p_uuids The assets to get the metadatas of - * \return The metadatas that were found - */ - [[nodiscard]] - virtual eastl::vector GetAssetMetadatas(eastl::span p_uuids) const = 0; - /** * Get the HardReferences of a given asset * @@ -96,24 +66,24 @@ class DataAccessor /** * Save an asset * - * \p_metadata The metadata - * \p_flatbuffer The flatbuffer of the asset + * \param p_uuid The UUID + * \param p_flatbuffer The flatbuffer of the asset * \param p_hardReferences The HardReferences the asset points to */ - virtual void SaveAssetFlatbuffer(const AssetMetadata& p_metadata, + virtual void SaveAssetFlatbuffer(const UUID& p_uuid, const eastl::span p_flatbuffer, const eastl::span p_hardReferences) = 0; /** * Save several assets * - * \p_metadatas The metadatas - * \p_flatbuffers The flatbuffers of the assets, matching p_metadatas by index + * \param p_uuids The UUIDs + * \param p_flatbuffers The flatbuffers of the assets, matching p_metadatas by index * \param p_hardReferences The HardReferences the asset points to */ - virtual void SaveAssetFlatbuffers(eastl::span p_metadatas, - eastl::span> p_flatbuffers, - const eastl::span> p_uuids) = 0; + virtual void SaveAssetFlatbuffers(const eastl::span p_uuids, + const eastl::span> p_flatbuffers, + const eastl::span> p_hardReferences) = 0; /** * Check if the Asset exists diff --git a/Bigfoot/Sources/Engine/Include/Engine/Sasquatch/Sasquatch.hpp b/Bigfoot/Sources/Engine/Include/Engine/Sasquatch/Sasquatch.hpp index 5108c06..674d8ed 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Sasquatch/Sasquatch.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Sasquatch/Sasquatch.hpp @@ -146,7 +146,7 @@ class Sasquatch: public DataAccessor * Get an Asset flatbuffer * * \param p_uuid The asset to get the flatbuffer of - * \return The flatbuffer, or nullopt if the asset was not found + * \return The flatbuffer, or an empty vector if the asset was not found */ [[nodiscard]] eastl::vector GetAssetFlatbuffer(const UUID& p_uuid) const override; @@ -160,20 +160,6 @@ class Sasquatch: public DataAccessor [[nodiscard]] eastl::vector> GetAssetFlatbuffers(eastl::span p_uuids) const override; - /** - * Sasquatch only serves flatbuffers: this will always fail - * - */ - [[nodiscard]] - AssetMetadata GetAssetMetadata(const UUID& p_uuid) const override; - - /** - * Sasquatch only serves flatbuffers: this will always fail - * - */ - [[nodiscard]] - eastl::vector GetAssetMetadatas(eastl::span p_uuids) const override; - /** * Get the HardReferences of a given asset * @@ -196,7 +182,7 @@ class Sasquatch: public DataAccessor * Sasquatch is read-only: this will always fail * */ - void SaveAssetFlatbuffer(const AssetMetadata& p_metadata, + void SaveAssetFlatbuffer(const UUID& p_uuid, eastl::span p_flatbuffer, eastl::span p_hardReferences) override; @@ -204,7 +190,7 @@ class Sasquatch: public DataAccessor * Sasquatch is read-only: this will always fail * */ - void SaveAssetFlatbuffers(eastl::span p_metadatas, + void SaveAssetFlatbuffers(const eastl::span p_uuids, eastl::span> p_flatbuffers, eastl::span> p_hardReferences) override; diff --git a/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp b/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp index 85ce888..2f5aad5 100644 --- a/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp +++ b/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp @@ -201,22 +201,6 @@ eastl::vector> Sasquatch::GetAssetFlatbuffers(const eas /****************************************************************************************/ -AssetMetadata Sasquatch::GetAssetMetadata([[maybe_unused]] const UUID& p_uuid) const -{ - ASSERT(EngineAssertHandler, false, "Sasquatch does not support metadata queries, only flatbuffers"); - return {}; -} - -/****************************************************************************************/ - -eastl::vector Sasquatch::GetAssetMetadatas([[maybe_unused]] const eastl::span p_uuids) const -{ - ASSERT(EngineAssertHandler, false, "Sasquatch does not support metadata queries, only flatbuffers"); - return eastl::vector {p_uuids.size()}; -} - -/****************************************************************************************/ - eastl::vector Sasquatch::GetAssetHardReferences(const UUID& p_uuid) const { eastl::vector hardReferences; @@ -261,7 +245,7 @@ eastl::vector> Sasquatch::GetAssetsHardReferences(eastl::spa /****************************************************************************************/ -void Sasquatch::SaveAssetFlatbuffer([[maybe_unused]] const AssetMetadata& p_metadata, +void Sasquatch::SaveAssetFlatbuffer([[maybe_unused]] const UUID& p_uuid, [[maybe_unused]] eastl::span p_flatbuffer, [[maybe_unused]] eastl::span p_hardReferences) { @@ -270,7 +254,7 @@ void Sasquatch::SaveAssetFlatbuffer([[maybe_unused]] const AssetMetadata& p_meta /****************************************************************************************/ -void Sasquatch::SaveAssetFlatbuffers([[maybe_unused]] eastl::span p_metadatas, +void Sasquatch::SaveAssetFlatbuffers([[maybe_unused]] const eastl::span p_uuids, [[maybe_unused]] eastl::span> p_flatbuffers, [[maybe_unused]] eastl::span> p_hardReferences) { diff --git a/Bigfoot/Tests/Engine/Asset/Asset.cpp b/Bigfoot/Tests/Engine/Asset/Asset.cpp index e867aec..75defc2 100644 --- a/Bigfoot/Tests/Engine/Asset/Asset.cpp +++ b/Bigfoot/Tests/Engine/Asset/Asset.cpp @@ -112,7 +112,7 @@ TEST_F(AssetFixture, PackThenUnpack_ShouldRoundTripTheHeaderAndTheAsset) TEST_F(AssetFixture, GetHardReferences_ShouldReturnTheHardReferencesOfTheAsset) { - const eastl::vector hardReferences = AssetC::GetHardReferences(m_assetC.Pack()); + const eastl::vector hardReferences = m_assetC.GetHardReferences(m_assetC.Pack()); EXPECT_EQ(hardReferences.size(), 2); EXPECT_TRUE(std::find(hardReferences.begin(), hardReferences.end(), m_assetA.GetHeader().uuid) != diff --git a/Bigfoot/Tests/Engine/Asset/AssetContainer.cpp b/Bigfoot/Tests/Engine/Asset/AssetContainer.cpp index 6f99543..51898d0 100644 --- a/Bigfoot/Tests/Engine/Asset/AssetContainer.cpp +++ b/Bigfoot/Tests/Engine/Asset/AssetContainer.cpp @@ -17,17 +17,13 @@ class ContainerHandleFixture: public ::testing::Test protected: void SetUp() override { - const auto key = m_containerA.Insert(); - - m_uuid = m_containerA.Get(key)->GetHeader().uuid; - - m_handle = m_containerA.AcquireContainerHandle(m_uuid); + m_handle = m_containerA.Insert(); + m_uuid = m_handle->GetAsset()->GetHeader().uuid; } AssetContainer m_containerA; UUID m_uuid; - ContainerHandle* m_handle; }; @@ -98,8 +94,8 @@ class AssetContainerFixture: public ::testing::Test TEST_F(AssetContainerFixture, Has_ShouldReturnTrueIfTheContainerHasTheAsset) { - const auto key = m_containerA.Insert(); - EXPECT_TRUE(m_containerA.Has(m_containerA.Get(key)->GetHeader().uuid)); + const ContainerHandle* handle = m_containerA.Insert(); + EXPECT_TRUE(m_containerA.Has(handle->GetAsset()->GetHeader().uuid)); } /****************************************************************************************/ @@ -113,11 +109,10 @@ TEST_F(AssetContainerFixture, Has_ShouldReturnFalseIfTheContainerDoesNotHaveTheA TEST_F(AssetContainerFixture, AcquireHandle_ShouldReturnTheAssociatedContainerHandle) { - const auto key = m_containerA.Insert(); + const ContainerHandle* handle = m_containerA.Insert(); + const UUID uuid = handle->GetAsset()->GetHeader().uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(m_containerA.Get(key)->GetHeader().uuid); - EXPECT_EQ(static_cast(handle->GetAsset())->GetHeader().uuid, - m_containerA.Get(key)->GetHeader().uuid); + EXPECT_EQ(m_containerA.AcquireContainerHandle(uuid), handle); } /****************************************************************************************/ @@ -130,53 +125,23 @@ TEST_F(AssetContainerFixture, AcquireHandle_ShouldCreateTheAssociatedContainerHa /****************************************************************************************/ -TEST_F(AssetContainerFixture, Insert_ShouldReturnValidAndUniqueSlotKeyOnInsert) +TEST_F(AssetContainerFixture, Insert_ShouldReturnAHandleWithTheInsertedAsset) { - const SlotMapKey slotKey = m_containerA.Insert(); - EXPECT_TRUE(slotKey.Valid()); - EXPECT_NE(slotKey, m_containerA.Insert()); -} - -/****************************************************************************************/ - -TEST_F(AssetContainerFixture, Insert_ShouldReturnTheSameSlotKeyInCaseOfDuplicatedUUID) -{ - const SlotMapKey slotKey = m_containerA.Insert(); - - AssetA duplicate; - duplicate.Unpack(m_containerA.Get(slotKey)->Pack()); - - EXPECT_EQ(slotKey, m_containerA.Insert(std::move(duplicate))); -} - -/****************************************************************************************/ - -TEST_F(AssetContainerFixture, Get_ShouldReturnTheAssetWithTheSlotKey) -{ - const SlotMapKey slotKey = m_containerA.Insert(); - - EXPECT_NE(m_containerA.Get(slotKey), nullptr); - EXPECT_NE(std::as_const(m_containerA).Get(slotKey), nullptr); -} - -/****************************************************************************************/ - -TEST_F(AssetContainerFixture, Get_ShouldReturnNullptrIfSlotKeyNotInContainer) -{ - EXPECT_EQ(m_containerA.Get(SlotMapKey<> {1, 0}), nullptr); - EXPECT_EQ(std::as_const(m_containerA).Get(SlotMapKey<> {1, 0}), nullptr); + const ContainerHandle* handle = m_containerA.Insert(); + EXPECT_NE(handle, nullptr); + EXPECT_NE(handle->GetAsset(), nullptr); } /****************************************************************************************/ TEST_F(AssetContainerFixture, Remove_ShouldRemoveTheAsset) { - const SlotMapKey slotKey = m_containerA.Insert(); - const UUID uuid = m_containerA.Get(slotKey)->GetHeader().uuid; + const ContainerHandle* handle = m_containerA.Insert(); + const UUID uuid = handle->GetAsset()->GetHeader().uuid; m_containerA.Remove(uuid); - EXPECT_EQ(m_containerA.Get(slotKey), nullptr); + EXPECT_EQ(handle->GetAsset(), nullptr); EXPECT_FALSE(m_containerA.Has(uuid)); } } // namespace Bigfoot diff --git a/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp b/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp index d7d1901..3bdbcfa 100644 --- a/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp +++ b/Bigfoot/Tests/Engine/Asset/AssetLibrary.cpp @@ -73,6 +73,32 @@ TEST_F(AssetLibraryFixture, GetAssetContainer_ShouldReturnNullptrIfTheContainerD /****************************************************************************************/ +TEST_F(AssetLibraryFixture, GetAssetContainer_ShouldReturnTheContainerThatHasTheAsset) +{ + std::ignore = m_library.Insert(&m_containerA); + std::ignore = m_library.Insert(&m_containerB); + + const UUID uuid = m_containerB.Insert()->GetAsset()->GetHeader().uuid; + + EXPECT_EQ(m_library.GetAssetContainer(uuid), &m_containerB); + EXPECT_EQ(std::as_const(m_library).GetAssetContainer(uuid), &m_containerB); +} + +/****************************************************************************************/ + +TEST_F(AssetLibraryFixture, GetAssetContainer_ShouldReturnNullptrIfNoContainerHasTheAsset) +{ + std::ignore = m_library.Insert(&m_containerA); + std::ignore = m_library.Insert(&m_containerB); + + const UUID uuid; + + EXPECT_EQ(m_library.GetAssetContainer(uuid), nullptr); + EXPECT_EQ(std::as_const(m_library).GetAssetContainer(uuid), nullptr); +} + +/****************************************************************************************/ + TEST_F(AssetLibraryFixture, SetActiveAssetLibrary_ShouldSetTheActiveAssetLibraryToTheGivenLibrary) { SetActiveAssetLibrary(&m_library); diff --git a/Bigfoot/Tests/Engine/Asset/Reference.cpp b/Bigfoot/Tests/Engine/Asset/Reference.cpp index 524dc14..b3de0b5 100644 --- a/Bigfoot/Tests/Engine/Asset/Reference.cpp +++ b/Bigfoot/Tests/Engine/Asset/Reference.cpp @@ -1,26 +1,49 @@ /********************************************************************* - * \file AssetLibrary.cpp + * \file Reference.cpp * * \author Romain BOULLARD - * \date July 2026 + * \date August 2026 *********************************************************************/ +#include + #include #include -#include -#include #include namespace Bigfoot { -class HardReferenceFixture: public ::testing::Test +template +struct RefCountTraits; + +template<> +struct RefCountTraits> +{ + [[nodiscard]] + static std::uint32_t Get(const ContainerHandle* p_handle) + { + return p_handle->GetHardRefCount(); + } +}; + +template<> +struct RefCountTraits> +{ + [[nodiscard]] + static std::uint32_t Get(const ContainerHandle* p_handle) + { + return p_handle->GetSoftRefCount(); + } +}; + +template +class ReferenceFixture: public ::testing::Test { protected: void SetUp() override { SetActiveAssetLibrary(&m_library); - std::ignore = m_library.Insert(&m_containerA); } @@ -29,452 +52,244 @@ class HardReferenceFixture: public ::testing::Test SetActiveAssetLibrary(&g_assetLibrary); } - AssetContainer m_containerA; - - AssetLibrary m_library; -}; - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, GetUUID_ShouldReturnTheUUID) -{ - UUID uuid; - HardReference hardRef {uuid}; - - EXPECT_EQ(hardRef.GetUUID(), uuid); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, Get_ShouldReturnTheAsset) -{ - const auto key = m_containerA.Insert(); - const UUID uuid = m_containerA.Get(key)->GetHeader().uuid; - - HardReference hardRef {uuid}; - - EXPECT_EQ(hardRef.Get(), m_containerA.Get(key)); - EXPECT_EQ(std::as_const(hardRef).Get(), std::as_const(m_containerA).Get(key)); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, Get_ShouldReturnNullptrIfTheAssetDoesNotExist) -{ - UUID uuid; - HardReference hardRef {uuid}; - - EXPECT_EQ(hardRef.Get(), nullptr); - EXPECT_EQ(std::as_const(hardRef).Get(), nullptr); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, Get_ShouldReturnNullptrAfterTheAssetIsRemovedFromTheContainer) -{ - const auto key = m_containerA.Insert(); - const UUID uuid = m_containerA.Get(key)->GetHeader().uuid; - - HardReference hardRef {uuid}; - - m_containerA.Remove(uuid); - - EXPECT_EQ(hardRef.Get(), nullptr); - EXPECT_EQ(std::as_const(hardRef).Get(), nullptr); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, ShouldTouchTheHardRefCountOfTheHandle) -{ - UUID uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid); - - EXPECT_EQ(handle->GetHardRefCount(), 0); - + [[nodiscard]] + static std::uint32_t GetRefCount(const ContainerHandle* p_handle) { - HardReference hardRef1 {uuid}; - EXPECT_EQ(handle->GetHardRefCount(), 1); - { - HardReference hardRef2 {uuid}; - EXPECT_EQ(handle->GetHardRefCount(), 2); - } - EXPECT_EQ(handle->GetHardRefCount(), 1); - } - - EXPECT_EQ(handle->GetHardRefCount(), 0); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, CopyConstructor_ShouldIncrementTheHardRefCountAndCopyTheState) -{ - const auto key = m_containerA.Insert(); - const UUID uuid = m_containerA.Get(key)->GetHeader().uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid); - - HardReference hardRef1 {uuid}; - EXPECT_EQ(handle->GetHardRefCount(), 1); - - HardReference hardRef2 {hardRef1}; - - EXPECT_EQ(handle->GetHardRefCount(), 2); - EXPECT_EQ(hardRef2.GetUUID(), uuid); - EXPECT_EQ(hardRef2.Get(), m_containerA.Get(key)); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, MoveConstructor_ShouldTransferTheStateWithoutChangingTheHardRefCount) -{ - const auto key = m_containerA.Insert(); - const UUID uuid = m_containerA.Get(key)->GetHeader().uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid); - - HardReference hardRef1 {uuid}; - EXPECT_EQ(handle->GetHardRefCount(), 1); - - HardReference hardRef2 {std::move(hardRef1)}; - - EXPECT_EQ(handle->GetHardRefCount(), 1); - EXPECT_EQ(hardRef2.GetUUID(), uuid); - EXPECT_EQ(hardRef2.Get(), m_containerA.Get(key)); - EXPECT_EQ(hardRef1.GetUUID(), UUID::NULL_UUID); - EXPECT_EQ(hardRef1.Get(), nullptr); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, CopyAssignment_ShouldReleaseThePreviousHandleAndAcquireTheNewOne) -{ - UUID uuidA; - UUID uuidB; - const ContainerHandle* handleA = m_containerA.AcquireContainerHandle(uuidA); - const ContainerHandle* handleB = m_containerA.AcquireContainerHandle(uuidB); - - HardReference hardRefA {uuidA}; - HardReference hardRefB {uuidB}; - EXPECT_EQ(handleA->GetHardRefCount(), 1); - EXPECT_EQ(handleB->GetHardRefCount(), 1); - - hardRefB = hardRefA; - - EXPECT_EQ(handleA->GetHardRefCount(), 2); - EXPECT_EQ(handleB->GetHardRefCount(), 0); - EXPECT_EQ(hardRefB.GetUUID(), uuidA); - EXPECT_EQ(hardRefB.Get(), hardRefA.Get()); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, CopyAssignment_SelfAssignment_ShouldNotChangeTheHardRefCount) -{ - UUID uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid); - - HardReference hardRef {uuid}; - EXPECT_EQ(handle->GetHardRefCount(), 1); - - HardReference* selfPtr = &hardRef; - hardRef = *selfPtr; - - EXPECT_EQ(handle->GetHardRefCount(), 1); - EXPECT_EQ(hardRef.GetUUID(), uuid); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, MoveAssignment_ShouldReleaseThePreviousHandleAndTransferTheNewOne) -{ - UUID uuidA; - UUID uuidB; - const ContainerHandle* handleA = m_containerA.AcquireContainerHandle(uuidA); - const ContainerHandle* handleB = m_containerA.AcquireContainerHandle(uuidB); - - HardReference hardRefA {uuidA}; - HardReference hardRefB {uuidB}; - EXPECT_EQ(handleA->GetHardRefCount(), 1); - EXPECT_EQ(handleB->GetHardRefCount(), 1); - - hardRefB = std::move(hardRefA); - - EXPECT_EQ(handleA->GetHardRefCount(), 1); - EXPECT_EQ(handleB->GetHardRefCount(), 0); - EXPECT_EQ(hardRefB.GetUUID(), uuidA); - EXPECT_EQ(hardRefA.GetUUID(), UUID::NULL_UUID); - EXPECT_EQ(hardRefA.Get(), nullptr); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, MoveAssignment_SelfAssignment_ShouldNotChangeTheHardRefCount) -{ - UUID uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid); - - HardReference hardRef {uuid}; - EXPECT_EQ(handle->GetHardRefCount(), 1); - - HardReference* selfPtr = &hardRef; - hardRef = std::move(*selfPtr); - - EXPECT_EQ(handle->GetHardRefCount(), 1); - EXPECT_EQ(hardRef.GetUUID(), uuid); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, EqualityOperator_ShouldReturnTrueForReferencesWithTheSameUUID) -{ - UUID uuid; - HardReference hardRef1 {uuid}; - HardReference hardRef2 {uuid}; - - EXPECT_EQ(hardRef1, hardRef2); -} - -/****************************************************************************************/ - -TEST_F(HardReferenceFixture, EqualityOperator_ShouldReturnFalseForReferencesWithDifferentUUIDs) -{ - UUID uuid1; - UUID uuid2; - HardReference hardRef1 {uuid1}; - HardReference hardRef2 {uuid2}; - - EXPECT_NE(hardRef1, hardRef2); -} - -/****************************************************************************************/ - -class SoftReferenceFixture: public ::testing::Test -{ - protected: - void SetUp() override - { - SetActiveAssetLibrary(&m_library); - - std::ignore = m_library.Insert(&m_containerA); - } - - void TearDown() override - { - SetActiveAssetLibrary(&g_assetLibrary); + return RefCountTraits::Get(p_handle); } AssetContainer m_containerA; - AssetLibrary m_library; }; +class ReferenceTypeNameGenerator +{ + public: + template + static std::string GetName(int) + { + if constexpr (std::is_same_v>) + { + return "HardReference"; + } + if constexpr (std::is_same_v>) + { + return "SoftReference"; + } + } +}; + +using ReferenceTypes = ::testing::Types, SoftReference>; +TYPED_TEST_SUITE(ReferenceFixture, ReferenceTypes, ReferenceTypeNameGenerator); + /****************************************************************************************/ -TEST_F(SoftReferenceFixture, GetUUID_ShouldReturnTheUUID) +TYPED_TEST(ReferenceFixture, GetUUID_ShouldReturnTheUUID) { UUID uuid; - SoftReference hardRef {uuid}; + TypeParam ref {uuid}; - EXPECT_EQ(hardRef.GetUUID(), uuid); + EXPECT_EQ(ref.GetUUID(), uuid); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, Get_ShouldReturnTheAsset) +TYPED_TEST(ReferenceFixture, Get_ShouldReturnTheAsset) { - const auto key = m_containerA.Insert(); - const UUID uuid = m_containerA.Get(key)->GetHeader().uuid; + const AssetA* inserted = static_cast(this->m_containerA.Insert()->GetAsset()); + const UUID uuid = inserted->GetHeader().uuid; - SoftReference hardRef {uuid}; + TypeParam ref {uuid}; - EXPECT_EQ(hardRef.Get(), m_containerA.Get(key)); - EXPECT_EQ(std::as_const(hardRef).Get(), std::as_const(m_containerA).Get(key)); + EXPECT_EQ(ref.Get(), inserted); + EXPECT_EQ(std::as_const(ref).Get(), inserted); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, Get_ShouldReturnNullptrIfTheAssetDoesNotExist) +TYPED_TEST(ReferenceFixture, Get_ShouldReturnNullptrIfTheAssetDoesNotExist) { UUID uuid; - SoftReference hardRef {uuid}; + TypeParam ref {uuid}; - EXPECT_EQ(hardRef.Get(), nullptr); - EXPECT_EQ(std::as_const(hardRef).Get(), nullptr); + EXPECT_EQ(ref.Get(), nullptr); + EXPECT_EQ(std::as_const(ref).Get(), nullptr); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, Get_ShouldReturnNullptrAfterTheAssetIsRemovedFromTheContainer) +TYPED_TEST(ReferenceFixture, Get_ShouldReturnNullptrAfterTheAssetIsRemovedFromTheContainer) { - const auto key = m_containerA.Insert(); - const UUID uuid = m_containerA.Get(key)->GetHeader().uuid; + const AssetA* inserted = static_cast(this->m_containerA.Insert()->GetAsset()); + const UUID uuid = inserted->GetHeader().uuid; - SoftReference hardRef {uuid}; + TypeParam ref {uuid}; - m_containerA.Remove(uuid); + this->m_containerA.Remove(uuid); - EXPECT_EQ(hardRef.Get(), nullptr); - EXPECT_EQ(std::as_const(hardRef).Get(), nullptr); + EXPECT_EQ(ref.Get(), nullptr); + EXPECT_EQ(std::as_const(ref).Get(), nullptr); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, ShouldTouchTheSoftRefCountOfTheHandle) +TYPED_TEST(ReferenceFixture, ShouldTouchTheRefCountOfTheHandle) { UUID uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid); + const ContainerHandle* handle = this->m_containerA.AcquireContainerHandle(uuid); - EXPECT_EQ(handle->GetSoftRefCount(), 0); + EXPECT_EQ(this->GetRefCount(handle), 0); { - SoftReference softRef1 {uuid}; - EXPECT_EQ(handle->GetSoftRefCount(), 1); + TypeParam ref1 {uuid}; + EXPECT_EQ(this->GetRefCount(handle), 1); { - SoftReference softRef2 {uuid}; - EXPECT_EQ(handle->GetSoftRefCount(), 2); + TypeParam ref2 {uuid}; + EXPECT_EQ(this->GetRefCount(handle), 2); } - EXPECT_EQ(handle->GetSoftRefCount(), 1); + EXPECT_EQ(this->GetRefCount(handle), 1); } - EXPECT_EQ(handle->GetSoftRefCount(), 0); + EXPECT_EQ(this->GetRefCount(handle), 0); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, CopyConstructor_ShouldIncrementTheSoftRefCountAndCopyTheState) +TYPED_TEST(ReferenceFixture, CopyConstructor_ShouldIncrementTheRefCountAndCopyTheState) { - const auto key = m_containerA.Insert(); - const UUID uuid = m_containerA.Get(key)->GetHeader().uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid); + const AssetA* inserted = static_cast(this->m_containerA.Insert()->GetAsset()); + const UUID uuid = inserted->GetHeader().uuid; + const ContainerHandle* handle = this->m_containerA.AcquireContainerHandle(uuid); - SoftReference softRef1 {uuid}; - EXPECT_EQ(handle->GetSoftRefCount(), 1); + TypeParam ref1 {uuid}; + EXPECT_EQ(this->GetRefCount(handle), 1); - SoftReference softRef2 {softRef1}; + TypeParam ref2 {ref1}; - EXPECT_EQ(handle->GetSoftRefCount(), 2); - EXPECT_EQ(softRef2.GetUUID(), uuid); - EXPECT_EQ(softRef2.Get(), m_containerA.Get(key)); + EXPECT_EQ(this->GetRefCount(handle), 2); + EXPECT_EQ(ref2.GetUUID(), uuid); + EXPECT_EQ(ref2.Get(), inserted); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, MoveConstructor_ShouldTransferTheStateWithoutChangingTheSoftRefCount) +TYPED_TEST(ReferenceFixture, MoveConstructor_ShouldTransferTheStateWithoutChangingTheRefCount) { - const auto key = m_containerA.Insert(); - const UUID uuid = m_containerA.Get(key)->GetHeader().uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid); + const AssetA* inserted = static_cast(this->m_containerA.Insert()->GetAsset()); + const UUID uuid = inserted->GetHeader().uuid; + const ContainerHandle* handle = this->m_containerA.AcquireContainerHandle(uuid); - SoftReference softRef1 {uuid}; - EXPECT_EQ(handle->GetSoftRefCount(), 1); + TypeParam ref1 {uuid}; + EXPECT_EQ(this->GetRefCount(handle), 1); - SoftReference softRef2 {std::move(softRef1)}; + TypeParam ref2 {std::move(ref1)}; - EXPECT_EQ(handle->GetSoftRefCount(), 1); - EXPECT_EQ(softRef2.GetUUID(), uuid); - EXPECT_EQ(softRef2.Get(), m_containerA.Get(key)); - EXPECT_EQ(softRef1.GetUUID(), UUID::NULL_UUID); - EXPECT_EQ(softRef1.Get(), nullptr); + EXPECT_EQ(this->GetRefCount(handle), 1); + EXPECT_EQ(ref2.GetUUID(), uuid); + EXPECT_EQ(ref2.Get(), inserted); + EXPECT_EQ(ref1.GetUUID(), UUID::NULL_UUID); + EXPECT_EQ(ref1.Get(), nullptr); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, CopyAssignment_ShouldReleaseThePreviousHandleAndAcquireTheNewOne) +TYPED_TEST(ReferenceFixture, CopyAssignment_ShouldReleaseThePreviousHandleAndAcquireTheNewOne) { UUID uuidA; UUID uuidB; - const ContainerHandle* handleA = m_containerA.AcquireContainerHandle(uuidA); - const ContainerHandle* handleB = m_containerA.AcquireContainerHandle(uuidB); + const ContainerHandle* handleA = this->m_containerA.AcquireContainerHandle(uuidA); + const ContainerHandle* handleB = this->m_containerA.AcquireContainerHandle(uuidB); - SoftReference softRefA {uuidA}; - SoftReference softRefB {uuidB}; - EXPECT_EQ(handleA->GetSoftRefCount(), 1); - EXPECT_EQ(handleB->GetSoftRefCount(), 1); + TypeParam refA {uuidA}; + TypeParam refB {uuidB}; + EXPECT_EQ(this->GetRefCount(handleA), 1); + EXPECT_EQ(this->GetRefCount(handleB), 1); - softRefB = softRefA; + refB = refA; - EXPECT_EQ(handleA->GetSoftRefCount(), 2); - EXPECT_EQ(handleB->GetSoftRefCount(), 0); - EXPECT_EQ(softRefB.GetUUID(), uuidA); - EXPECT_EQ(softRefB.Get(), softRefA.Get()); + EXPECT_EQ(this->GetRefCount(handleA), 2); + EXPECT_EQ(this->GetRefCount(handleB), 0); + EXPECT_EQ(refB.GetUUID(), uuidA); + EXPECT_EQ(refB.Get(), refA.Get()); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, CopyAssignment_SelfAssignment_ShouldNotChangeTheSoftRefCount) +TYPED_TEST(ReferenceFixture, CopyAssignment_SelfAssignment_ShouldNotChangeTheRefCount) { UUID uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid); + const ContainerHandle* handle = this->m_containerA.AcquireContainerHandle(uuid); - SoftReference softRef {uuid}; - EXPECT_EQ(handle->GetSoftRefCount(), 1); + TypeParam ref {uuid}; + EXPECT_EQ(this->GetRefCount(handle), 1); - SoftReference* selfPtr = &softRef; - softRef = *selfPtr; + TypeParam* selfPtr = &ref; + ref = *selfPtr; - EXPECT_EQ(handle->GetSoftRefCount(), 1); - EXPECT_EQ(softRef.GetUUID(), uuid); + EXPECT_EQ(this->GetRefCount(handle), 1); + EXPECT_EQ(ref.GetUUID(), uuid); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, MoveAssignment_ShouldReleaseThePreviousHandleAndTransferTheNewOne) +TYPED_TEST(ReferenceFixture, MoveAssignment_ShouldReleaseThePreviousHandleAndTransferTheNewOne) { UUID uuidA; UUID uuidB; - const ContainerHandle* handleA = m_containerA.AcquireContainerHandle(uuidA); - const ContainerHandle* handleB = m_containerA.AcquireContainerHandle(uuidB); + const ContainerHandle* handleA = this->m_containerA.AcquireContainerHandle(uuidA); + const ContainerHandle* handleB = this->m_containerA.AcquireContainerHandle(uuidB); - SoftReference softRefA {uuidA}; - SoftReference softRefB {uuidB}; - EXPECT_EQ(handleA->GetSoftRefCount(), 1); - EXPECT_EQ(handleB->GetSoftRefCount(), 1); + TypeParam refA {uuidA}; + TypeParam refB {uuidB}; + EXPECT_EQ(this->GetRefCount(handleA), 1); + EXPECT_EQ(this->GetRefCount(handleB), 1); - softRefB = std::move(softRefA); + refB = std::move(refA); - EXPECT_EQ(handleA->GetSoftRefCount(), 1); - EXPECT_EQ(handleB->GetSoftRefCount(), 0); - EXPECT_EQ(softRefB.GetUUID(), uuidA); - EXPECT_EQ(softRefA.GetUUID(), UUID::NULL_UUID); - EXPECT_EQ(softRefA.Get(), nullptr); + EXPECT_EQ(this->GetRefCount(handleA), 1); + EXPECT_EQ(this->GetRefCount(handleB), 0); + EXPECT_EQ(refB.GetUUID(), uuidA); + EXPECT_EQ(refA.GetUUID(), UUID::NULL_UUID); + EXPECT_EQ(refA.Get(), nullptr); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, MoveAssignment_SelfAssignment_ShouldNotChangeTheSoftRefCount) +TYPED_TEST(ReferenceFixture, MoveAssignment_SelfAssignment_ShouldNotChangeTheRefCount) { UUID uuid; - const ContainerHandle* handle = m_containerA.AcquireContainerHandle(uuid); + const ContainerHandle* handle = this->m_containerA.AcquireContainerHandle(uuid); - SoftReference softRef {uuid}; - EXPECT_EQ(handle->GetSoftRefCount(), 1); + TypeParam ref {uuid}; + EXPECT_EQ(this->GetRefCount(handle), 1); - SoftReference* selfPtr = &softRef; - softRef = std::move(*selfPtr); + TypeParam* selfPtr = &ref; + ref = std::move(*selfPtr); - EXPECT_EQ(handle->GetSoftRefCount(), 1); - EXPECT_EQ(softRef.GetUUID(), uuid); + EXPECT_EQ(this->GetRefCount(handle), 1); + EXPECT_EQ(ref.GetUUID(), uuid); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, EqualityOperator_ShouldReturnTrueForReferencesWithTheSameUUID) +TYPED_TEST(ReferenceFixture, EqualityOperator_ShouldReturnTrueForReferencesWithTheSameUUID) { UUID uuid; - SoftReference softRef1 {uuid}; - SoftReference softRef2 {uuid}; + TypeParam ref1 {uuid}; + TypeParam ref2 {uuid}; - EXPECT_EQ(softRef1, softRef2); + EXPECT_EQ(ref1, ref2); } /****************************************************************************************/ -TEST_F(SoftReferenceFixture, EqualityOperator_ShouldReturnFalseForReferencesWithDifferentUUIDs) +TYPED_TEST(ReferenceFixture, EqualityOperator_ShouldReturnFalseForReferencesWithDifferentUUIDs) { UUID uuid1; UUID uuid2; - SoftReference softRef1 {uuid1}; - SoftReference softRef2 {uuid2}; + TypeParam ref1 {uuid1}; + TypeParam ref2 {uuid2}; - EXPECT_NE(softRef1, softRef2); + EXPECT_NE(ref1, ref2); } } // namespace Bigfoot diff --git a/Bigfoot/Tests/Engine/BigFile/BigFile.cpp b/Bigfoot/Tests/Engine/BigFile/BigFile.cpp index 078e68c..ab08c24 100644 --- a/Bigfoot/Tests/Engine/BigFile/BigFile.cpp +++ b/Bigfoot/Tests/Engine/BigFile/BigFile.cpp @@ -31,6 +31,48 @@ class BigFileFixture: public ::testing::Test m_bigFile.Clear(); } + /* + * Packs an asset and saves it to the BigFile + * + * \param p_asset The asset to save + * \return The UUID the asset was saved under + */ + template + UUID SaveAsset(ASSET& p_asset) + { + const eastl::vector flatbuffer = p_asset.Pack(); + + m_bigFile.SaveAssetFlatbuffer(p_asset.GetHeader().uuid, flatbuffer, p_asset.GetHardReferences(flatbuffer)); + + return p_asset.GetHeader().uuid; + } + + /* + * Packs and saves several assets to the BigFile in a single SaveAssetFlatbuffers + * + * \param p_assets The assets to save + */ + void SaveAssets(const eastl::vector& p_assets) + { + eastl::vector uuids; + eastl::vector> flatbuffers; + eastl::vector> hardReferences; + + uuids.reserve(p_assets.size()); + flatbuffers.reserve(p_assets.size()); + hardReferences.reserve(p_assets.size()); + + for (AssetBase* const asset: p_assets) + { + eastl::vector flatbuffer = asset->Pack(); + hardReferences.push_back(asset->GetHardReferences(flatbuffer)); + uuids.push_back(asset->GetHeader().uuid); + flatbuffers.push_back(std::move(flatbuffer)); + } + + m_bigFile.SaveAssetFlatbuffers(uuids, flatbuffers, hardReferences); + } + BigFile m_bigFile {File {BIGFILE_ENGINETESTS_LOCATION}}; }; @@ -40,24 +82,12 @@ TEST_F(BigFileFixture, Clear_ShouldRemoveAllAssetsMetadataAndHardReferences) { AssetA referencedAsset; referencedAsset.SetName("referenced"); - const eastl::vector referencedFlatbuffer = referencedAsset.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = referencedAsset.GetHeader().uuid, - .m_name = referencedAsset.GetHeader().name, - .m_typeID = referencedAsset.GetHeader().type_id, - .m_typeName = referencedAsset.GetHeader().type_name}, - referencedFlatbuffer, - AssetA::GetHardReferences(referencedFlatbuffer)); + SaveAsset(referencedAsset); AssetB asset; asset.SetName("hello"); asset.GetAsset().ref_a = HardReference {referencedAsset.GetHeader().uuid}; - const eastl::vector flatbuffer = asset.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}, - flatbuffer, - AssetB::GetHardReferences(flatbuffer)); + SaveAsset(asset); ASSERT_TRUE(m_bigFile.Has(referencedAsset.GetHeader().uuid)); ASSERT_TRUE(m_bigFile.Has(asset.GetHeader().uuid)); @@ -68,9 +98,6 @@ TEST_F(BigFileFixture, Clear_ShouldRemoveAllAssetsMetadataAndHardReferences) EXPECT_FALSE(m_bigFile.Has(referencedAsset.GetHeader().uuid)); EXPECT_FALSE(m_bigFile.Has(asset.GetHeader().uuid)); - EXPECT_EQ(m_bigFile.GetAssetMetadata(referencedAsset.GetHeader().uuid).m_uuid, UUID::NULL_UUID); - EXPECT_EQ(m_bigFile.GetAssetMetadata(asset.GetHeader().uuid).m_uuid, UUID::NULL_UUID); - EXPECT_TRUE(m_bigFile.GetAssetFlatbuffer(referencedAsset.GetHeader().uuid).empty()); EXPECT_TRUE(m_bigFile.GetAssetFlatbuffer(asset.GetHeader().uuid).empty()); @@ -94,149 +121,61 @@ TEST_F(BigFileFixture, GetAssetFlatbuffer_ShouldGetTheAssetFlatbuffer) asset.SetName("hello"); asset.GetAsset().health = 42; asset.GetAsset().mana = 7; - const eastl::vector flatbuffer = asset.Pack(); + SaveAsset(asset); - const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}; - - m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer, AssetA::GetHardReferences(flatbuffer)); - - const eastl::optional> savedFlatbuffer = m_bigFile.GetAssetFlatbuffer( - asset.GetHeader().uuid); - ASSERT_TRUE(savedFlatbuffer.has_value()); - EXPECT_EQ(*savedFlatbuffer, flatbuffer); + const eastl::vector savedFlatbuffer = m_bigFile.GetAssetFlatbuffer(asset.GetHeader().uuid); + EXPECT_EQ(savedFlatbuffer, asset.Pack()); } /****************************************************************************************/ -TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldOmitUUIDsThatDoNotExist) +TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldReturnEmptyForUUIDsThatDoNotExist) { AssetA assetA; assetA.SetName("hello"); - const eastl::vector flatbufferA = assetA.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetA.GetHeader().uuid, - .m_name = assetA.GetHeader().name, - .m_typeID = assetA.GetHeader().type_id, - .m_typeName = assetA.GetHeader().type_name}, - flatbufferA, - AssetA::GetHardReferences(flatbufferA)); + SaveAsset(assetA); AssetA assetB; assetB.SetName("world"); - const eastl::vector flatbufferB = assetB.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetB.GetHeader().uuid, - .m_name = assetB.GetHeader().name, - .m_typeID = assetB.GetHeader().type_id, - .m_typeName = assetB.GetHeader().type_name}, - flatbufferB, - AssetA::GetHardReferences(flatbufferB)); + SaveAsset(assetB); const eastl::array uuids {assetA.GetHeader().uuid, UUID {}, assetB.GetHeader().uuid}; const eastl::vector> flatbuffers = m_bigFile.GetAssetFlatbuffers(uuids); - ASSERT_EQ(flatbuffers.size(), 2); - EXPECT_TRUE((flatbuffers[0] == flatbufferA && flatbuffers[1] == flatbufferB) || - (flatbuffers[0] == flatbufferB && flatbuffers[1] == flatbufferA)); + ASSERT_EQ(flatbuffers.size(), 3); + EXPECT_EQ(flatbuffers[0], assetA.Pack()); + EXPECT_TRUE(flatbuffers[1].empty()); + EXPECT_EQ(flatbuffers[2], assetB.Pack()); } /****************************************************************************************/ -TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldNotDuplicateResultsForADuplicateUUID) +TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldReturnEmptyForASingleUUIDThatDoesNotExist) +{ + const eastl::array uuids {UUID {}}; + + const eastl::vector> flatbuffers = m_bigFile.GetAssetFlatbuffers(uuids); + + ASSERT_EQ(flatbuffers.size(), 1); + EXPECT_TRUE(flatbuffers[0].empty()); +} + +/****************************************************************************************/ + +TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldDuplicateResultsForADuplicateUUID) { AssetA assetA; assetA.SetName("hello"); - const eastl::vector flatbufferA = assetA.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetA.GetHeader().uuid, - .m_name = assetA.GetHeader().name, - .m_typeID = assetA.GetHeader().type_id, - .m_typeName = assetA.GetHeader().type_name}, - flatbufferA, - AssetA::GetHardReferences(flatbufferA)); + SaveAsset(assetA); const eastl::array uuids {assetA.GetHeader().uuid, assetA.GetHeader().uuid}; const eastl::vector> flatbuffers = m_bigFile.GetAssetFlatbuffers(uuids); - ASSERT_EQ(flatbuffers.size(), 1); - EXPECT_EQ(flatbuffers[0], flatbufferA); -} - -/****************************************************************************************/ - -TEST_F(BigFileFixture, GetAssetMetadata_ShouldReturnNullForNonExistentUUID) -{ - const UUID uuid; - - EXPECT_EQ(m_bigFile.GetAssetMetadata(uuid).m_uuid, UUID::NULL_UUID); -} - -/****************************************************************************************/ - -TEST_F(BigFileFixture, GetAssetMetadata_ShouldGetTheAssetMetadata) -{ - AssetA asset; - asset.SetName("hello"); - asset.GetAsset().health = 42; - asset.GetAsset().mana = 7; - const eastl::vector flatbuffer = asset.Pack(); - - const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}; - - m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer, AssetA::GetHardReferences(flatbuffer)); - - const eastl::optional savedMetadata = m_bigFile.GetAssetMetadata(asset.GetHeader().uuid); - ASSERT_TRUE(savedMetadata.has_value()); - - EXPECT_EQ(savedMetadata->m_uuid, metadata.m_uuid); - EXPECT_EQ(savedMetadata->m_name, metadata.m_name); - EXPECT_EQ(savedMetadata->m_typeID, metadata.m_typeID); - EXPECT_EQ(savedMetadata->m_typeName, metadata.m_typeName); - EXPECT_GT(savedMetadata->m_creationTime, Time {0}); - EXPECT_GT(savedMetadata->m_modificationTime, Time {0}); -} - -/****************************************************************************************/ - -TEST_F(BigFileFixture, GetAssetMetadatas_ShouldOmitUUIDsThatDoNotExist) -{ - AssetA assetA; - assetA.SetName("hello"); - - const eastl::vector flatbufferA = assetA.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetA.GetHeader().uuid, - .m_name = assetA.GetHeader().name, - .m_typeID = assetA.GetHeader().type_id, - .m_typeName = assetA.GetHeader().type_name}, - flatbufferA, - AssetA::GetHardReferences(flatbufferA)); - - AssetA assetB; - assetB.SetName("world"); - - const eastl::vector flatbufferB = assetB.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetB.GetHeader().uuid, - .m_name = assetB.GetHeader().name, - .m_typeID = assetB.GetHeader().type_id, - .m_typeName = assetB.GetHeader().type_name}, - flatbufferB, - AssetA::GetHardReferences(flatbufferB)); - - const UUID missingUUID; - const eastl::array uuids {assetA.GetHeader().uuid, missingUUID, assetB.GetHeader().uuid}; - - const eastl::vector metadatas = m_bigFile.GetAssetMetadatas(uuids); - - ASSERT_EQ(metadatas.size(), 2); - EXPECT_TRUE((metadatas[0].m_uuid == assetA.GetHeader().uuid && metadatas[0].m_name == "hello" && - metadatas[1].m_uuid == assetB.GetHeader().uuid && metadatas[1].m_name == "world") || - (metadatas[0].m_uuid == assetB.GetHeader().uuid && metadatas[0].m_name == "world" && - metadatas[1].m_uuid == assetA.GetHeader().uuid && metadatas[1].m_name == "hello")); + ASSERT_EQ(flatbuffers.size(), 2); + EXPECT_EQ(flatbuffers[0], assetA.Pack()); + EXPECT_EQ(flatbuffers[1], assetA.Pack()); } /****************************************************************************************/ @@ -264,14 +203,7 @@ TEST_F(BigFileFixture, GetAssetHardReference_ShouldGetTheAssetHardReferences) asset.SetName("hello"); asset.GetAsset().ref_a = HardReference {referencedAssetX.GetHeader().uuid}; asset.GetAsset().refs_a.push_back(SoftReference {referencedAssetY.GetHeader().uuid}); - const eastl::vector flatbuffer = asset.Pack(); - - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}, - flatbuffer, - AssetB::GetHardReferences(flatbuffer)); + SaveAsset(asset); const eastl::vector hardReferences = m_bigFile.GetAssetHardReferences(asset.GetHeader().uuid); @@ -289,24 +221,12 @@ TEST_F(BigFileFixture, GetAssetHardReferences_ShouldReturnEmptyVectorsForUUIDsTh AssetA assetWithoutReferences; assetWithoutReferences.SetName("noRefs"); - const eastl::vector flatbufferWithoutReferences = assetWithoutReferences.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetWithoutReferences.GetHeader().uuid, - .m_name = assetWithoutReferences.GetHeader().name, - .m_typeID = assetWithoutReferences.GetHeader().type_id, - .m_typeName = assetWithoutReferences.GetHeader().type_name}, - flatbufferWithoutReferences, - AssetA::GetHardReferences(flatbufferWithoutReferences)); + SaveAsset(assetWithoutReferences); AssetB assetWithReferences; assetWithReferences.SetName("withRefs"); assetWithReferences.GetAsset().ref_a = HardReference {referencedAsset.GetHeader().uuid}; - const eastl::vector flatbufferWithReferences = assetWithReferences.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetWithReferences.GetHeader().uuid, - .m_name = assetWithReferences.GetHeader().name, - .m_typeID = assetWithReferences.GetHeader().type_id, - .m_typeName = assetWithReferences.GetHeader().type_name}, - flatbufferWithReferences, - AssetB::GetHardReferences(flatbufferWithReferences)); + SaveAsset(assetWithReferences); const UUID missingUUID; const eastl::array uuids {assetWithoutReferences.GetHeader().uuid, @@ -336,14 +256,7 @@ TEST_F(BigFileFixture, GetAssetHardReferences_ShouldDuplicateResultsForADuplicat asset.SetName("hello"); asset.GetAsset().ref_a = HardReference {referencedAssetX.GetHeader().uuid}; asset.GetAsset().refs_a.push_back(SoftReference {referencedAssetY.GetHeader().uuid}); - const eastl::vector flatbuffer = asset.Pack(); - - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}, - flatbuffer, - AssetB::GetHardReferences(flatbuffer)); + SaveAsset(asset); const eastl::array uuids {asset.GetHeader().uuid, asset.GetHeader().uuid}; @@ -359,6 +272,136 @@ TEST_F(BigFileFixture, GetAssetHardReferences_ShouldDuplicateResultsForADuplicat /****************************************************************************************/ +TEST_F(BigFileFixture, GetAssetTime_ShouldReturnNulloptForNonExistentUUID) +{ + const UUID uuid; + + EXPECT_FALSE(m_bigFile.GetAssetTime(uuid).has_value()); +} + +/****************************************************************************************/ + +TEST_F(BigFileFixture, GetAssetTime_ShouldReturnCreationAndModificationTimeOnFirstSave) +{ + AssetA asset; + asset.SetName("hello"); + + const std::uint64_t beforeSave = Time::Now().GetEpoch(); + SaveAsset(asset); + + const eastl::optional assetTime = m_bigFile.GetAssetTime(asset.GetHeader().uuid); + ASSERT_TRUE(assetTime.has_value()); + + constexpr std::uint64_t TOLERANCE_MICROSECONDS = 1'000'000; + const std::uint64_t creationEpoch = assetTime->m_creationTime.GetEpoch(); + const std::uint64_t delta = creationEpoch > beforeSave ? creationEpoch - beforeSave : beforeSave - creationEpoch; + EXPECT_LE(delta, TOLERANCE_MICROSECONDS); + EXPECT_EQ(assetTime->m_creationTime, assetTime->m_modificationTime); +} + +/****************************************************************************************/ + +TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldUpdateModificationTimeButNotCreationTimeOnSecondSave) +{ + AssetA asset; + asset.SetName("hello"); + SaveAsset(asset); + + const eastl::optional firstAssetTime = m_bigFile.GetAssetTime(asset.GetHeader().uuid); + ASSERT_TRUE(firstAssetTime.has_value()); + + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + + asset.GetAsset().health = 42; + SaveAsset(asset); + + const eastl::optional secondAssetTime = m_bigFile.GetAssetTime(asset.GetHeader().uuid); + ASSERT_TRUE(secondAssetTime.has_value()); + + EXPECT_EQ(secondAssetTime->m_creationTime, firstAssetTime->m_creationTime); + EXPECT_GT(secondAssetTime->m_modificationTime.GetEpoch(), firstAssetTime->m_modificationTime.GetEpoch()); +} + +/****************************************************************************************/ + +TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldUpdateModificationTimeButNotCreationTimeOnSecondSave) +{ + AssetA asset; + asset.SetName("hello"); + SaveAssets({&asset}); + + const eastl::optional firstAssetTime = m_bigFile.GetAssetTime(asset.GetHeader().uuid); + ASSERT_TRUE(firstAssetTime.has_value()); + + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + + asset.GetAsset().health = 42; + SaveAssets({&asset}); + + const eastl::optional secondAssetTime = m_bigFile.GetAssetTime(asset.GetHeader().uuid); + ASSERT_TRUE(secondAssetTime.has_value()); + + EXPECT_EQ(secondAssetTime->m_creationTime, firstAssetTime->m_creationTime); + EXPECT_GT(secondAssetTime->m_modificationTime.GetEpoch(), firstAssetTime->m_modificationTime.GetEpoch()); +} + +/****************************************************************************************/ + +TEST_F(BigFileFixture, GetAssetsTime_ShouldReturnNulloptForUUIDsThatDoNotExist) +{ + AssetA asset; + asset.SetName("hello"); + SaveAsset(asset); + + const UUID missingUUID; + const eastl::array uuids {asset.GetHeader().uuid, missingUUID}; + + const eastl::vector> times = m_bigFile.GetAssetsTime(uuids); + + ASSERT_EQ(times.size(), 2); + EXPECT_TRUE(times[0].has_value()); + EXPECT_FALSE(times[1].has_value()); +} + +/****************************************************************************************/ + +TEST_F(BigFileFixture, GetAssetsTime_ShouldDuplicateResultsForADuplicateUUID) +{ + AssetA asset; + asset.SetName("hello"); + SaveAsset(asset); + + const eastl::optional expected = m_bigFile.GetAssetTime(asset.GetHeader().uuid); + ASSERT_TRUE(expected.has_value()); + + const eastl::array uuids {asset.GetHeader().uuid, asset.GetHeader().uuid}; + + const eastl::vector> times = m_bigFile.GetAssetsTime(uuids); + + ASSERT_EQ(times.size(), 2); + ASSERT_TRUE(times[0].has_value()); + ASSERT_TRUE(times[1].has_value()); + EXPECT_EQ(*times[0], *expected); + EXPECT_EQ(*times[1], *expected); +} + +/****************************************************************************************/ + +TEST_F(BigFileFixture, Clear_ShouldRemoveAssetTime) +{ + AssetA asset; + asset.SetName("hello"); + SaveAsset(asset); + + ASSERT_TRUE(m_bigFile.GetAssetTime(asset.GetHeader().uuid).has_value()); + + m_bigFile.Clear(); + + EXPECT_FALSE(m_bigFile.GetAssetTime(asset.GetHeader().uuid).has_value()); +} + +/****************************************************************************************/ + TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldSaveTheAsset) { AssetA referencedAsset; @@ -367,14 +410,7 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldSaveTheAsset) AssetB asset; asset.SetName("hello"); asset.GetAsset().ref_a = HardReference {referencedAsset.GetHeader().uuid}; - const eastl::vector flatbuffer = asset.Pack(); - - const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}; - - m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer, AssetB::GetHardReferences(flatbuffer)); + SaveAsset(asset); EXPECT_TRUE(m_bigFile.Has(asset.GetHeader().uuid)); @@ -387,8 +423,6 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldSaveTheAsset) TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldUpdateTheDataWhenCalledTwice) { - const UUID uuid; - AssetA referencedAssetX; referencedAssetX.SetName("referencedX"); @@ -398,30 +432,16 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldUpdateTheDataWhenCalledTwice) AssetB asset; asset.GetAsset().count = 1; asset.GetAsset().ref_a = HardReference {referencedAssetX.GetHeader().uuid}; + SaveAsset(asset); - eastl::vector flatbuffer = asset.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = uuid, - .m_name = "hello", - .m_typeID = AssetB::GetTypeID(), - .m_typeName = eastl::string {AssetB::GetTypeName()}}, - flatbuffer, - AssetB::GetHardReferences(flatbuffer)); - - const eastl::optional savedMetadata1 = m_bigFile.GetAssetMetadata(uuid); - ASSERT_TRUE(savedMetadata1.has_value()); - EXPECT_EQ(savedMetadata1->m_name, "hello"); - EXPECT_EQ(savedMetadata1->m_typeID, AssetB::GetTypeID()); - EXPECT_EQ(savedMetadata1->m_typeName, eastl::string {AssetB::GetTypeName()}); - EXPECT_EQ(savedMetadata1->m_modificationTime, savedMetadata1->m_creationTime); - - const eastl::optional> savedFlatbuffer1 = m_bigFile.GetAssetFlatbuffer(uuid); - ASSERT_TRUE(savedFlatbuffer1.has_value()); + const eastl::vector savedFlatbuffer1 = m_bigFile.GetAssetFlatbuffer(asset.GetHeader().uuid); + ASSERT_FALSE(savedFlatbuffer1.empty()); AssetB savedAsset1; - savedAsset1.Unpack(*savedFlatbuffer1); + savedAsset1.Unpack(savedFlatbuffer1); EXPECT_EQ(savedAsset1.GetAsset().count, 1); - const eastl::vector hardReferences1 = m_bigFile.GetAssetHardReferences(uuid); + const eastl::vector hardReferences1 = m_bigFile.GetAssetHardReferences(asset.GetHeader().uuid); ASSERT_EQ(hardReferences1.size(), 1); EXPECT_EQ(hardReferences1[0], referencedAssetX.GetHeader().uuid); @@ -429,32 +449,16 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldUpdateTheDataWhenCalledTwice) asset.GetAsset().count = 2; asset.GetAsset().ref_a = HardReference {referencedAssetY.GetHeader().uuid}; + SaveAsset(asset); - flatbuffer = asset.Pack(); - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = uuid, - .m_name = "world", - .m_typeID = AssetB::GetTypeID(), - .m_typeName = eastl::string {AssetB::GetTypeName()}}, - flatbuffer, - AssetB::GetHardReferences(flatbuffer)); - - const eastl::optional savedMetadata2 = m_bigFile.GetAssetMetadata(uuid); - ASSERT_TRUE(savedMetadata2.has_value()); - EXPECT_EQ(savedMetadata2->m_name, "world"); - EXPECT_EQ(savedMetadata2->m_typeID, AssetB::GetTypeID()); - EXPECT_EQ(savedMetadata2->m_typeName, eastl::string {AssetB::GetTypeName()}); - EXPECT_GT(savedMetadata2->m_modificationTime, savedMetadata2->m_creationTime); - - EXPECT_LT(savedMetadata1->m_modificationTime, savedMetadata2->m_modificationTime); - - const eastl::optional> savedFlatbuffer2 = m_bigFile.GetAssetFlatbuffer(uuid); - ASSERT_TRUE(savedFlatbuffer2.has_value()); + const eastl::vector savedFlatbuffer2 = m_bigFile.GetAssetFlatbuffer(asset.GetHeader().uuid); + ASSERT_FALSE(savedFlatbuffer2.empty()); AssetB savedAsset2; - savedAsset2.Unpack(*savedFlatbuffer2); + savedAsset2.Unpack(savedFlatbuffer2); EXPECT_EQ(savedAsset2.GetAsset().count, 2); - const eastl::vector hardReferences2 = m_bigFile.GetAssetHardReferences(uuid); + const eastl::vector hardReferences2 = m_bigFile.GetAssetHardReferences(asset.GetHeader().uuid); ASSERT_EQ(hardReferences2.size(), 1); EXPECT_EQ(hardReferences2[0], referencedAssetY.GetHeader().uuid); EXPECT_NE(hardReferences2[0], referencedAssetX.GetHeader().uuid); @@ -480,23 +484,7 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldSaveTheAssets) assetB.GetAsset().count = 7; assetB.GetAsset().ref_a = HardReference {referencedAssetB.GetHeader().uuid}; - const eastl::array metadatas {AssetMetadata {.m_uuid = assetA.GetHeader().uuid, - .m_name = assetA.GetHeader().name, - .m_typeID = assetA.GetHeader().type_id, - .m_typeName = assetA.GetHeader().type_name}, - AssetMetadata {.m_uuid = assetB.GetHeader().uuid, - .m_name = assetB.GetHeader().name, - .m_typeID = assetB.GetHeader().type_id, - .m_typeName = assetB.GetHeader().type_name}}; - - const eastl::vector flatbufferA = assetA.Pack(); - const eastl::vector flatbufferB = assetB.Pack(); - - const eastl::array, 2> flatbuffers {flatbufferA, flatbufferB}; - const eastl::array, 2> flatbuffersHardReferences {AssetB::GetHardReferences(flatbufferA), - AssetB::GetHardReferences(flatbufferB)}; - - m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers, flatbuffersHardReferences); + SaveAssets({&assetA, &assetB}); EXPECT_TRUE(m_bigFile.Has(assetA.GetHeader().uuid)); EXPECT_TRUE(m_bigFile.Has(assetB.GetHeader().uuid)); @@ -514,8 +502,6 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldSaveTheAssets) TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldUpdateTheDataWhenCalledTwice) { - const UUID uuid; - AssetA referencedAssetX; referencedAssetX.SetName("referencedX"); @@ -525,32 +511,16 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldUpdateTheDataWhenCalledTwice) AssetB asset; asset.GetAsset().count = 1; asset.GetAsset().ref_a = HardReference {referencedAssetX.GetHeader().uuid}; - const eastl::array metadatas1 { - AssetMetadata {.m_uuid = uuid, - .m_name = "hello", - .m_typeID = AssetB::GetTypeID(), - .m_typeName = eastl::string {AssetB::GetTypeName()}}}; + SaveAssets({&asset}); - const eastl::vector flatbuffer1 = asset.Pack(); - - const eastl::array, 1> flatbuffers1 {flatbuffer1}; - const eastl::array, 1> flatbuffersHardReferences1 {AssetB::GetHardReferences(flatbuffer1)}; - - m_bigFile.SaveAssetFlatbuffers(metadatas1, flatbuffers1, flatbuffersHardReferences1); - - const eastl::optional savedMetadata1 = m_bigFile.GetAssetMetadata(uuid); - ASSERT_TRUE(savedMetadata1.has_value()); - EXPECT_EQ(savedMetadata1->m_name, "hello"); - EXPECT_EQ(savedMetadata1->m_modificationTime, savedMetadata1->m_creationTime); - - const eastl::optional> savedFlatbuffer1 = m_bigFile.GetAssetFlatbuffer(uuid); - ASSERT_TRUE(savedFlatbuffer1.has_value()); + eastl::vector savedFlatbuffer1 = m_bigFile.GetAssetFlatbuffer(asset.GetHeader().uuid); + ASSERT_FALSE(savedFlatbuffer1.empty()); AssetB savedAsset1; - savedAsset1.Unpack(*savedFlatbuffer1); + savedAsset1.Unpack(savedFlatbuffer1); EXPECT_EQ(savedAsset1.GetAsset().count, 1); - const eastl::vector hardReferences1 = m_bigFile.GetAssetHardReferences(uuid); + const eastl::vector hardReferences1 = m_bigFile.GetAssetHardReferences(asset.GetHeader().uuid); ASSERT_EQ(hardReferences1.size(), 1); EXPECT_EQ(hardReferences1[0], referencedAssetX.GetHeader().uuid); @@ -558,37 +528,18 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldUpdateTheDataWhenCalledTwice) asset.GetAsset().count = 2; asset.GetAsset().ref_a = HardReference {referencedAssetY.GetHeader().uuid}; + SaveAssets({&asset}); - const eastl::array metadatas2 { - AssetMetadata {.m_uuid = uuid, - .m_name = "world", - .m_typeID = AssetB::GetTypeID(), - .m_typeName = eastl::string {AssetB::GetTypeName()}}}; - const eastl::vector flatbuffer2 = asset.Pack(); - - const eastl::array, 1> flatbuffers2 {flatbuffer2}; - const eastl::array, 1> flatbuffersHardReferences2 {AssetB::GetHardReferences(flatbuffer2)}; - - m_bigFile.SaveAssetFlatbuffers(metadatas2, flatbuffers2, flatbuffersHardReferences2); - - const eastl::optional savedMetadata2 = m_bigFile.GetAssetMetadata(uuid); - ASSERT_TRUE(savedMetadata2.has_value()); - EXPECT_EQ(savedMetadata2->m_name, "world"); - EXPECT_GT(savedMetadata2->m_modificationTime, savedMetadata2->m_creationTime); - - EXPECT_LT(savedMetadata1->m_modificationTime, savedMetadata2->m_modificationTime); - - const eastl::optional> savedFlatbuffer2 = m_bigFile.GetAssetFlatbuffer(uuid); - ASSERT_TRUE(savedFlatbuffer2.has_value()); + const eastl::vector savedFlatbuffer2 = m_bigFile.GetAssetFlatbuffer(asset.GetHeader().uuid); + ASSERT_FALSE(savedFlatbuffer2.empty()); AssetB savedAsset2; - savedAsset2.Unpack(*savedFlatbuffer2); + savedAsset2.Unpack(savedFlatbuffer2); EXPECT_EQ(savedAsset2.GetAsset().count, 2); - const eastl::vector hardReferences2 = m_bigFile.GetAssetHardReferences(uuid); + const eastl::vector hardReferences2 = m_bigFile.GetAssetHardReferences(asset.GetHeader().uuid); ASSERT_EQ(hardReferences2.size(), 1); EXPECT_EQ(hardReferences2[0], referencedAssetY.GetHeader().uuid); - EXPECT_NE(hardReferences2[0], referencedAssetX.GetHeader().uuid); } /****************************************************************************************/ @@ -599,14 +550,7 @@ TEST_F(BigFileFixture, Has_ShouldReturnTrueIfTheAssetExists) asset.SetName("hello"); asset.GetAsset().health = 42; asset.GetAsset().mana = 7; - const eastl::vector flatbuffer = asset.Pack(); - - const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid, - .m_name = asset.GetHeader().name, - .m_typeID = asset.GetHeader().type_id, - .m_typeName = asset.GetHeader().type_name}; - - m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer, AssetA::GetHardReferences(flatbuffer)); + SaveAsset(asset); EXPECT_TRUE(m_bigFile.Has(asset.GetHeader().uuid)); } diff --git a/Bigfoot/Tests/Engine/DataAccessor/DataAccessor.cpp b/Bigfoot/Tests/Engine/DataAccessor/DataAccessor.cpp index e851a36..f68d222 100644 --- a/Bigfoot/Tests/Engine/DataAccessor/DataAccessor.cpp +++ b/Bigfoot/Tests/Engine/DataAccessor/DataAccessor.cpp @@ -6,7 +6,8 @@ *********************************************************************/ #include -#include +#include + #include namespace Bigfoot @@ -14,39 +15,6 @@ namespace Bigfoot class DataAccessorFixture: public ::testing::Test { protected: - class DataAccessorMock: public DataAccessor - { - public: - MOCK_METHOD(eastl::vector, GetAssetFlatbuffer, (const UUID& p_uuid), (const, override)); - MOCK_METHOD(eastl::vector>, - GetAssetFlatbuffers, - (eastl::span p_uuids), - (const, override)); - MOCK_METHOD(AssetMetadata, GetAssetMetadata, (const UUID& p_uuid), (const, override)); - MOCK_METHOD(eastl::vector, - GetAssetMetadatas, - (eastl::span p_uuids), - (const, override)); - MOCK_METHOD(eastl::vector, GetAssetHardReferences, (const UUID& p_uuid), (const, override)); - MOCK_METHOD(eastl::vector>, - GetAssetsHardReferences, - (const eastl::span p_uuids), - (const, override)); - MOCK_METHOD(void, - SaveAssetFlatbuffer, - (const AssetMetadata& p_metaData, - const eastl::span p_flatbuffer, - const eastl::span p_hardReferences), - (override)); - MOCK_METHOD(void, - SaveAssetFlatbuffers, - (eastl::span p_metadatas, - eastl::span> p_flatbuffers, - eastl::span> p_hardReferences), - (override)); - MOCK_METHOD(bool, Has, (const UUID& p_uuid), (const, override)); - }; - void SetUp() override { m_original = g_dataAccessor; diff --git a/Bigfoot/Tests/Engine/Include/EngineTests/DataAccessorMock.hpp b/Bigfoot/Tests/Engine/Include/EngineTests/DataAccessorMock.hpp new file mode 100644 index 0000000..260f544 --- /dev/null +++ b/Bigfoot/Tests/Engine/Include/EngineTests/DataAccessorMock.hpp @@ -0,0 +1,44 @@ +/********************************************************************* + * \file DataAccessorMock.hpp + * + * \author Romain BOULLARD + * \date August 2026 + *********************************************************************/ +#ifndef BIGFOOT_ENGINETESTS_DATAACCESSORMOCK_HPP +#define BIGFOOT_ENGINETESTS_DATAACCESSORMOCK_HPP +#include + +#include + +namespace Bigfoot +{ +class DataAccessorMock: public DataAccessor +{ + public: + MOCK_METHOD(eastl::vector, GetAssetFlatbuffer, (const UUID& p_uuid), (const, override)); + MOCK_METHOD(eastl::vector>, + GetAssetFlatbuffers, + (eastl::span p_uuids), + (const, override)); + MOCK_METHOD(eastl::vector, GetAssetHardReferences, (const UUID& p_uuid), (const, override)); + MOCK_METHOD(eastl::vector>, + GetAssetsHardReferences, + (const eastl::span p_uuids), + (const, override)); + MOCK_METHOD(void, + SaveAssetFlatbuffer, + (const UUID& p_uuid, + const eastl::span p_flatbuffer, + const eastl::span p_hardReferences), + (override)); + MOCK_METHOD(void, + SaveAssetFlatbuffers, + (const eastl::span p_uuids, + const eastl::span> p_flatbuffers, + const eastl::span> p_hardReferences), + (override)); + MOCK_METHOD(bool, Has, (const UUID& p_uuid), (const, override)); +}; +} // namespace Bigfoot + +#endif diff --git a/Bigfoot/Tests/Engine/Sasquatch/Sasquatch.cpp b/Bigfoot/Tests/Engine/Sasquatch/Sasquatch.cpp index 6379a03..5daaa21 100644 --- a/Bigfoot/Tests/Engine/Sasquatch/Sasquatch.cpp +++ b/Bigfoot/Tests/Engine/Sasquatch/Sasquatch.cpp @@ -21,48 +21,57 @@ namespace Bigfoot class SasquatchFixture: public ::testing::Test { protected: - struct SasquatchData - { - UUID m_uuid; - eastl::span m_flatbuffer; - eastl::vector m_hardReferences; - }; - void SetUp() { - File {SASQUATCH_ENGINETESTS_LOCATION}.Delete(); - m_assetA.SetName("hello"); - m_flatbufferA = m_assetA.Pack(); m_assetB.SetName("world"); m_assetB.GetAsset().ref_a = HardReference {m_assetA.GetHeader().uuid}; - m_flatbufferB = m_assetB.Pack(); - const eastl::vector assets { - SasquatchData {.m_uuid = m_assetA.GetHeader().uuid, - .m_flatbuffer = m_flatbufferA, - .m_hardReferences = AssetA::GetHardReferences(m_flatbufferA)}, - SasquatchData {.m_uuid = m_assetB.GetHeader().uuid, - .m_flatbuffer = m_flatbufferB, - .m_hardReferences = AssetB::GetHardReferences(m_flatbufferB)}}; + BuildSasquatch({&m_assetA, &m_assetB}); + } + + /* + * Packs the given assets and writes them to a Sasquatch file, then opens it as m_sasquatch + * + * \param p_assets The assets to write, in insertion order + */ + void BuildSasquatch(const eastl::vector& p_assets) + { + struct WriteData + { + UUID m_uuid; + eastl::vector m_flatbuffer; + eastl::vector m_hardReferences; + }; + + eastl::vector writeData; + writeData.reserve(p_assets.size()); std::uint64_t totalFlatbufferBytes = 0; std::size_t totalHardReferencesBytes = 0; - for (const SasquatchData& asset: assets) + for (AssetBase* const asset: p_assets) { - totalFlatbufferBytes += asset.m_flatbuffer.size(); - totalFlatbufferBytes += asset.m_hardReferences.size() * UUID::UUID_BYTE_SIZE; + eastl::vector flatbuffer = asset->Pack(); + eastl::vector hardReferences = asset->GetHardReferences(flatbuffer); + + totalFlatbufferBytes += flatbuffer.size(); + totalHardReferencesBytes += hardReferences.size() * UUID::UUID_BYTE_SIZE; + + writeData.push_back(WriteData {.m_uuid = asset->GetHeader().uuid, + .m_flatbuffer = std::move(flatbuffer), + .m_hardReferences = std::move(hardReferences)}); } + File {SASQUATCH_ENGINETESTS_LOCATION}.Delete(); { SasquatchWriter writer {File {SASQUATCH_ENGINETESTS_LOCATION}, - assets.size(), + writeData.size(), totalFlatbufferBytes, totalHardReferencesBytes}; - for (const SasquatchData& asset: assets) + for (const WriteData& data: writeData) { - writer.WriteAsset(asset.m_uuid, asset.m_flatbuffer, asset.m_hardReferences); + writer.WriteAsset(data.m_uuid, data.m_flatbuffer, data.m_hardReferences); } } @@ -72,9 +81,6 @@ class SasquatchFixture: public ::testing::Test AssetA m_assetA; AssetB m_assetB; - eastl::vector m_flatbufferA; - eastl::vector m_flatbufferB; - eastl::optional m_sasquatch; }; @@ -151,7 +157,7 @@ TEST_F(SasquatchFixture, GetAssetFlatbuffer_ShouldReturnEmptyForNonExistentUUID) TEST_F(SasquatchFixture, GetAssetFlatbuffer_ShouldGetTheAssetFlatbuffer) { const eastl::vector savedFlatbuffer = m_sasquatch->GetAssetFlatbuffer(m_assetA.GetHeader().uuid); - EXPECT_EQ(savedFlatbuffer, m_flatbufferA); + EXPECT_EQ(savedFlatbuffer, m_assetA.Pack()); } /****************************************************************************************/ @@ -162,9 +168,9 @@ TEST_F(SasquatchFixture, GetAssetFlatbuffers_ShouldReturnEmptyForNonExistentUUID const eastl::vector> flatbuffers = m_sasquatch->GetAssetFlatbuffers(uuids); ASSERT_EQ(flatbuffers.size(), 3); - EXPECT_EQ(flatbuffers[0], m_flatbufferA); + EXPECT_EQ(flatbuffers[0], m_assetA.Pack()); EXPECT_TRUE(flatbuffers[1].empty()); - EXPECT_EQ(flatbuffers[2], m_flatbufferB); + EXPECT_EQ(flatbuffers[2], m_assetB.Pack()); } /****************************************************************************************/ @@ -175,8 +181,8 @@ TEST_F(SasquatchFixture, GetAssetFlatbuffers_ShouldDuplicateResultsForADuplicate const eastl::vector> flatbuffers = m_sasquatch->GetAssetFlatbuffers(uuids); ASSERT_EQ(flatbuffers.size(), 2); - EXPECT_EQ(flatbuffers[0], m_flatbufferA); - EXPECT_EQ(flatbuffers[1], m_flatbufferA); + EXPECT_EQ(flatbuffers[0], m_assetA.Pack()); + EXPECT_EQ(flatbuffers[1], m_assetA.Pack()); } /****************************************************************************************/ diff --git a/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp b/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp index 9ca1019..4a39381 100644 --- a/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp +++ b/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp @@ -30,6 +30,20 @@ class SasquatchBakerFixture: public ::testing::Test m_outputFile.Delete(); } + /* + * Packs an asset and saves it to the BigFile + * + * \param p_asset The asset to save + * \return The UUID the asset was saved under + */ + template + UUID SaveAsset(ASSET& p_asset) + { + const eastl::vector flatbuffer = p_asset.Pack(); + m_bigFile.SaveAssetFlatbuffer(p_asset.GetHeader().uuid, flatbuffer, p_asset.GetHardReferences(flatbuffer)); + return p_asset.GetHeader().uuid; + } + static constexpr eastl::string_view SASQUATCH_SASQUATCHBAKERTESTS_LOCATION {"./SasquatchBakerTests.sasquatch"}; BigFile m_bigFile {File {BIGFILE_SASQUATCHBAKERTESTS_LOCATION}}; File m_outputFile {SASQUATCH_SASQUATCHBAKERTESTS_LOCATION}; @@ -56,28 +70,12 @@ TEST_F(SasquatchBakerFixture, Bake_ShouldWriteEveryAssetOfTheBigFile) { AssetA assetA; assetA.SetName("hello"); - - const eastl::vector flatbufferA = assetA.Pack(); - - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetA.GetHeader().uuid, - .m_name = assetA.GetHeader().name, - .m_typeID = assetA.GetHeader().type_id, - .m_typeName = assetA.GetHeader().type_name}, - flatbufferA, - AssetA::GetHardReferences(flatbufferA)); + SaveAsset(assetA); AssetB assetB; assetB.SetName("world"); assetB.GetAsset().ref_a = HardReference {assetA.GetHeader().uuid}; - - const eastl::vector flatbufferB = assetB.Pack(); - - m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = assetB.GetHeader().uuid, - .m_name = assetB.GetHeader().name, - .m_typeID = assetB.GetHeader().type_id, - .m_typeName = assetB.GetHeader().type_name}, - flatbufferB, - AssetB::GetHardReferences(flatbufferB)); + SaveAsset(assetB); Bake(m_bigFile, m_outputFile); Sasquatch sasquatch {m_outputFile};