diff --git a/Bigfoot/Benchmarks/AssetsForBenchmarking/Asset/BenchmarkAssetReferred.cpp b/Bigfoot/Benchmarks/AssetsForBenchmarking/Asset/BenchmarkAssetReferred.cpp new file mode 100644 index 0000000..dc595c0 --- /dev/null +++ b/Bigfoot/Benchmarks/AssetsForBenchmarking/Asset/BenchmarkAssetReferred.cpp @@ -0,0 +1,11 @@ +/********************************************************************* + * \file BenchmarkAssetReferred.cpp + * + * \author Romain BOULLARD + * \date August 2026 + *********************************************************************/ +#include + +#include + +BIGFOOT_ASSET(BenchmarkAssetReferred, ::Bigfoot::BenchmarkAssetReferred) diff --git a/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAsset.fbs b/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAsset.fbs index b988d5b..a022054 100644 --- a/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAsset.fbs +++ b/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAsset.fbs @@ -1,8 +1,11 @@ +include "Engine/Asset/Reference.fbs"; + namespace Flat.Bigfoot; table BenchmarkAsset { payload: [ubyte]; + refs: [HardReference] (native_inline, bigfoot_ref: "::Bigfoot::BenchmarkAssetReferred"); } root_type BenchmarkAsset; diff --git a/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAssetReferred.fbs b/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAssetReferred.fbs new file mode 100644 index 0000000..5b43973 --- /dev/null +++ b/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAssetReferred.fbs @@ -0,0 +1,7 @@ +namespace Flat.Bigfoot; + +table BenchmarkAssetReferred +{ +} + +root_type BenchmarkAssetReferred; diff --git a/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAssetReferred.hpp b/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAssetReferred.hpp new file mode 100644 index 0000000..f306e30 --- /dev/null +++ b/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAssetReferred.hpp @@ -0,0 +1,25 @@ +/********************************************************************* + * \file BenchmarkAssetReferred.hpp + * + * \author Romain BOULLARD + * \date August 2026 + *********************************************************************/ +#ifndef BIGFOOT_ASSETSFORBENCHMARKING_ASSET_BENCHMARKASSETREFERRED_HPP +#define BIGFOOT_ASSETSFORBENCHMARKING_ASSET_BENCHMARKASSETREFERRED_HPP +#include + +#include + +namespace Bigfoot +{ +struct BenchmarkAssetReferredTraits +{ + using FLAT = ::Flat::Bigfoot::BenchmarkAssetReferred; +}; + +class BenchmarkAssetReferred: public Asset +{ +}; +} // namespace Bigfoot + +#endif diff --git a/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAssetReferred_generated.hpp b/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAssetReferred_generated.hpp new file mode 100644 index 0000000..bbd8dd2 --- /dev/null +++ b/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAssetReferred_generated.hpp @@ -0,0 +1,172 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_BENCHMARKASSETREFERRED_FLAT_BIGFOOT_H_ +#define FLATBUFFERS_GENERATED_BENCHMARKASSETREFERRED_FLAT_BIGFOOT_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && + FLATBUFFERS_VERSION_MINOR == 12 && + FLATBUFFERS_VERSION_REVISION == 19, + "Non-compatible flatbuffers version included"); +// Ensure the included flatbuffers.h is Bigfoot's fork - stock +// flatbuffers (or a differently versioned Bigfoot fork) is not compatible. +#ifndef FLATBUFFERS_BIGFOOT_VERSION +#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible" +#endif +static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, + "Non-compatible Bigfoot flatbuffers fork version included"); + +#include "EASTL/unique_ptr.h" +#include "EASTL/string.h" +#include "EASTL/vector.h" + +namespace Flat { +namespace Bigfoot { + +struct BenchmarkAssetReferred; +struct BenchmarkAssetReferredBuilder; +struct BenchmarkAssetReferredT; + +inline const ::flatbuffers::TypeTable *BenchmarkAssetReferredTypeTable(); + +struct BenchmarkAssetReferredT : public ::flatbuffers::NativeTable { + typedef BenchmarkAssetReferred TableType; + static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() { + return "Flat.Bigfoot.BenchmarkAssetReferredT"; + } +}; + +struct BenchmarkAssetReferred FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { + typedef BenchmarkAssetReferredT NativeTableType; + typedef BenchmarkAssetReferredBuilder Builder; + struct Traits; + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return BenchmarkAssetReferredTypeTable(); + } + static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() { + return "Flat.Bigfoot.BenchmarkAssetReferred"; + } + template + bool Verify(::flatbuffers::VerifierTemplate &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + BenchmarkAssetReferredT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(BenchmarkAssetReferredT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; + static ::flatbuffers::Offset Pack(::flatbuffers::FlatBufferBuilder &_fbb, const BenchmarkAssetReferredT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct BenchmarkAssetReferredBuilder { + typedef BenchmarkAssetReferred Table; + ::flatbuffers::FlatBufferBuilder &fbb_; + ::flatbuffers::uoffset_t start_; + explicit BenchmarkAssetReferredBuilder(::flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ::flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = ::flatbuffers::Offset(end); + return o; + } +}; + +inline ::flatbuffers::Offset CreateBenchmarkAssetReferred( + ::flatbuffers::FlatBufferBuilder &_fbb) { + BenchmarkAssetReferredBuilder builder_(_fbb); + return builder_.Finish(); +} + +struct BenchmarkAssetReferred::Traits { + using type = BenchmarkAssetReferred; + static auto constexpr Create = CreateBenchmarkAssetReferred; +}; + +::flatbuffers::Offset CreateBenchmarkAssetReferred(::flatbuffers::FlatBufferBuilder &_fbb, const BenchmarkAssetReferredT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); + +inline BenchmarkAssetReferredT *BenchmarkAssetReferred::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::make_unique(); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void BenchmarkAssetReferred::UnPackTo(BenchmarkAssetReferredT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline ::flatbuffers::Offset CreateBenchmarkAssetReferred(::flatbuffers::FlatBufferBuilder &_fbb, const BenchmarkAssetReferredT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { + return BenchmarkAssetReferred::Pack(_fbb, _o, _rehasher); +} + +inline ::flatbuffers::Offset BenchmarkAssetReferred::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const BenchmarkAssetReferredT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const BenchmarkAssetReferredT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return Flat::Bigfoot::CreateBenchmarkAssetReferred( + _fbb); +} + +inline const ::flatbuffers::TypeTable *BenchmarkAssetReferredTypeTable() { + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_TABLE, 0, nullptr, nullptr, nullptr, nullptr, nullptr + }; + return &tt; +} + +inline const Flat::Bigfoot::BenchmarkAssetReferred *GetBenchmarkAssetReferred(const void *buf) { + return ::flatbuffers::GetRoot(buf); +} + +inline const Flat::Bigfoot::BenchmarkAssetReferred *GetSizePrefixedBenchmarkAssetReferred(const void *buf) { + return ::flatbuffers::GetSizePrefixedRoot(buf); +} + +template +inline bool VerifyBenchmarkAssetReferredBuffer( + ::flatbuffers::VerifierTemplate &verifier) { + return verifier.template VerifyBuffer(nullptr); +} + +template +inline bool VerifySizePrefixedBenchmarkAssetReferredBuffer( + ::flatbuffers::VerifierTemplate &verifier) { + return verifier.template VerifySizePrefixedBuffer(nullptr); +} + +inline const char *BenchmarkAssetReferredExtension() { + return "bfbs"; +} + +inline void FinishBenchmarkAssetReferredBuffer( + ::flatbuffers::FlatBufferBuilder &fbb, + ::flatbuffers::Offset root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedBenchmarkAssetReferredBuffer( + ::flatbuffers::FlatBufferBuilder &fbb, + ::flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root); +} + +inline eastl::unique_ptr UnPackBenchmarkAssetReferred( + const void *buf, + const ::flatbuffers::resolver_function_t *res = nullptr) { + return eastl::unique_ptr(GetBenchmarkAssetReferred(buf)->UnPack(res)); +} + +inline eastl::unique_ptr UnPackSizePrefixedBenchmarkAssetReferred( + const void *buf, + const ::flatbuffers::resolver_function_t *res = nullptr) { + return eastl::unique_ptr(GetSizePrefixedBenchmarkAssetReferred(buf)->UnPack(res)); +} + +} // namespace Bigfoot +} // namespace Flat + +#endif // FLATBUFFERS_GENERATED_BENCHMARKASSETREFERRED_FLAT_BIGFOOT_H_ diff --git a/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAsset_generated.hpp b/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAsset_generated.hpp index c618b4f..b816755 100644 --- a/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAsset_generated.hpp +++ b/Bigfoot/Benchmarks/AssetsForBenchmarking/Include/AssetsForBenchmarking/Asset/BenchmarkAsset_generated.hpp @@ -20,6 +20,10 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1, "Non-compatible Bigfoot flatbuffers fork version included"); +#include "System/UUID/UUID.hpp" +#include "Engine/Asset/Reference.hpp" +#include "Engine/Asset/Reference_generated.hpp" + #include "EASTL/unique_ptr.h" #include "EASTL/string.h" #include "EASTL/vector.h" @@ -31,6 +35,21 @@ struct BenchmarkAsset; struct BenchmarkAssetBuilder; struct BenchmarkAssetT; +} // namespace Bigfoot +} // namespace Flat + +namespace Bigfoot { +class BenchmarkAssetReferred; +} // namespace Bigfoot + +namespace flatbuffers { +Flat::Bigfoot::HardReference PackHardReferenceBenchmarkAssetReferred(const ::Bigfoot::HardReference<::Bigfoot::BenchmarkAssetReferred>& p_asset); +::Bigfoot::HardReference<::Bigfoot::BenchmarkAssetReferred> UnPackHardReferenceBenchmarkAssetReferred(const Flat::Bigfoot::HardReference& p_asset); +} // namespace flatbuffers + +namespace Flat { +namespace Bigfoot { + inline const ::flatbuffers::TypeTable *BenchmarkAssetTypeTable(); struct BenchmarkAssetT : public ::flatbuffers::NativeTable { @@ -39,6 +58,7 @@ struct BenchmarkAssetT : public ::flatbuffers::NativeTable { return "Flat.Bigfoot.BenchmarkAssetT"; } eastl::vector payload{}; + eastl::vector<::Bigfoot::HardReference<::Bigfoot::BenchmarkAssetReferred>> refs{}; }; struct BenchmarkAsset FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { @@ -52,16 +72,22 @@ struct BenchmarkAsset FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { return "Flat.Bigfoot.BenchmarkAsset"; } enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_PAYLOAD = 4 + VT_PAYLOAD = 4, + VT_REFS = 6 }; const ::flatbuffers::Vector *payload() const { return GetPointer *>(VT_PAYLOAD); } + const ::flatbuffers::Vector *refs() const { + return GetPointer *>(VT_REFS); + } template bool Verify(::flatbuffers::VerifierTemplate &verifier) const { return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_PAYLOAD) && verifier.VerifyVector(payload()) && + VerifyOffset(verifier, VT_REFS) && + verifier.VerifyVector(refs()) && verifier.EndTable(); } BenchmarkAssetT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -76,6 +102,9 @@ struct BenchmarkAssetBuilder { void add_payload(::flatbuffers::Offset<::flatbuffers::Vector> payload) { fbb_.AddOffset(BenchmarkAsset::VT_PAYLOAD, payload); } + void add_refs(::flatbuffers::Offset<::flatbuffers::Vector> refs) { + fbb_.AddOffset(BenchmarkAsset::VT_REFS, refs); + } explicit BenchmarkAssetBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -89,8 +118,10 @@ struct BenchmarkAssetBuilder { inline ::flatbuffers::Offset CreateBenchmarkAsset( ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::Vector> payload = 0) { + ::flatbuffers::Offset<::flatbuffers::Vector> payload = 0, + ::flatbuffers::Offset<::flatbuffers::Vector> refs = 0) { BenchmarkAssetBuilder builder_(_fbb); + builder_.add_refs(refs); builder_.add_payload(payload); return builder_.Finish(); } @@ -112,6 +143,7 @@ inline void BenchmarkAsset::UnPackTo(BenchmarkAssetT *_o, const ::flatbuffers::r (void)_o; (void)_resolver; { auto _e = payload(); if (_e) { _o->payload.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->payload.begin()); } } + { auto _e = refs(); if (_e) { _o->refs.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->refs[_i] = ::flatbuffers::UnPackHardReferenceBenchmarkAssetReferred(*_e->Get(_i)); } } else { _o->refs.resize(0); } } } inline ::flatbuffers::Offset CreateBenchmarkAsset(::flatbuffers::FlatBufferBuilder &_fbb, const BenchmarkAssetT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { @@ -123,17 +155,23 @@ inline ::flatbuffers::Offset BenchmarkAsset::Pack(::flatbuffers: (void)_o; struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const BenchmarkAssetT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _payload = _fbb.CreateVector(_o->payload.data(), _o->payload.size()); + auto _refs = _fbb.CreateVectorOfNativeStructs>(_o->refs.data(), _o->refs.size(), ::flatbuffers::PackHardReferenceBenchmarkAssetReferred); return Flat::Bigfoot::CreateBenchmarkAsset( _fbb, - _payload); + _payload, + _refs); } inline const ::flatbuffers::TypeTable *BenchmarkAssetTypeTable() { static const ::flatbuffers::TypeCode type_codes[] = { - { ::flatbuffers::ET_UCHAR, 1, -1 } + { ::flatbuffers::ET_UCHAR, 1, -1 }, + { ::flatbuffers::ET_SEQUENCE, 1, 0 } + }; + static const ::flatbuffers::TypeFunction type_refs[] = { + Flat::Bigfoot::HardReferenceTypeTable }; static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_TABLE, 1, type_codes, nullptr, nullptr, nullptr, nullptr + ::flatbuffers::ST_TABLE, 2, type_codes, type_refs, nullptr, nullptr, nullptr }; return &tt; } @@ -189,4 +227,12 @@ inline eastl::unique_ptr UnPackSizePrefixedBench } // namespace Bigfoot } // namespace Flat +namespace flatbuffers { +#ifndef FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEBENCHMARKASSETREFERRED +#define FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEBENCHMARKASSETREFERRED +inline Flat::Bigfoot::HardReference PackHardReferenceBenchmarkAssetReferred(const ::Bigfoot::HardReference<::Bigfoot::BenchmarkAssetReferred>& p_asset) { return {Pack(p_asset.GetUUID())}; } +inline ::Bigfoot::HardReference<::Bigfoot::BenchmarkAssetReferred> UnPackHardReferenceBenchmarkAssetReferred(const Flat::Bigfoot::HardReference& p_asset) { return {UnPack(p_asset.uuid())}; } +#endif // FLATBUFFERS_BIGFOOT_REF_HARDREFERENCEBENCHMARKASSETREFERRED +} // namespace flatbuffers + #endif // FLATBUFFERS_GENERATED_BENCHMARKASSET_FLAT_BIGFOOT_H_ diff --git a/Bigfoot/Benchmarks/Engine/BigFile/BigFile.cpp b/Bigfoot/Benchmarks/Engine/BigFile/BigFile.cpp index c5a589b..ae57ecd 100644 --- a/Bigfoot/Benchmarks/Engine/BigFile/BigFile.cpp +++ b/Bigfoot/Benchmarks/Engine/BigFile/BigFile.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -33,32 +34,42 @@ class BigFileFixture: public benchmark::Fixture void SetUp(benchmark::State&) override { - BigFile::Request {m_bigFile, "DELETE FROM Asset;"}.Execute(); - BigFile::Request {m_bigFile, "DELETE FROM AssetMetadata;"}.Execute(); + m_bigFile.Clear(); 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); for (std::uint32_t i = 0; i < ASSET_COUNT; ++i) { BenchmarkAsset asset; asset.SetName(asset.GetHeader().uuid.ToString().c_str()); asset.GetAsset().payload.assign(ASSET_PAYLOAD_SIZE, std::uint8_t {0xAB}); + for (std::uint32_t j = 0; j < 4; ++j) + { + BenchmarkAssetReferred assetReferred; + assetReferred.SetName(assetReferred.GetHeader().uuid.ToString().c_str()); + + 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}); - flatbuffers.push_back(asset.Pack()); + const eastl::vector flatbuffer = asset.Pack(); + flatbuffers.push_back(flatbuffer); + hardReferences.push_back(BenchmarkAsset::GetHardReferences(flatbuffer)); m_uuids.push_back(asset.GetHeader().uuid); } - m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers); + m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers, hardReferences); } [[nodiscard]] @@ -196,6 +207,48 @@ BENCHMARK_REGISTER_F(BigFileFixture, GetAssetMetadatas) /****************************************************************************************/ +BENCHMARK_DEFINE_F(BigFileFixture, GetAssetHardReferences)(benchmark::State& state) +{ + for (auto _: state) + { + benchmark::DoNotOptimize( + m_bigFile.GetAssetHardReferences(m_uuids[Random::get(0, m_uuids.size() - 1)])); + } + + state.SetItemsProcessed(state.iterations()); +} + +BENCHMARK_REGISTER_F(BigFileFixture, GetAssetHardReferences)->Name("BigFile/GetAssetHardReferences"); + +/****************************************************************************************/ + +BENCHMARK_DEFINE_F(BigFileFixture, GetAssetsHardReferences)(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.GetAssetsHardReferences(batchPool[batchIndex])); + batchIndex = (batchIndex + 1) % BATCH_POOL_SIZE; + } + + state.SetItemsProcessed(state.iterations() * batchSize); +} + +BENCHMARK_REGISTER_F(BigFileFixture, GetAssetsHardReferences) + ->Name("BigFile/GetAssetsHardReferences") + ->Arg(1) + ->Arg(8) + ->Arg(64) + ->Arg(512) + ->Arg(4096); + +/****************************************************************************************/ + BENCHMARK_DEFINE_F(BigFileFixture, SaveAssetFlatbuffer)(benchmark::State& state) { std::int64_t bytesProcessed = 0; @@ -212,10 +265,11 @@ BENCHMARK_DEFINE_F(BigFileFixture, SaveAssetFlatbuffer)(benchmark::State& state) .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); bytesProcessed += static_cast(flatbuffer.size()); state.ResumeTiming(); - m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer); + m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer, hardReferences); } state.SetItemsProcessed(state.iterations()); @@ -236,8 +290,10 @@ BENCHMARK_DEFINE_F(BigFileFixture, SaveAssetFlatbuffers)(benchmark::State& state state.PauseTiming(); eastl::vector metadatas; eastl::vector> flatbuffers; + eastl::vector> hardReferences; metadatas.reserve(batchSize); flatbuffers.reserve(batchSize); + hardReferences.reserve(batchSize); for (std::size_t i = 0; i < batchSize; ++i) { @@ -249,12 +305,14 @@ BENCHMARK_DEFINE_F(BigFileFixture, SaveAssetFlatbuffers)(benchmark::State& state .m_name = asset.GetHeader().name, .m_typeID = asset.GetHeader().type_id, .m_typeName = asset.GetHeader().type_name}); - flatbuffers.push_back(asset.Pack()); - bytesProcessed += static_cast(flatbuffers.back().size()); + const eastl::vector flatbuffer = asset.Pack(); + flatbuffers.push_back(flatbuffer); + hardReferences.push_back(BenchmarkAsset::GetHardReferences(flatbuffer)); + bytesProcessed += static_cast(flatbuffer.size()); } state.ResumeTiming(); - m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers); + m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers, hardReferences); } state.SetItemsProcessed(state.iterations() * batchSize); diff --git a/Bigfoot/Benchmarks/Tools/SasquatchBaker/SasquatchBaker.cpp b/Bigfoot/Benchmarks/Tools/SasquatchBaker/SasquatchBaker.cpp index 811faf4..163c45f 100644 --- a/Bigfoot/Benchmarks/Tools/SasquatchBaker/SasquatchBaker.cpp +++ b/Bigfoot/Benchmarks/Tools/SasquatchBaker/SasquatchBaker.cpp @@ -34,14 +34,15 @@ class SasquatchBakerFixture: public benchmark::Fixture void SetUp(benchmark::State&) override { - BigFile::Request {m_bigFile, "DELETE FROM Asset;"}.Execute(); - BigFile::Request {m_bigFile, "DELETE FROM AssetMetadata;"}.Execute(); + m_bigFile.Clear(); m_sasquatch.Delete(); eastl::vector metadatas; eastl::vector> flatbuffers; + eastl::vector> hardReferences; metadatas.reserve(ASSET_COUNT); flatbuffers.reserve(ASSET_COUNT); + hardReferences.reserve(ASSET_COUNT); for (std::uint32_t i = 0; i < ASSET_COUNT; ++i) { @@ -53,10 +54,12 @@ class SasquatchBakerFixture: public benchmark::Fixture .m_name = asset.GetHeader().name, .m_typeID = asset.GetHeader().type_id, .m_typeName = asset.GetHeader().type_name}); - flatbuffers.push_back(asset.Pack()); + const eastl::vector flatbuffer = asset.Pack(); + flatbuffers.push_back(flatbuffer); + hardReferences.push_back(BenchmarkAsset::GetHardReferences(flatbuffer)); } - m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers); + m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers, hardReferences); } void TearDown(benchmark::State&) override diff --git a/Bigfoot/Sources/Engine/BigFile/BigFile.cpp b/Bigfoot/Sources/Engine/BigFile/BigFile.cpp index 0dc5289..738e7df 100644 --- a/Bigfoot/Sources/Engine/BigFile/BigFile.cpp +++ b/Bigfoot/Sources/Engine/BigFile/BigFile.cpp @@ -69,6 +69,19 @@ void BigFile::RollbackTransaction() /****************************************************************************************/ +void BigFile::Clear() +{ + BeginTransaction(); + + BigFile::Request {*this, "DELETE FROM AssetHardReference;"}.Execute(); + BigFile::Request {*this, "DELETE FROM Asset;"}.Execute(); + BigFile::Request {*this, "DELETE FROM AssetMetadata;"}.Execute(); + + CommitTransaction(); +} + +/****************************************************************************************/ + BigFile::~BigFile() { [[maybe_unused]] @@ -248,7 +261,109 @@ eastl::vector BigFile::GetAssetMetadatas(const eastl::span p_flatbuffer) +eastl::vector BigFile::GetAssetHardReferences(const UUID& p_uuid) const +{ + BigFile::Request hardReferencesRequest {*this, "SELECT HardReference FROM AssetHardReference WHERE UUID = ?1;"}; + hardReferencesRequest.Bind(1, p_uuid.ToBytes()); + + eastl::vector hardReferences; + while (hardReferencesRequest.Step()) + { + const eastl::span rawUUID = static_cast>( + hardReferencesRequest.Get(0)); + hardReferences.emplace_back(std::span(rawUUID.begin(), rawUUID.end())); + } + + return hardReferences; +} + +/****************************************************************************************/ + +eastl::vector> BigFile::GetAssetsHardReferences(eastl::span p_uuids) const +{ + eastl::vector> hardReferences(p_uuids.size()); + + if (p_uuids.empty()) + { + return hardReferences; + } + + 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, HardReference FROM AssetHardReference WHERE UUID IN ({});", + placeholders); + + BigFile::Request hardReferencesRequest {*this, sql.c_str()}; + for (std::size_t i = 0; i < chunkSize; ++i) + { + hardReferencesRequest.Bind(static_cast(i + 1), distinctUUIDs[chunkStart + i].ToBytes()); + } + + while (hardReferencesRequest.Step()) + { + const eastl::span rawOwnerUUID = + static_cast>(hardReferencesRequest.Get(0)); + const UUID ownerUUID { + std::span {rawOwnerUUID.begin(), rawOwnerUUID.end()}}; + + const auto it = uuidToIndices.find(ownerUUID); + ASSERT(EngineAssertHandler, + it != uuidToIndices.end(), + "Returned UUID {} not found in requested UUIDs", + ownerUUID); + + const eastl::span rawHardReference = + static_cast>(hardReferencesRequest.Get(1)); + + for (const std::size_t index: it->second) + { + hardReferences[index].emplace_back( + std::span {rawHardReference.begin(), + rawHardReference.end()}); + } + } + } + + return hardReferences; +} + +/****************************************************************************************/ + +void BigFile::SaveAssetFlatbuffer(const AssetMetadata& p_metadata, + const eastl::span p_flatbuffer, + const eastl::span p_hardReferences) { BeginTransaction(); @@ -269,17 +384,57 @@ void BigFile::SaveAssetFlatbuffer(const AssetMetadata& p_metadata, const eastl:: 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.Execute(); + + constexpr std::size_t HARDREF_PARAMS_PER_ROW = 2; + const std::size_t maxHardRefRowsPerStatement = static_cast( + sqlite3_limit(m_db, SQLITE_LIMIT_VARIABLE_NUMBER, -1)) / + HARDREF_PARAMS_PER_ROW; + + for (std::size_t chunkStart = 0; chunkStart < p_hardReferences.size(); chunkStart += maxHardRefRowsPerStatement) + { + const std::size_t chunkSize = eastl::min(maxHardRefRowsPerStatement, p_hardReferences.size() - chunkStart); + + eastl::string hardReferencePlaceholders; + hardReferencePlaceholders.reserve(chunkSize * 8); + for (std::size_t i = 0; i < chunkSize; ++i) + { + if (i > 0) + { + hardReferencePlaceholders += ", "; + } + hardReferencePlaceholders += "(?, ?)"; + } + + const std::string hardReferenceSQL = fmt::format( + "INSERT INTO AssetHardReference (UUID, HardReference) VALUES {} " + "ON CONFLICT(UUID, HardReference) DO NOTHING;", + hardReferencePlaceholders); + + BigFile::Request hardReferenceRequest {*this, hardReferenceSQL.c_str()}; + 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_hardReferences[chunkStart + i].ToBytes()); + } + hardReferenceRequest.Execute(); + } + CommitTransaction(); } /****************************************************************************************/ void BigFile::SaveAssetFlatbuffers(const eastl::span p_metadatas, - const eastl::span> p_flatbuffers) + const eastl::span> p_flatbuffers, + const eastl::span> p_hardReferences) { ASSERT(EngineAssertHandler, - p_metadatas.size() == p_flatbuffers.size(), - "p_metadatas and p_flatbuffers must have the same size"); + p_metadatas.size() == p_flatbuffers.size() && p_metadatas.size() == p_hardReferences.size(), + "p_metadatas and p_flatbuffers and p_hardReferences must have the same size"); if (p_metadatas.empty()) { @@ -349,6 +504,77 @@ void BigFile::SaveAssetFlatbuffers(const eastl::span p_meta assetRequest.Bind(assetBindIndex++, p_flatbuffers[chunkStart + i]); } assetRequest.Execute(); + + // Replace hard references for every asset in this chunk with its current set. + eastl::string deleteInPlaceholders; + deleteInPlaceholders.reserve(chunkSize * 3); + for (std::size_t i = 0; i < chunkSize; ++i) + { + if (i > 0) + { + deleteInPlaceholders += ", "; + } + deleteInPlaceholders += "?"; + } + + const std::string deleteHardReferencesSQL = fmt::format("DELETE FROM AssetHardReference WHERE UUID IN ({});", + deleteInPlaceholders); + + 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.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); + } + } + + constexpr std::size_t HARDREF_PARAMS_PER_ROW = 2; + const std::size_t maxHardRefRowsPerStatement = static_cast( + sqlite3_limit(m_db, SQLITE_LIMIT_VARIABLE_NUMBER, -1)) / + HARDREF_PARAMS_PER_ROW; + + for (std::size_t hardRefChunkStart = 0; hardRefChunkStart < hardReferencePairs.size(); + hardRefChunkStart += maxHardRefRowsPerStatement) + { + const std::size_t hardRefChunkSize = eastl::min(maxHardRefRowsPerStatement, + hardReferencePairs.size() - hardRefChunkStart); + + eastl::string hardReferencePlaceholders; + hardReferencePlaceholders.reserve(hardRefChunkSize * 8); + for (std::size_t i = 0; i < hardRefChunkSize; ++i) + { + if (i > 0) + { + hardReferencePlaceholders += ", "; + } + hardReferencePlaceholders += "(?, ?)"; + } + + const std::string hardReferenceSQL = fmt::format( + "INSERT INTO AssetHardReference (UUID, HardReference) VALUES {} " + "ON CONFLICT(UUID, HardReference) DO NOTHING;", + hardReferencePlaceholders); + + BigFile::Request hardReferenceRequest {*this, hardReferenceSQL.c_str()}; + std::uint32_t bindIndex = 1; + for (std::size_t i = 0; i < hardRefChunkSize; ++i) + { + const auto& [assetUUID, hardReference] = hardReferencePairs[hardRefChunkStart + i]; + hardReferenceRequest.Bind(bindIndex++, assetUUID.ToBytes()); + hardReferenceRequest.Bind(bindIndex++, hardReference.ToBytes()); + } + hardReferenceRequest.Execute(); + } } CommitTransaction(); diff --git a/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql b/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql index 314fbf6..62882de 100644 --- a/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql +++ b/Bigfoot/Sources/Engine/BigFile/BigFileSchema.sql @@ -1,12 +1,12 @@ PRAGMA journal_mode=WAL; CREATE TABLE IF NOT EXISTS AssetMetadata ( - UUID BLOB NOT NULL, - Name TEXT NOT NULL UNIQUE, + 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)), + CreateTime INTEGER NOT NULL DEFAULT(CAST(unixepoch('subsec') * 1000000 AS INTEGER)), ModificationTime INTEGER NOT NULL DEFAULT(CAST(unixepoch('subsec') * 1000000 AS INTEGER)), PRIMARY KEY(UUID) @@ -21,7 +21,7 @@ BEGIN END; CREATE TABLE IF NOT EXISTS Asset ( - UUID BLOB NOT NULL, + UUID BLOB NOT NULL, Asset BLOB NOT NULL, @@ -35,4 +35,15 @@ BEGIN UPDATE AssetMetadata SET ModificationTime = CAST(unixepoch('subsec') * 1000000 AS INTEGER) WHERE UUID = NEW.UUID; -END; \ No newline at end of file +END; + +CREATE TABLE IF NOT EXISTS AssetHardReference ( + UUID BLOB NOT NULL, + HardReference BLOB NOT NULL, + + PRIMARY KEY(UUID, HardReference), + FOREIGN KEY(UUID) REFERENCES AssetMetadata(UUID) + ON DELETE CASCADE +); + +CREATE INDEX IF NOT EXISTS AssetHardReference_ReferencedUUID ON AssetHardReference(HardReference); \ No newline at end of file diff --git a/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp b/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp index 19e49d7..6e3ce0a 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp @@ -49,6 +49,12 @@ class BigFile: public DataAccessor */ void RollbackTransaction(); + /** + * Clear the BigFile + * + */ + void Clear(); + ~BigFile(); /** @@ -83,22 +89,43 @@ class BigFile: public DataAccessor */ eastl::vector GetAssetMetadatas(eastl::span p_uuids) const override; + /** + * Get the HardReferences of a given asset + * + * \param p_uuid The asset to get the HardReferences of + * \return The HardReferences of the asset + */ + eastl::vector GetAssetHardReferences(const UUID& p_uuid) const override; + + /** + * Get the HardReferences of given assets + * + * \param p_uuids The assets to get the HardReferences of + * \return The HardReferences of the assets + */ + eastl::vector> GetAssetsHardReferences(eastl::span p_uuids) const override; + /** * Save an asset * * \p_metadata The metadata * \p_flatbuffer The flatbuffer of the asset + * \param p_hardReferences The HardReferences the asset points to */ - void SaveAssetFlatbuffer(const AssetMetadata& p_metadata, const eastl::span p_flatbuffer) override; + void SaveAssetFlatbuffer(const AssetMetadata& p_metadata, + 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_hardReferences The HardReferences the asset points to */ void SaveAssetFlatbuffers(eastl::span p_metadatas, - eastl::span> p_flatbuffers) override; + eastl::span> p_flatbuffers, + const eastl::span> p_uuids) 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 8f87d9a..2879034 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/DataAccessor/DataAccessor.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/DataAccessor/DataAccessor.hpp @@ -72,23 +72,43 @@ class DataAccessor */ virtual eastl::vector GetAssetMetadatas(eastl::span p_uuids) const = 0; + /** + * Get the HardReferences of a given asset + * + * \param p_uuid The asset to get the HardReferences of + * \return The HardReferences of the asset + */ + virtual eastl::vector GetAssetHardReferences(const UUID& p_uuid) const = 0; + + /** + * Get the HardReferences of given assets + * + * \param p_uuids The assets to get the HardReferences of + * \return The HardReferences of the assets + */ + virtual eastl::vector> GetAssetsHardReferences(eastl::span p_uuids) const = 0; + /** * Save an asset * * \p_metadata The metadata * \p_flatbuffer The flatbuffer of the asset + * \param p_hardReferences The HardReferences the asset points to */ virtual void SaveAssetFlatbuffer(const AssetMetadata& p_metadata, - const eastl::span p_flatbuffer) = 0; + 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_hardReferences The HardReferences the asset points to */ virtual void SaveAssetFlatbuffers(eastl::span p_metadatas, - eastl::span> p_flatbuffers) = 0; + eastl::span> p_flatbuffers, + const eastl::span> p_uuids) = 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 d56ac4d..1036b86 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Sasquatch/Sasquatch.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Sasquatch/Sasquatch.hpp @@ -173,14 +173,17 @@ class Sasquatch: public DataAccessor * Sasquatch is read-only: this will always fail * */ - void SaveAssetFlatbuffer(const AssetMetadata& p_metadata, eastl::span p_flatbuffer) override; + void SaveAssetFlatbuffer(const AssetMetadata& p_metadata, + eastl::span p_flatbuffer, + eastl::span p_hardReferences) override; /** * Sasquatch is read-only: this will always fail * */ void SaveAssetFlatbuffers(eastl::span p_metadatas, - eastl::span> p_flatbuffers) override; + eastl::span> p_flatbuffers, + eastl::span> p_hardReferences) override; /** * Check if the Asset exists diff --git a/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp b/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp index 48b9e64..c4dd605 100644 --- a/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp +++ b/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp @@ -200,7 +200,7 @@ eastl::vector> Sasquatch::GetAssetFlatbuffers(const eas /****************************************************************************************/ -eastl::optional Sasquatch::GetAssetMetadata(const UUID&) const +eastl::optional Sasquatch::GetAssetMetadata([[maybe_unused]] const UUID& p_uuid) const { ASSERT(EngineAssertHandler, false, "Sasquatch does not support metadata queries, only flatbuffers"); return eastl::nullopt; @@ -208,7 +208,7 @@ eastl::optional Sasquatch::GetAssetMetadata(const UUID&) const /****************************************************************************************/ -eastl::vector Sasquatch::GetAssetMetadatas(const eastl::span) const +eastl::vector Sasquatch::GetAssetMetadatas([[maybe_unused]] const eastl::span p_uuids) const { ASSERT(EngineAssertHandler, false, "Sasquatch does not support metadata queries, only flatbuffers"); return {}; @@ -216,14 +216,18 @@ eastl::vector Sasquatch::GetAssetMetadatas(const eastl::span) +void Sasquatch::SaveAssetFlatbuffer([[maybe_unused]] const AssetMetadata& p_metadata, + [[maybe_unused]] eastl::span p_flatbuffer, + [[maybe_unused]] eastl::span p_hardReferences) { ASSERT(EngineAssertHandler, false, "Sasquatch is read-only, it cannot save assets"); } /****************************************************************************************/ -void Sasquatch::SaveAssetFlatbuffers(eastl::span, eastl::span>) +void Sasquatch::SaveAssetFlatbuffers([[maybe_unused]] eastl::span p_metadatas, + [[maybe_unused]] eastl::span> p_flatbuffers, + [[maybe_unused]] eastl::span> p_hardReferences) { ASSERT(EngineAssertHandler, false, "Sasquatch is read-only, it cannot save assets"); } diff --git a/Bigfoot/Tests/Engine/BigFile/BigFile.cpp b/Bigfoot/Tests/Engine/BigFile/BigFile.cpp index 0ed7eb3..e9e45e2 100644 --- a/Bigfoot/Tests/Engine/BigFile/BigFile.cpp +++ b/Bigfoot/Tests/Engine/BigFile/BigFile.cpp @@ -11,7 +11,10 @@ #include #include +#include +#include +#include #include #include @@ -25,8 +28,7 @@ class BigFileFixture: public ::testing::Test protected: void SetUp() override { - BigFile::Request {m_bigFile, "DELETE FROM Asset;"}.Execute(); - BigFile::Request {m_bigFile, "DELETE FROM AssetMetadata;"}.Execute(); + m_bigFile.Clear(); } BigFile m_bigFile {File {BIGFILE_ENGINETESTS_LOCATION}}; @@ -34,6 +36,49 @@ class BigFileFixture: public ::testing::Test /****************************************************************************************/ +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)); + + 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)); + + ASSERT_TRUE(m_bigFile.Has(referencedAsset.GetHeader().uuid)); + ASSERT_TRUE(m_bigFile.Has(asset.GetHeader().uuid)); + ASSERT_FALSE(m_bigFile.GetAssetHardReferences(asset.GetHeader().uuid).empty()); + + m_bigFile.Clear(); + + EXPECT_FALSE(m_bigFile.Has(referencedAsset.GetHeader().uuid)); + EXPECT_FALSE(m_bigFile.Has(asset.GetHeader().uuid)); + + EXPECT_FALSE(m_bigFile.GetAssetMetadata(referencedAsset.GetHeader().uuid).has_value()); + EXPECT_FALSE(m_bigFile.GetAssetMetadata(asset.GetHeader().uuid).has_value()); + + EXPECT_FALSE(m_bigFile.GetAssetFlatbuffer(referencedAsset.GetHeader().uuid).has_value()); + EXPECT_FALSE(m_bigFile.GetAssetFlatbuffer(asset.GetHeader().uuid).has_value()); + + EXPECT_TRUE(m_bigFile.GetAssetHardReferences(asset.GetHeader().uuid).empty()); +} + +/****************************************************************************************/ + TEST_F(BigFileFixture, GetAssetFlatbuffer_ShouldReturnNulloptForNonExistentUUID) { const UUID uuid; @@ -56,7 +101,7 @@ TEST_F(BigFileFixture, GetAssetFlatbuffer_ShouldGetTheAssetFlatbuffer) .m_typeID = asset.GetHeader().type_id, .m_typeName = asset.GetHeader().type_name}; - m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer); + m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer, AssetA::GetHardReferences(flatbuffer)); const eastl::optional> savedFlatbuffer = m_bigFile.GetAssetFlatbuffer( asset.GetHeader().uuid); @@ -75,7 +120,8 @@ TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldOmitUUIDsThatDoNotExist) .m_name = assetA.GetHeader().name, .m_typeID = assetA.GetHeader().type_id, .m_typeName = assetA.GetHeader().type_name}, - flatbufferA); + flatbufferA, + AssetA::GetHardReferences(flatbufferA)); AssetA assetB; assetB.SetName("world"); @@ -84,9 +130,10 @@ TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldOmitUUIDsThatDoNotExist) .m_name = assetB.GetHeader().name, .m_typeID = assetB.GetHeader().type_id, .m_typeName = assetB.GetHeader().type_name}, - flatbufferB); + flatbufferB, + AssetA::GetHardReferences(flatbufferB)); - const eastl::vector uuids {assetA.GetHeader().uuid, UUID {}, assetB.GetHeader().uuid}; + const eastl::array uuids {assetA.GetHeader().uuid, UUID {}, assetB.GetHeader().uuid}; const eastl::vector> flatbuffers = m_bigFile.GetAssetFlatbuffers(uuids); @@ -106,9 +153,10 @@ TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldNotDuplicateResultsForADuplicat .m_name = assetA.GetHeader().name, .m_typeID = assetA.GetHeader().type_id, .m_typeName = assetA.GetHeader().type_name}, - flatbufferA); + flatbufferA, + AssetA::GetHardReferences(flatbufferA)); - const eastl::vector uuids {assetA.GetHeader().uuid, assetA.GetHeader().uuid}; + const eastl::array uuids {assetA.GetHeader().uuid, assetA.GetHeader().uuid}; const eastl::vector> flatbuffers = m_bigFile.GetAssetFlatbuffers(uuids); @@ -140,7 +188,7 @@ TEST_F(BigFileFixture, GetAssetMetadata_ShouldGetTheAssetMetadata) .m_typeID = asset.GetHeader().type_id, .m_typeName = asset.GetHeader().type_name}; - m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer); + m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer, AssetA::GetHardReferences(flatbuffer)); const eastl::optional savedMetadata = m_bigFile.GetAssetMetadata(asset.GetHeader().uuid); ASSERT_TRUE(savedMetadata.has_value()); @@ -159,22 +207,28 @@ 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}, - assetA.Pack()); + 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}, - assetB.Pack()); + flatbufferB, + AssetA::GetHardReferences(flatbufferB)); const UUID missingUUID; - const eastl::vector uuids {assetA.GetHeader().uuid, missingUUID, assetB.GetHeader().uuid}; + const eastl::array uuids {assetA.GetHeader().uuid, missingUUID, assetB.GetHeader().uuid}; const eastl::vector metadatas = m_bigFile.GetAssetMetadatas(uuids); @@ -187,12 +241,132 @@ TEST_F(BigFileFixture, GetAssetMetadatas_ShouldOmitUUIDsThatDoNotExist) /****************************************************************************************/ +TEST_F(BigFileFixture, GetAssetHardReference_ShouldReturnEmptyVectorForNonExistentUUID) +{ + const UUID uuid; + + const eastl::vector hardReferences = m_bigFile.GetAssetHardReferences(uuid); + + EXPECT_TRUE(hardReferences.empty()); +} + +/****************************************************************************************/ + +TEST_F(BigFileFixture, GetAssetHardReference_ShouldGetTheAssetHardReferences) +{ + AssetA referencedAssetX; + referencedAssetX.SetName("referencedX"); + + AssetA referencedAssetY; + referencedAssetY.SetName("referencedY"); + + AssetB asset; + 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)); + + const eastl::vector hardReferences = m_bigFile.GetAssetHardReferences(asset.GetHeader().uuid); + + ASSERT_EQ(hardReferences.size(), 1); + EXPECT_TRUE(std::find(hardReferences.begin(), hardReferences.end(), referencedAssetX.GetHeader().uuid) != + hardReferences.end()); +} + +/****************************************************************************************/ + +TEST_F(BigFileFixture, GetAssetHardReferences_ShouldReturnEmptyVectorsForUUIDsThatDoNotExistOrHaveNoReferences) +{ + AssetA referencedAsset; + referencedAsset.SetName("referenced"); + + 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)); + + 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)); + + const UUID missingUUID; + const eastl::array uuids {assetWithoutReferences.GetHeader().uuid, + missingUUID, + assetWithReferences.GetHeader().uuid}; + + const eastl::vector> hardReferences = m_bigFile.GetAssetsHardReferences(uuids); + + ASSERT_EQ(hardReferences.size(), 3); + EXPECT_TRUE(hardReferences[0].empty()); + EXPECT_TRUE(hardReferences[1].empty()); + ASSERT_EQ(hardReferences[2].size(), 1); + EXPECT_EQ(hardReferences[2][0], referencedAsset.GetHeader().uuid); +} + +/****************************************************************************************/ + +TEST_F(BigFileFixture, GetAssetHardReferences_ShouldDuplicateResultsForADuplicateUUID) +{ + AssetA referencedAssetX; + referencedAssetX.SetName("referencedX"); + + AssetA referencedAssetY; + referencedAssetY.SetName("referencedY"); + + AssetB asset; + 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)); + + const eastl::array uuids {asset.GetHeader().uuid, asset.GetHeader().uuid}; + + const eastl::vector> hardReferences = m_bigFile.GetAssetsHardReferences(uuids); + + ASSERT_EQ(hardReferences.size(), 2); + for (const eastl::vector& entry: hardReferences) + { + ASSERT_EQ(entry.size(), 1); + EXPECT_TRUE(std::find(entry.begin(), entry.end(), referencedAssetX.GetHeader().uuid) != entry.end()); + } +} + +/****************************************************************************************/ + TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldSaveTheAsset) { - AssetA asset; + AssetA referencedAsset; + referencedAsset.SetName("referenced"); + + AssetB asset; asset.SetName("hello"); - asset.GetAsset().health = 42; - asset.GetAsset().mana = 7; + asset.GetAsset().ref_a = HardReference {referencedAsset.GetHeader().uuid}; const eastl::vector flatbuffer = asset.Pack(); const AssetMetadata metadata {.m_uuid = asset.GetHeader().uuid, @@ -200,9 +374,13 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldSaveTheAsset) .m_typeID = asset.GetHeader().type_id, .m_typeName = asset.GetHeader().type_name}; - m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer); + m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer, AssetB::GetHardReferences(flatbuffer)); EXPECT_TRUE(m_bigFile.Has(asset.GetHeader().uuid)); + + const eastl::vector hardReferences = m_bigFile.GetAssetHardReferences(asset.GetHeader().uuid); + ASSERT_EQ(hardReferences.size(), 1); + EXPECT_EQ(hardReferences[0], referencedAsset.GetHeader().uuid); } /****************************************************************************************/ @@ -211,42 +389,60 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldUpdateTheDataWhenCalledTwice) { const UUID uuid; - AssetA asset; - asset.GetAsset().health = 1; + AssetA referencedAssetX; + referencedAssetX.SetName("referencedX"); + + AssetA referencedAssetY; + referencedAssetY.SetName("referencedY"); + + AssetB asset; + asset.GetAsset().count = 1; + asset.GetAsset().ref_a = HardReference {referencedAssetX.GetHeader().uuid}; + + eastl::vector flatbuffer = asset.Pack(); m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = uuid, .m_name = "hello", - .m_typeID = AssetA::GetTypeID(), - .m_typeName = eastl::string {AssetA::GetTypeName()}}, - asset.Pack()); + .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, AssetA::GetTypeID()); - EXPECT_EQ(savedMetadata1->m_typeName, eastl::string {AssetA::GetTypeName()}); + 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()); - AssetA savedAsset1; + AssetB savedAsset1; savedAsset1.Unpack(*savedFlatbuffer1); - EXPECT_EQ(savedAsset1.GetAsset().health, 1); + EXPECT_EQ(savedAsset1.GetAsset().count, 1); + + const eastl::vector hardReferences1 = m_bigFile.GetAssetHardReferences(uuid); + ASSERT_EQ(hardReferences1.size(), 1); + EXPECT_EQ(hardReferences1[0], referencedAssetX.GetHeader().uuid); std::this_thread::sleep_for(std::chrono::milliseconds(20)); - asset.GetAsset().health = 2; + asset.GetAsset().count = 2; + asset.GetAsset().ref_a = HardReference {referencedAssetY.GetHeader().uuid}; + + flatbuffer = asset.Pack(); m_bigFile.SaveAssetFlatbuffer(AssetMetadata {.m_uuid = uuid, .m_name = "world", - .m_typeID = AssetA::GetTypeID(), - .m_typeName = eastl::string {AssetA::GetTypeName()}}, - asset.Pack()); + .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, AssetA::GetTypeID()); - EXPECT_EQ(savedMetadata2->m_typeName, eastl::string {AssetA::GetTypeName()}); + 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); @@ -254,37 +450,64 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffer_ShouldUpdateTheDataWhenCalledTwice) const eastl::optional> savedFlatbuffer2 = m_bigFile.GetAssetFlatbuffer(uuid); ASSERT_TRUE(savedFlatbuffer2.has_value()); - AssetA savedAsset2; + AssetB savedAsset2; savedAsset2.Unpack(*savedFlatbuffer2); - EXPECT_EQ(savedAsset2.GetAsset().health, 2); + EXPECT_EQ(savedAsset2.GetAsset().count, 2); + + const eastl::vector hardReferences2 = m_bigFile.GetAssetHardReferences(uuid); + ASSERT_EQ(hardReferences2.size(), 1); + EXPECT_EQ(hardReferences2[0], referencedAssetY.GetHeader().uuid); + EXPECT_NE(hardReferences2[0], referencedAssetX.GetHeader().uuid); } /****************************************************************************************/ TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldSaveTheAssets) { - AssetA assetA; + AssetA referencedAssetA; + referencedAssetA.SetName("referencedA"); + + AssetA referencedAssetB; + referencedAssetB.SetName("referencedB"); + + AssetB assetA; assetA.SetName("hello"); - assetA.GetAsset().health = 42; + assetA.GetAsset().count = 42; + assetA.GetAsset().ref_a = HardReference {referencedAssetA.GetHeader().uuid}; - AssetA assetB; + AssetB assetB; assetB.SetName("world"); - assetB.GetAsset().health = 7; + assetB.GetAsset().count = 7; + assetB.GetAsset().ref_a = HardReference {referencedAssetB.GetHeader().uuid}; - const eastl::vector 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> flatbuffers {assetA.Pack(), assetB.Pack()}; + 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}}; - m_bigFile.SaveAssetFlatbuffers(metadatas, flatbuffers); + 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); EXPECT_TRUE(m_bigFile.Has(assetA.GetHeader().uuid)); EXPECT_TRUE(m_bigFile.Has(assetB.GetHeader().uuid)); + + const eastl::vector hardReferencesA = m_bigFile.GetAssetHardReferences(assetA.GetHeader().uuid); + ASSERT_EQ(hardReferencesA.size(), 1); + EXPECT_EQ(hardReferencesA[0], referencedAssetA.GetHeader().uuid); + + const eastl::vector hardReferencesB = m_bigFile.GetAssetHardReferences(assetB.GetHeader().uuid); + ASSERT_EQ(hardReferencesB.size(), 1); + EXPECT_EQ(hardReferencesB[0], referencedAssetB.GetHeader().uuid); } /****************************************************************************************/ @@ -293,14 +516,27 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldUpdateTheDataWhenCalledTwice) { const UUID uuid; - AssetA asset; - asset.GetAsset().health = 1; - const eastl::vector metadatas1 {AssetMetadata {.m_uuid = uuid, - .m_name = "hello", - .m_typeID = AssetA::GetTypeID(), - .m_typeName = eastl::string {AssetA::GetTypeName()}}}; - const eastl::vector> flatbuffers1 {asset.Pack()}; - m_bigFile.SaveAssetFlatbuffers(metadatas1, flatbuffers1); + AssetA referencedAssetX; + referencedAssetX.SetName("referencedX"); + + AssetA referencedAssetY; + referencedAssetY.SetName("referencedY"); + + 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()}}}; + + 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()); @@ -310,19 +546,30 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldUpdateTheDataWhenCalledTwice) const eastl::optional> savedFlatbuffer1 = m_bigFile.GetAssetFlatbuffer(uuid); ASSERT_TRUE(savedFlatbuffer1.has_value()); - AssetA savedAsset1; + AssetB savedAsset1; savedAsset1.Unpack(*savedFlatbuffer1); - EXPECT_EQ(savedAsset1.GetAsset().health, 1); + EXPECT_EQ(savedAsset1.GetAsset().count, 1); + + const eastl::vector hardReferences1 = m_bigFile.GetAssetHardReferences(uuid); + ASSERT_EQ(hardReferences1.size(), 1); + EXPECT_EQ(hardReferences1[0], referencedAssetX.GetHeader().uuid); std::this_thread::sleep_for(std::chrono::milliseconds(20)); - asset.GetAsset().health = 2; - const eastl::vector metadatas2 {AssetMetadata {.m_uuid = uuid, - .m_name = "world", - .m_typeID = AssetA::GetTypeID(), - .m_typeName = eastl::string {AssetA::GetTypeName()}}}; - const eastl::vector> flatbuffers2 {asset.Pack()}; - m_bigFile.SaveAssetFlatbuffers(metadatas2, flatbuffers2); + asset.GetAsset().count = 2; + asset.GetAsset().ref_a = HardReference {referencedAssetY.GetHeader().uuid}; + + 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()); @@ -334,9 +581,14 @@ TEST_F(BigFileFixture, SaveAssetFlatbuffers_ShouldUpdateTheDataWhenCalledTwice) const eastl::optional> savedFlatbuffer2 = m_bigFile.GetAssetFlatbuffer(uuid); ASSERT_TRUE(savedFlatbuffer2.has_value()); - AssetA savedAsset2; + AssetB savedAsset2; savedAsset2.Unpack(*savedFlatbuffer2); - EXPECT_EQ(savedAsset2.GetAsset().health, 2); + EXPECT_EQ(savedAsset2.GetAsset().count, 2); + + const eastl::vector hardReferences2 = m_bigFile.GetAssetHardReferences(uuid); + ASSERT_EQ(hardReferences2.size(), 1); + EXPECT_EQ(hardReferences2[0], referencedAssetY.GetHeader().uuid); + EXPECT_NE(hardReferences2[0], referencedAssetX.GetHeader().uuid); } /****************************************************************************************/ @@ -354,7 +606,7 @@ TEST_F(BigFileFixture, Has_ShouldReturnTrueIfTheAssetExists) .m_typeID = asset.GetHeader().type_id, .m_typeName = asset.GetHeader().type_name}; - m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer); + m_bigFile.SaveAssetFlatbuffer(metadata, flatbuffer, AssetA::GetHardReferences(flatbuffer)); 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 ede3957..1ada664 100644 --- a/Bigfoot/Tests/Engine/DataAccessor/DataAccessor.cpp +++ b/Bigfoot/Tests/Engine/DataAccessor/DataAccessor.cpp @@ -30,14 +30,22 @@ class DataAccessorFixture: public ::testing::Test 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 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_flatbuffers, + eastl::span> p_hardReferences), (override)); MOCK_METHOD(bool, Has, (const UUID& p_uuid), (const, override)); }; diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.fbs b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.fbs index 3cc2362..800edf6 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.fbs +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB.fbs @@ -4,6 +4,7 @@ namespace Flat.Bigfoot; table AssetB { + count: uint = 0; ref_a: HardReference (native_inline, bigfoot_ref: "::Bigfoot::AssetA"); refs_a: [SoftReference] (native_inline, bigfoot_ref: "::Bigfoot::AssetA"); } diff --git a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB_generated.hpp b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB_generated.hpp index 9a55a7f..f3fd52e 100644 --- a/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB_generated.hpp +++ b/Bigfoot/Tests/Misc/AssetsForTesting/Include/AssetsForTesting/Asset/AssetB_generated.hpp @@ -59,6 +59,7 @@ struct AssetBT : public ::flatbuffers::NativeTable { static FLATBUFFERS_CONSTEXPR_CPP11 const char *GetFullyQualifiedName() { return "Flat.Bigfoot.AssetBT"; } + uint32_t count = 0; ::Bigfoot::HardReference<::Bigfoot::AssetA> ref_a{}; eastl::vector<::Bigfoot::SoftReference<::Bigfoot::AssetA>> refs_a{}; }; @@ -74,9 +75,13 @@ struct AssetB FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { return "Flat.Bigfoot.AssetB"; } enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_REF_A = 4, - VT_REFS_A = 6 + VT_COUNT = 4, + VT_REF_A = 6, + VT_REFS_A = 8 }; + uint32_t count() const { + return GetField(VT_COUNT, 0); + } const Flat::Bigfoot::HardReference *ref_a() const { return GetStruct(VT_REF_A); } @@ -86,6 +91,7 @@ struct AssetB FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { template bool Verify(::flatbuffers::VerifierTemplate &verifier) const { return VerifyTableStart(verifier) && + VerifyField(verifier, VT_COUNT, 4) && VerifyField(verifier, VT_REF_A, 1) && VerifyOffset(verifier, VT_REFS_A) && verifier.VerifyVector(refs_a()) && @@ -100,6 +106,9 @@ struct AssetBBuilder { typedef AssetB Table; ::flatbuffers::FlatBufferBuilder &fbb_; ::flatbuffers::uoffset_t start_; + void add_count(uint32_t count) { + fbb_.AddElement(AssetB::VT_COUNT, count, 0); + } void add_ref_a(const Flat::Bigfoot::HardReference *ref_a) { fbb_.AddStruct(AssetB::VT_REF_A, ref_a); } @@ -119,11 +128,13 @@ struct AssetBBuilder { inline ::flatbuffers::Offset CreateAssetB( ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t count = 0, const Flat::Bigfoot::HardReference *ref_a = nullptr, ::flatbuffers::Offset<::flatbuffers::Vector> refs_a = 0) { AssetBBuilder builder_(_fbb); builder_.add_refs_a(refs_a); builder_.add_ref_a(ref_a); + builder_.add_count(count); return builder_.Finish(); } @@ -143,6 +154,7 @@ inline AssetBT *AssetB::UnPack(const ::flatbuffers::resolver_function_t *_resolv inline void AssetB::UnPackTo(AssetBT *_o, const ::flatbuffers::resolver_function_t *_resolver) const { (void)_o; (void)_resolver; + { auto _e = count(); _o->count = _e; } { auto _e = ref_a(); if (_e) _o->ref_a = ::flatbuffers::UnPackHardReferenceAssetA(*_e); } { auto _e = refs_a(); if (_e) { _o->refs_a.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->refs_a[_i] = ::flatbuffers::UnPackSoftReferenceAssetA(*_e->Get(_i)); } } else { _o->refs_a.resize(0); } } } @@ -155,16 +167,19 @@ inline ::flatbuffers::Offset AssetB::Pack(::flatbuffers::FlatBufferBuild (void)_rehasher; (void)_o; struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const AssetBT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _count = _o->count; auto _ref_a = ::flatbuffers::PackHardReferenceAssetA(_o->ref_a); auto _refs_a = _fbb.CreateVectorOfNativeStructs>(_o->refs_a.data(), _o->refs_a.size(), ::flatbuffers::PackSoftReferenceAssetA); return Flat::Bigfoot::CreateAssetB( _fbb, + _count, &_ref_a, _refs_a); } inline const ::flatbuffers::TypeTable *AssetBTypeTable() { static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_UINT, 0, -1 }, { ::flatbuffers::ET_SEQUENCE, 0, 0 }, { ::flatbuffers::ET_SEQUENCE, 1, 1 } }; @@ -173,7 +188,7 @@ inline const ::flatbuffers::TypeTable *AssetBTypeTable() { Flat::Bigfoot::SoftReferenceTypeTable }; static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_TABLE, 2, type_codes, type_refs, nullptr, nullptr, nullptr + ::flatbuffers::ST_TABLE, 3, type_codes, type_refs, nullptr, nullptr, nullptr }; return &tt; } diff --git a/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp b/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp index 3a23bdd..a8aab1b 100644 --- a/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp +++ b/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp @@ -26,8 +26,7 @@ class SasquatchBakerFixture: public ::testing::Test protected: void SetUp() override { - BigFile::Request {m_bigFile, "DELETE FROM Asset;"}.Execute(); - BigFile::Request {m_bigFile, "DELETE FROM AssetMetadata;"}.Execute(); + m_bigFile.Clear(); m_sasquatch.Delete(); } @@ -87,19 +86,27 @@ 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}, - assetA.Pack()); + 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}, - assetB.Pack()); + flatbufferB, + AssetA::GetHardReferences(flatbufferB)); Bake(m_bigFile, m_sasquatch);