diff --git a/Bigfoot/Benchmarks/Engine/Sasquatch/Sasquatch.cpp b/Bigfoot/Benchmarks/Engine/Sasquatch/Sasquatch.cpp index 3bd068f..ef5edc3 100644 --- a/Bigfoot/Benchmarks/Engine/Sasquatch/Sasquatch.cpp +++ b/Bigfoot/Benchmarks/Engine/Sasquatch/Sasquatch.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -29,6 +30,13 @@ using Random = effolkronium::random_static; class SasquatchFixture: public benchmark::Fixture { protected: + struct SasquatchData + { + UUID m_uuid; + eastl::span m_flatbuffer; + eastl::span m_hardReferences; + }; + static constexpr std::uint32_t ASSET_COUNT = 20'000; static constexpr std::size_t ASSET_PAYLOAD_SIZE = 256; @@ -37,7 +45,9 @@ class SasquatchFixture: public benchmark::Fixture File {SASQUATCH_ENGINEBENCHMARKS_LOCATION}.Delete(); eastl::vector> flatbuffers; + eastl::vector> hardReferences; flatbuffers.reserve(ASSET_COUNT); + hardReferences.reserve(ASSET_COUNT); m_uuids.clear(); m_uuids.reserve(ASSET_COUNT); @@ -47,8 +57,17 @@ class SasquatchFixture: public benchmark::Fixture 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()); - flatbuffers.push_back(asset.Pack()); + asset.GetAsset().refs.emplace_back(assetReferred.GetHeader().uuid); + } + + const eastl::vector flatbuffer = asset.Pack(); + flatbuffers.push_back(flatbuffer); + hardReferences.push_back(BenchmarkAsset::GetHardReferences(flatbuffer)); m_uuids.push_back(asset.GetHeader().uuid); } @@ -56,20 +75,24 @@ class SasquatchFixture: public benchmark::Fixture assets.reserve(ASSET_COUNT); for (std::uint32_t i = 0; i < ASSET_COUNT; ++i) { - assets.push_back(SasquatchData {.m_uuid = m_uuids[i], .m_flatbuffer = flatbuffers[i]}); + assets.push_back(SasquatchData {.m_uuid = m_uuids[i], + .m_flatbuffer = flatbuffers[i], + .m_hardReferences = hardReferences[i]}); } - std::uint64_t totalFlatbufferBytes = 0; + std::size_t totalFlatbufferBytes = 0; + std::size_t totalHardReferencesBytes = 0; for (const SasquatchData& asset: assets) { totalFlatbufferBytes += asset.m_flatbuffer.size(); + totalHardReferencesBytes += asset.m_hardReferences.size() * UUID::UUID_BYTE_SIZE; } { - SasquatchWriter writer {File {SASQUATCH_ENGINEBENCHMARKS_LOCATION}, assets.size(), totalFlatbufferBytes}; + SasquatchWriter writer {File {SASQUATCH_ENGINEBENCHMARKS_LOCATION}, assets.size(), totalFlatbufferBytes, totalHardReferencesBytes}; for (const SasquatchData& asset: assets) { - writer.WriteAsset(asset.m_uuid, asset.m_flatbuffer); + writer.WriteAsset(asset.m_uuid, asset.m_flatbuffer, asset.m_hardReferences); } } @@ -114,6 +137,48 @@ class SasquatchFixture: public benchmark::Fixture /****************************************************************************************/ +BENCHMARK_DEFINE_F(SasquatchFixture, GetAssetHardReferences)(benchmark::State& state) +{ + for (auto _: state) + { + benchmark::DoNotOptimize( + m_sasquatch->GetAssetHardReferences(m_uuids[Random::get(0, m_uuids.size() - 1)])); + } + + state.SetItemsProcessed(state.iterations()); +} + +BENCHMARK_REGISTER_F(SasquatchFixture, GetAssetHardReferences)->Name("Sasquatch/GetAssetHardReferences"); + +/****************************************************************************************/ + +BENCHMARK_DEFINE_F(SasquatchFixture, 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_sasquatch->GetAssetsHardReferences(batchPool[batchIndex])); + batchIndex = (batchIndex + 1) % BATCH_POOL_SIZE; + } + + state.SetItemsProcessed(state.iterations() * batchSize); +} + +BENCHMARK_REGISTER_F(SasquatchFixture, GetAssetsHardReferences) + ->Name("Sasquatch/GetAssetsHardReferences") + ->Arg(1) + ->Arg(8) + ->Arg(64) + ->Arg(512) + ->Arg(4096); + +/****************************************************************************************/ + BENCHMARK_DEFINE_F(SasquatchFixture, GetAssetFlatbuffer)(benchmark::State& state) { std::int64_t bytesProcessed = 0; diff --git a/Bigfoot/Sources/Engine/BigFile/BigFile.cpp b/Bigfoot/Sources/Engine/BigFile/BigFile.cpp index 738e7df..d61ffb5 100644 --- a/Bigfoot/Sources/Engine/BigFile/BigFile.cpp +++ b/Bigfoot/Sources/Engine/BigFile/BigFile.cpp @@ -91,14 +91,14 @@ BigFile::~BigFile() /****************************************************************************************/ -eastl::optional> BigFile::GetAssetFlatbuffer(const UUID& p_uuid) const +eastl::vector BigFile::GetAssetFlatbuffer(const UUID& p_uuid) const { BigFile::Request assetRequest {*this, "SELECT Asset FROM Asset WHERE UUID = ?1;"}; assetRequest.Bind(1, p_uuid.ToBytes()); if (!assetRequest.Step()) { - return eastl::nullopt; + return {}; } const eastl::span flatbuffer = assetRequest.Get(0); @@ -168,7 +168,7 @@ eastl::vector> BigFile::GetAssetFlatbuffers(const eastl /****************************************************************************************/ -eastl::optional BigFile::GetAssetMetadata(const UUID& p_uuid) const +AssetMetadata BigFile::GetAssetMetadata(const UUID& p_uuid) const { BigFile::Request assetRequest { *this, @@ -177,7 +177,7 @@ eastl::optional BigFile::GetAssetMetadata(const UUID& p_uuid) con if (!assetRequest.Step()) { - return eastl::nullopt; + return {}; } return AssetMetadata {.m_uuid = UUID {std::span { diff --git a/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp b/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp index 6e3ce0a..a67f50c 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/BigFile/BigFile.hpp @@ -63,7 +63,7 @@ class BigFile: public DataAccessor * \param p_uuid The asset to get the flatbuffer of * \return The flatbuffer, or nullopt if the asset was not found */ - eastl::optional> GetAssetFlatbuffer(const UUID& p_uuid) const override; + eastl::vector GetAssetFlatbuffer(const UUID& p_uuid) const override; /** * Get several Asset flatbuffers @@ -79,7 +79,7 @@ class BigFile: public DataAccessor * \param p_uuid The asset to get the metadata of * \return The metadata, or nullopt if the asset was not found */ - eastl::optional GetAssetMetadata(const UUID& p_uuid) const override; + AssetMetadata GetAssetMetadata(const UUID& p_uuid) const override; /** * Get several Asset metadatas diff --git a/Bigfoot/Sources/Engine/Include/Engine/DataAccessor/DataAccessor.hpp b/Bigfoot/Sources/Engine/Include/Engine/DataAccessor/DataAccessor.hpp index 2879034..f2b90ef 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/DataAccessor/DataAccessor.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/DataAccessor/DataAccessor.hpp @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -46,7 +45,7 @@ class DataAccessor * \param p_uuid The asset to get the flatbuffer of * \return The flatbuffer, or nullopt if the asset was not found */ - virtual eastl::optional> GetAssetFlatbuffer(const UUID& p_uuid) const = 0; + virtual eastl::vector GetAssetFlatbuffer(const UUID& p_uuid) const = 0; /** * Get several Asset flatbuffers @@ -62,7 +61,7 @@ class DataAccessor * \param p_uuid The asset to get the metadata of * \return The metadata, or nullopt if the asset was not found */ - virtual eastl::optional GetAssetMetadata(const UUID& p_uuid) const = 0; + virtual AssetMetadata GetAssetMetadata(const UUID& p_uuid) const = 0; /** * Get several Asset metadatas diff --git a/Bigfoot/Sources/Engine/Include/Engine/Sasquatch/Sasquatch.hpp b/Bigfoot/Sources/Engine/Include/Engine/Sasquatch/Sasquatch.hpp index 1036b86..3628cfc 100644 --- a/Bigfoot/Sources/Engine/Include/Engine/Sasquatch/Sasquatch.hpp +++ b/Bigfoot/Sources/Engine/Include/Engine/Sasquatch/Sasquatch.hpp @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -35,7 +34,6 @@ struct SasquatchHeader std::uint64_t m_assetCount = 0; }; -static_assert(sizeof(SasquatchHeader) == 16); static_assert(std::is_trivially_copyable_v); /****************************************************************************************/ @@ -43,22 +41,19 @@ static_assert(std::is_trivially_copyable_v); struct SasquatchEntry { std::array m_uuid {}; - std::size_t m_offset = 0; - std::size_t m_size = 0; + + std::size_t m_assetOffset = 0; + std::size_t m_assetSize = 0; + + std::size_t m_hardReferencesOffset = 0; + std::size_t m_hardReferencesSize = 0; }; -static_assert(sizeof(SasquatchEntry) == 32); static_assert(std::is_trivially_copyable_v); /****************************************************************************************/ #if defined(BIGFOOT_TOOLMODE) || defined(BIGFOOT_BUILD_TESTS) || defined(BIGFOOT_BUILD_BENCHMARKS) -struct SasquatchData -{ - UUID m_uuid; - eastl::span m_flatbuffer; -}; - class SasquatchWriter { public: @@ -69,8 +64,12 @@ class SasquatchWriter * \param p_file The file to write * \param p_assetCount The number of assets that will be written * \param p_totalFlatbufferBytes The sum of the sizes of every flatbuffer that will be written + * \param p_totalHardReferencesBytes The sum of the sizes of every asset hardreferences that will be written */ - SasquatchWriter(const File& p_file, std::uint64_t p_assetCount, std::size_t p_totalFlatbufferBytes); + SasquatchWriter(const File& p_file, + const std::uint64_t p_assetCount, + const std::size_t p_totalFlatbufferBytes, + const std::size_t p_totalHardReferencesBytes); SasquatchWriter(const SasquatchWriter& p_writer) = delete; SasquatchWriter(SasquatchWriter&& p_writer) = delete; @@ -88,7 +87,9 @@ class SasquatchWriter * \param p_uuid The UUID of the asset * \param p_flatbuffer The flatbuffer of the asset */ - void WriteAsset(const UUID& p_uuid, eastl::span p_flatbuffer); + void WriteAsset(const UUID& p_uuid, + eastl::span p_flatbuffer, + eastl::span p_hardReferences); SasquatchWriter& operator=(const SasquatchWriter& p_writer) = delete; SasquatchWriter& operator=(SasquatchWriter&& p_writer) = delete; @@ -99,12 +100,7 @@ class SasquatchWriter /** * The number of assets expected */ - BIGFOOT_NOT_OPTIMIZED_ONLY(std::uint64_t m_assetCount;) - - /** - * The offset the next WriteAsset call will write to - */ - std::size_t m_nextOffset; + std::uint64_t m_assetCount; /** * How far into m_file has already been prefetched @@ -147,7 +143,7 @@ class Sasquatch: public DataAccessor * \param p_uuid The asset to get the flatbuffer of * \return The flatbuffer, or nullopt if the asset was not found */ - eastl::optional> GetAssetFlatbuffer(const UUID& p_uuid) const override; + eastl::vector GetAssetFlatbuffer(const UUID& p_uuid) const override; /** * Get several Asset flatbuffers @@ -161,7 +157,7 @@ class Sasquatch: public DataAccessor * Sasquatch only serves flatbuffers: this will always fail * */ - eastl::optional GetAssetMetadata(const UUID& p_uuid) const override; + AssetMetadata GetAssetMetadata(const UUID& p_uuid) const override; /** * Sasquatch only serves flatbuffers: this will always fail @@ -169,6 +165,22 @@ class Sasquatch: 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; + /** * Sasquatch is read-only: this will always fail * @@ -199,8 +211,11 @@ class Sasquatch: public DataAccessor private: struct Entry { - std::size_t m_offset; - std::size_t m_size; + std::size_t m_assetOffset = 0; + std::size_t m_assetSize = 0; + + std::size_t m_hardReferencesOffset = 0; + std::size_t m_hardReferencesSize = 0; }; /** diff --git a/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp b/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp index c4dd605..32c1648 100644 --- a/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp +++ b/Bigfoot/Sources/Engine/Sasquatch/Sasquatch.cpp @@ -16,16 +16,18 @@ namespace Bigfoot #if defined(BIGFOOT_TOOLMODE) || defined(BIGFOOT_BUILD_TESTS) || defined(BIGFOOT_BUILD_BENCHMARKS) SasquatchWriter::SasquatchWriter(const File& p_file, const std::uint64_t p_assetCount, - const std::size_t p_totalFlatbufferBytes): - BIGFOOT_NOT_OPTIMIZED_ONLY(m_assetCount(p_assetCount), ) - m_nextOffset(sizeof(SasquatchHeader) + p_assetCount * sizeof(SasquatchEntry)), + const std::size_t p_totalFlatbufferBytes, + const std::size_t p_totalHardReferencesBytes): + m_assetCount(p_assetCount), m_prefetchedUpTo(0), - m_file(p_file, m_nextOffset + p_totalFlatbufferBytes) + m_file(p_file, + sizeof(SasquatchHeader) + m_assetCount * sizeof(SasquatchEntry) + p_totalFlatbufferBytes + + p_totalHardReferencesBytes) { - m_entries.reserve(p_assetCount); + m_entries.reserve(m_assetCount); SasquatchHeader header; - header.m_assetCount = p_assetCount; + header.m_assetCount = m_assetCount; std::memcpy(m_file.GetData().data(), &header, sizeof(SasquatchHeader)); } @@ -52,20 +54,30 @@ SasquatchWriter::~SasquatchWriter() /****************************************************************************************/ -void SasquatchWriter::WriteAsset(const UUID& p_uuid, const eastl::span p_flatbuffer) +void SasquatchWriter::WriteAsset(const UUID& p_uuid, + eastl::span p_flatbuffer, + eastl::span p_hardReferences) { ASSERT(EngineAssertHandler, m_entries.size() < m_assetCount, "SasquatchWriter can only hold {} assets", m_assetCount); + const std::size_t offset = std::accumulate(m_entries.begin(), + m_entries.end(), + sizeof(SasquatchHeader) + m_assetCount * sizeof(SasquatchEntry), + [](const std::size_t p_value, const SasquatchEntry& p_entry) + { + return p_value + p_entry.m_assetSize + p_entry.m_hardReferencesSize; + }); + const eastl::span data = m_file.GetData(); ASSERT(EngineAssertHandler, - m_nextOffset + p_flatbuffer.size() <= data.size(), + offset + p_flatbuffer.size() + p_hardReferences.size() * UUID::UUID_BYTE_SIZE <= data.size(), "SasquatchWriter can only write {} bytes", data.size()); - const std::size_t writeEnd = m_nextOffset + p_flatbuffer.size(); + const std::size_t writeEnd = offset + p_flatbuffer.size() + p_hardReferences.size() * UUID::UUID_BYTE_SIZE; if (writeEnd > m_prefetchedUpTo) { const std::size_t prefetchEnd = std::min(writeEnd + PREFETCH_BYTES, data.size()); @@ -75,12 +87,22 @@ void SasquatchWriter::WriteAsset(const UUID& p_uuid, const eastl::span rawUUID = p_hardReferences[i].ToBytes(); + std::memcpy(data.data() + entry.m_hardReferencesOffset + i * UUID::UUID_BYTE_SIZE, + rawUUID.data(), + UUID::UUID_BYTE_SIZE); + } + + m_entries.push_back(entry); } #endif @@ -130,27 +152,31 @@ Sasquatch::Sasquatch(const File& p_file): for (const SasquatchEntry& entry: entries) { CRITICAL_ASSERT(EngineAssertHandler, - entry.m_offset + entry.m_size <= data.size(), + entry.m_assetOffset + entry.m_assetSize + entry.m_hardReferencesSize <= data.size(), "Sasquatch file {} has an out-of-bounds asset entry", p_file.GetPath()); - m_entries.emplace(UUID {entry.m_uuid}, Entry {.m_offset = entry.m_offset, .m_size = entry.m_size}); + m_entries.emplace(UUID {entry.m_uuid}, + Entry {.m_assetOffset = entry.m_assetOffset, + .m_assetSize = entry.m_assetSize, + .m_hardReferencesOffset = entry.m_hardReferencesOffset, + .m_hardReferencesSize = entry.m_hardReferencesSize}); } } /****************************************************************************************/ -eastl::optional> Sasquatch::GetAssetFlatbuffer(const UUID& p_uuid) const +eastl::vector Sasquatch::GetAssetFlatbuffer(const UUID& p_uuid) const { const auto it = m_entries.find(p_uuid); if (it == m_entries.end()) { - return eastl::nullopt; + return {}; } const eastl::span data = m_file.GetData(); - const eastl::span bytes {data.data() + it->second.m_offset, - static_cast(it->second.m_size)}; + const eastl::span bytes {data.data() + it->second.m_assetOffset, + static_cast(it->second.m_assetSize)}; return eastl::vector {bytes.begin(), bytes.end()}; } @@ -159,40 +185,11 @@ eastl::optional> Sasquatch::GetAssetFlatbuffer(const UU eastl::vector> Sasquatch::GetAssetFlatbuffers(const eastl::span p_uuids) const { eastl::vector> flatbuffers; - if (p_uuids.empty()) - { - return flatbuffers; - } - flatbuffers.reserve(p_uuids.size()); - if (p_uuids.size() == 1) + for (const UUID& uuid : p_uuids) { - if (eastl::optional> flatbuffer = GetAssetFlatbuffer(p_uuids[0]); - flatbuffer.has_value()) - { - flatbuffers.push_back(std::move(*flatbuffer)); - } - - return flatbuffers; - } - - ankerl::unordered_dense::set seen; - seen.reserve(p_uuids.size()); - for (const UUID& uuid: p_uuids) - { - if (!seen.insert(uuid).second) - { - continue; - } - - if (const auto it = m_entries.find(uuid); it != m_entries.end()) - { - const eastl::span data = m_file.GetData(); - const eastl::span bytes {data.data() + it->second.m_offset, - static_cast(it->second.m_size)}; - flatbuffers.emplace_back(bytes.begin(), bytes.end()); - } + flatbuffers.push_back(GetAssetFlatbuffer(uuid)); } return flatbuffers; @@ -200,10 +197,10 @@ eastl::vector> Sasquatch::GetAssetFlatbuffers(const eas /****************************************************************************************/ -eastl::optional Sasquatch::GetAssetMetadata([[maybe_unused]] const UUID& p_uuid) const +AssetMetadata Sasquatch::GetAssetMetadata([[maybe_unused]] const UUID& p_uuid) const { ASSERT(EngineAssertHandler, false, "Sasquatch does not support metadata queries, only flatbuffers"); - return eastl::nullopt; + return {}; } /****************************************************************************************/ @@ -211,7 +208,51 @@ eastl::optional Sasquatch::GetAssetMetadata([[maybe_unused]] cons eastl::vector Sasquatch::GetAssetMetadatas([[maybe_unused]] const eastl::span p_uuids) const { ASSERT(EngineAssertHandler, false, "Sasquatch does not support metadata queries, only flatbuffers"); - return {}; + return eastl::vector{p_uuids.size()}; +} + +/****************************************************************************************/ + +eastl::vector Sasquatch::GetAssetHardReferences(const UUID& p_uuid) const +{ + eastl::vector hardReferences; + + const auto it = m_entries.find(p_uuid); + if (it == m_entries.end()) + { + return hardReferences; + } + + const eastl::span data = m_file.GetData(); + const eastl::span bytes {data.data() + it->second.m_hardReferencesOffset, + static_cast(it->second.m_hardReferencesSize)}; + + const std::size_t hardReferenceCount = bytes.size() / UUID::UUID_BYTE_SIZE; + hardReferences.reserve(hardReferenceCount); + + for (std::size_t i = 0; i < hardReferenceCount; ++i) + { + std::array rawUUID; + std::memcpy(rawUUID.data(), bytes.data() + i * UUID::UUID_BYTE_SIZE, UUID::UUID_BYTE_SIZE); + hardReferences.emplace_back(rawUUID); + } + + return hardReferences; +} + +/****************************************************************************************/ + +eastl::vector> Sasquatch::GetAssetsHardReferences(eastl::span p_uuids) const +{ + eastl::vector> hardReferences; + hardReferences.reserve(p_uuids.size()); + + for (const UUID& uuid : p_uuids) + { + hardReferences.push_back(GetAssetHardReferences(uuid)); + } + + return hardReferences; } /****************************************************************************************/ diff --git a/Bigfoot/Sources/Tools/SasquatchBaker/SasquatchBaker.cpp b/Bigfoot/Sources/Tools/SasquatchBaker/SasquatchBaker.cpp index 8b1508d..aa944e7 100644 --- a/Bigfoot/Sources/Tools/SasquatchBaker/SasquatchBaker.cpp +++ b/Bigfoot/Sources/Tools/SasquatchBaker/SasquatchBaker.cpp @@ -32,23 +32,33 @@ void Bake(const BigFile& p_bigFile, const File& p_outputFile) totalFlatbufferBytes = sizeRequest.Get(0); } - SasquatchWriter writer {p_outputFile, assetCount, totalFlatbufferBytes}; + std::uint64_t totalHardReferencesBytes = 0; + { + BigFile::Request sizeRequest {p_bigFile, "SELECT COALESCE(SUM(LENGTH(AssetHardReference)), 0) FROM AssetHardReference;"}; + [[maybe_unused]] + const bool hasSize = sizeRequest.Step(); + ASSERT(SasquatchBakerAssertHandler, hasSize, "Failed to sum the hardreferences sizes of the BigFile"); + totalFlatbufferBytes = sizeRequest.Get(0); + } - BigFile::Request request {p_bigFile, "SELECT UUID, Asset FROM Asset;"}; + SasquatchWriter writer {p_outputFile, assetCount, totalFlatbufferBytes, totalHardReferencesBytes}; + + BigFile::Request request {p_bigFile, "SELECT UUID FROM Asset;"}; while (request.Step()) { - const eastl::span uuidBytes = request.Get(0); - const eastl::span flatbuffer = request.Get(1); - + const eastl::span rawUUID = request.Get(0); + ASSERT(SasquatchBakerAssertHandler, - uuidBytes.size() == UUID::UUID_BYTE_SIZE, + rawUUID.size() == UUID::UUID_BYTE_SIZE, "Unexpected UUID blob size in BigFile (got {} / expected {})", - uuidBytes.size(), + rawUUID.size(), UUID::UUID_BYTE_SIZE); - writer.WriteAsset( - UUID {{std::span {uuidBytes.data(), UUID::UUID_BYTE_SIZE}}}, - flatbuffer); + const UUID uuid {std::span {rawUUID.data(), UUID::UUID_BYTE_SIZE}}; + const eastl::vector flatbuffer = p_bigFile.GetAssetFlatbuffer(uuid); + const eastl::vector hardReferences = p_bigFile.GetAssetHardReferences(uuid); + + writer.WriteAsset(uuid, flatbuffer, hardReferences); } } } // namespace Bigfoot diff --git a/Bigfoot/Tests/Engine/BigFile/BigFile.cpp b/Bigfoot/Tests/Engine/BigFile/BigFile.cpp index e9e45e2..078e68c 100644 --- a/Bigfoot/Tests/Engine/BigFile/BigFile.cpp +++ b/Bigfoot/Tests/Engine/BigFile/BigFile.cpp @@ -68,22 +68,22 @@ TEST_F(BigFileFixture, Clear_ShouldRemoveAllAssetsMetadataAndHardReferences) 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_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_FALSE(m_bigFile.GetAssetFlatbuffer(referencedAsset.GetHeader().uuid).has_value()); - EXPECT_FALSE(m_bigFile.GetAssetFlatbuffer(asset.GetHeader().uuid).has_value()); + EXPECT_TRUE(m_bigFile.GetAssetFlatbuffer(referencedAsset.GetHeader().uuid).empty()); + EXPECT_TRUE(m_bigFile.GetAssetFlatbuffer(asset.GetHeader().uuid).empty()); EXPECT_TRUE(m_bigFile.GetAssetHardReferences(asset.GetHeader().uuid).empty()); } /****************************************************************************************/ -TEST_F(BigFileFixture, GetAssetFlatbuffer_ShouldReturnNulloptForNonExistentUUID) +TEST_F(BigFileFixture, GetAssetFlatbuffer_ShouldReturnEmptyForNonExistentUUID) { const UUID uuid; - EXPECT_FALSE(m_bigFile.GetAssetFlatbuffer(uuid).has_value()); + EXPECT_TRUE(m_bigFile.GetAssetFlatbuffer(uuid).empty()); } /****************************************************************************************/ @@ -166,11 +166,11 @@ TEST_F(BigFileFixture, GetAssetFlatbuffers_ShouldNotDuplicateResultsForADuplicat /****************************************************************************************/ -TEST_F(BigFileFixture, GetAssetMetadata_ShouldReturnNulloptForNonExistentUUID) +TEST_F(BigFileFixture, GetAssetMetadata_ShouldReturnNullForNonExistentUUID) { const UUID uuid; - EXPECT_FALSE(m_bigFile.GetAssetMetadata(uuid).has_value()); + EXPECT_EQ(m_bigFile.GetAssetMetadata(uuid).m_uuid, UUID::NULL_UUID); } /****************************************************************************************/ diff --git a/Bigfoot/Tests/Engine/DataAccessor/DataAccessor.cpp b/Bigfoot/Tests/Engine/DataAccessor/DataAccessor.cpp index 1ada664..d62e63f 100644 --- a/Bigfoot/Tests/Engine/DataAccessor/DataAccessor.cpp +++ b/Bigfoot/Tests/Engine/DataAccessor/DataAccessor.cpp @@ -17,7 +17,7 @@ class DataAccessorFixture: public ::testing::Test class DataAccessorMock: public DataAccessor { public: - MOCK_METHOD(eastl::optional>, + MOCK_METHOD(eastl::vector, GetAssetFlatbuffer, (const UUID& p_uuid), (const, override)); @@ -25,7 +25,7 @@ class DataAccessorFixture: public ::testing::Test GetAssetFlatbuffers, (eastl::span p_uuids), (const, override)); - MOCK_METHOD(eastl::optional, GetAssetMetadata, (const UUID& p_uuid), (const, override)); + MOCK_METHOD(AssetMetadata, GetAssetMetadata, (const UUID& p_uuid), (const, override)); MOCK_METHOD(eastl::vector, GetAssetMetadatas, (eastl::span p_uuids), diff --git a/Bigfoot/Tests/Engine/Sasquatch/Sasquatch.cpp b/Bigfoot/Tests/Engine/Sasquatch/Sasquatch.cpp index 17e95c6..6169276 100644 --- a/Bigfoot/Tests/Engine/Sasquatch/Sasquatch.cpp +++ b/Bigfoot/Tests/Engine/Sasquatch/Sasquatch.cpp @@ -21,6 +21,13 @@ 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(); @@ -29,23 +36,30 @@ class SasquatchFixture: public ::testing::Test 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}, - SasquatchData {.m_uuid = m_assetB.GetHeader().uuid, .m_flatbuffer = m_flatbufferB}}; + 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)}}; std::uint64_t totalFlatbufferBytes = 0; + std::size_t totalHardReferencesBytes = 0; for (const SasquatchData& asset: assets) { totalFlatbufferBytes += asset.m_flatbuffer.size(); + totalFlatbufferBytes += asset.m_hardReferences.size() * UUID::UUID_BYTE_SIZE; } { - SasquatchWriter writer {File {SASQUATCH_ENGINETESTS_LOCATION}, assets.size(), totalFlatbufferBytes}; + SasquatchWriter writer {File {SASQUATCH_ENGINETESTS_LOCATION}, assets.size(), totalFlatbufferBytes, totalHardReferencesBytes}; for (const SasquatchData& asset: assets) { - writer.WriteAsset(asset.m_uuid, asset.m_flatbuffer); + writer.WriteAsset(asset.m_uuid, asset.m_flatbuffer, asset.m_hardReferences); } } @@ -63,42 +77,96 @@ class SasquatchFixture: public ::testing::Test /****************************************************************************************/ -TEST_F(SasquatchFixture, GetAssetFlatbuffer_ShouldReturnNulloptForNonExistentUUID) +TEST_F(SasquatchFixture, GetAssetHardReference_ShouldReturnEmptyVectorForNonExistentUUID) { - EXPECT_FALSE(m_sasquatch->GetAssetFlatbuffer(UUID {}).has_value()); + const UUID uuid; + + const eastl::vector hardReferences = m_sasquatch->GetAssetHardReferences(uuid); + + EXPECT_TRUE(hardReferences.empty()); +} + +/****************************************************************************************/ + +TEST_F(SasquatchFixture, GetAssetHardReference_ShouldGetTheAssetHardReferences) +{ + const eastl::vector hardReferences = m_sasquatch->GetAssetHardReferences(m_assetB.GetHeader().uuid); + + ASSERT_EQ(hardReferences.size(), 1); + EXPECT_TRUE(std::find(hardReferences.begin(), hardReferences.end(), m_assetA.GetHeader().uuid) != + hardReferences.end()); +} + +/****************************************************************************************/ + +TEST_F(SasquatchFixture, GetAssetHardReferences_ShouldReturnEmptyVectorsForUUIDsThatDoNotExistOrHaveNoReferences) +{ + const UUID missingUUID; + const eastl::array uuids {missingUUID, + m_assetB.GetHeader().uuid}; + + const eastl::vector> hardReferences = m_sasquatch->GetAssetsHardReferences(uuids); + + ASSERT_EQ(hardReferences.size(), 2); + EXPECT_TRUE(hardReferences[0].empty()); + EXPECT_EQ(hardReferences[1][0], m_assetA.GetHeader().uuid); +} + +/****************************************************************************************/ + +TEST_F(SasquatchFixture, GetAssetHardReferences_ShouldDuplicateResultsForADuplicateUUID) +{ + const eastl::array uuids {m_assetB.GetHeader().uuid, m_assetB.GetHeader().uuid}; + + const eastl::vector> hardReferences = m_sasquatch->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(), m_assetA.GetHeader().uuid) != entry.end()); + } +} + +/****************************************************************************************/ + +TEST_F(SasquatchFixture, GetAssetFlatbuffer_ShouldReturnEmptyForNonExistentUUID) +{ + EXPECT_TRUE(m_sasquatch->GetAssetFlatbuffer(UUID {}).empty()); } /****************************************************************************************/ TEST_F(SasquatchFixture, GetAssetFlatbuffer_ShouldGetTheAssetFlatbuffer) { - const eastl::optional> savedFlatbuffer = m_sasquatch->GetAssetFlatbuffer( + const eastl::vector savedFlatbuffer = m_sasquatch->GetAssetFlatbuffer( m_assetA.GetHeader().uuid); - ASSERT_TRUE(savedFlatbuffer.has_value()); - EXPECT_EQ(*savedFlatbuffer, m_flatbufferA); + EXPECT_EQ(savedFlatbuffer, m_flatbufferA); } /****************************************************************************************/ -TEST_F(SasquatchFixture, GetAssetFlatbuffers_ShouldOmitUUIDsThatDoNotExist) +TEST_F(SasquatchFixture, GetAssetFlatbuffers_ShouldReturnEmptyForNonExistentUUID) { const eastl::vector uuids {m_assetA.GetHeader().uuid, UUID {}, m_assetB.GetHeader().uuid}; const eastl::vector> flatbuffers = m_sasquatch->GetAssetFlatbuffers(uuids); - ASSERT_EQ(flatbuffers.size(), 2); - EXPECT_TRUE((flatbuffers[0] == m_flatbufferA && flatbuffers[1] == m_flatbufferB) || - (flatbuffers[0] == m_flatbufferB && flatbuffers[1] == m_flatbufferA)); + ASSERT_EQ(flatbuffers.size(), 3); + EXPECT_EQ(flatbuffers[0], m_flatbufferA); + EXPECT_TRUE(flatbuffers[1].empty()); + EXPECT_EQ(flatbuffers[2], m_flatbufferB); } /****************************************************************************************/ -TEST_F(SasquatchFixture, GetAssetFlatbuffers_ShouldNotDuplicateResultsForADuplicateUUID) +TEST_F(SasquatchFixture, GetAssetFlatbuffers_ShouldDuplicateResultsForADuplicateUUID) { const eastl::vector uuids {m_assetA.GetHeader().uuid, m_assetA.GetHeader().uuid}; const eastl::vector> flatbuffers = m_sasquatch->GetAssetFlatbuffers(uuids); - ASSERT_EQ(flatbuffers.size(), 1); + ASSERT_EQ(flatbuffers.size(), 2); EXPECT_EQ(flatbuffers[0], m_flatbufferA); + EXPECT_EQ(flatbuffers[1], m_flatbufferA); } /****************************************************************************************/ diff --git a/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp b/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp index a8aab1b..93c6097 100644 --- a/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp +++ b/Bigfoot/Tests/Tools/SasquatchBaker/SasquatchBaker.cpp @@ -96,8 +96,9 @@ TEST_F(SasquatchBakerFixture, Bake_ShouldWriteEveryAssetOfTheBigFile) flatbufferA, AssetA::GetHardReferences(flatbufferA)); - AssetA assetB; + AssetB assetB; assetB.SetName("world"); + assetB.GetAsset().ref_a = HardReference {assetA.GetHeader().uuid}; const eastl::vector flatbufferB = assetB.Pack(); @@ -106,7 +107,7 @@ TEST_F(SasquatchBakerFixture, Bake_ShouldWriteEveryAssetOfTheBigFile) .m_typeID = assetB.GetHeader().type_id, .m_typeName = assetB.GetHeader().type_name}, flatbufferB, - AssetA::GetHardReferences(flatbufferB)); + AssetB::GetHardReferences(flatbufferB)); Bake(m_bigFile, m_sasquatch);