Sasquatch Write and Get HardReferences
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Successful in 23s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 1m0s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 51s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Successful in 34s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Successful in 23s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Failing after 39s
Bigfoot / Sonarqube (push) Skipped
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Successful in 33s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Failing after 35s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Failing after 27s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Successful in 55s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Successful in 42s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 1m2s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 50s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Successful in 30s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Successful in 22s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 45s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Successful in 39s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Successful in 41s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Failing after 28s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Successful in 56s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Successful in 43s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Successful in 35s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Successful in 45s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Successful in 39s
Bigfoot / Clang Format Checks (push) Failing after 10s

This commit is contained in:
2026-08-29 18:50:11 +02:00
parent cb4105ee87
commit 8e6ba22cc3
11 changed files with 327 additions and 128 deletions
@@ -12,6 +12,7 @@
#include <EngineBenchmarks/SasquatchInfo_generated.hpp>
#include <AssetsForBenchmarking/Asset/BenchmarkAsset.hpp>
#include <AssetsForBenchmarking/Asset/BenchmarkAssetReferred.hpp>
#include <EASTL/optional.h>
#include <EASTL/vector.h>
@@ -29,6 +30,13 @@ using Random = effolkronium::random_static;
class SasquatchFixture: public benchmark::Fixture
{
protected:
struct SasquatchData
{
UUID m_uuid;
eastl::span<const std::byte> m_flatbuffer;
eastl::span<const UUID> 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<eastl::vector<std::byte>> flatbuffers;
eastl::vector<eastl::vector<UUID>> 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<std::byte> 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<std::size_t>(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<std::size_t>(state.range(0));
constexpr std::size_t BATCH_POOL_SIZE = 64;
const eastl::vector<eastl::vector<UUID>> 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;
+4 -4
View File
@@ -91,14 +91,14 @@ BigFile::~BigFile()
/****************************************************************************************/
eastl::optional<eastl::vector<std::byte>> BigFile::GetAssetFlatbuffer(const UUID& p_uuid) const
eastl::vector<std::byte> 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<const std::byte> flatbuffer = assetRequest.Get(0);
@@ -168,7 +168,7 @@ eastl::vector<eastl::vector<std::byte>> BigFile::GetAssetFlatbuffers(const eastl
/****************************************************************************************/
eastl::optional<AssetMetadata> 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<AssetMetadata> BigFile::GetAssetMetadata(const UUID& p_uuid) con
if (!assetRequest.Step())
{
return eastl::nullopt;
return {};
}
return AssetMetadata {.m_uuid = UUID {std::span<const std::byte, UUID::UUID_BYTE_SIZE> {
@@ -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<eastl::vector<std::byte>> GetAssetFlatbuffer(const UUID& p_uuid) const override;
eastl::vector<std::byte> 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<AssetMetadata> GetAssetMetadata(const UUID& p_uuid) const override;
AssetMetadata GetAssetMetadata(const UUID& p_uuid) const override;
/**
* Get several Asset metadatas
@@ -11,7 +11,6 @@
#include <System/Time/Time.hpp>
#include <System/UUID/UUID.hpp>
#include <EASTL/optional.h>
#include <EASTL/span.h>
#include <EASTL/string.h>
#include <EASTL/vector.h>
@@ -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<eastl::vector<std::byte>> GetAssetFlatbuffer(const UUID& p_uuid) const = 0;
virtual eastl::vector<std::byte> 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<AssetMetadata> GetAssetMetadata(const UUID& p_uuid) const = 0;
virtual AssetMetadata GetAssetMetadata(const UUID& p_uuid) const = 0;
/**
* Get several Asset metadatas
@@ -18,7 +18,6 @@
#include <EASTL/vector.h>
#include <ankerl/unordered_dense.h>
#include <array>
#include <cstddef>
#include <cstdint>
#include <type_traits>
@@ -35,7 +34,6 @@ struct SasquatchHeader
std::uint64_t m_assetCount = 0;
};
static_assert(sizeof(SasquatchHeader) == 16);
static_assert(std::is_trivially_copyable_v<SasquatchHeader>);
/****************************************************************************************/
@@ -43,22 +41,19 @@ static_assert(std::is_trivially_copyable_v<SasquatchHeader>);
struct SasquatchEntry
{
std::array<std::byte, UUID::UUID_BYTE_SIZE> 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<SasquatchEntry>);
/****************************************************************************************/
#if defined(BIGFOOT_TOOLMODE) || defined(BIGFOOT_BUILD_TESTS) || defined(BIGFOOT_BUILD_BENCHMARKS)
struct SasquatchData
{
UUID m_uuid;
eastl::span<const std::byte> 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<const std::byte> p_flatbuffer);
void WriteAsset(const UUID& p_uuid,
eastl::span<const std::byte> p_flatbuffer,
eastl::span<const UUID> 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<eastl::vector<std::byte>> GetAssetFlatbuffer(const UUID& p_uuid) const override;
eastl::vector<std::byte> 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<AssetMetadata> 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<AssetMetadata> GetAssetMetadatas(eastl::span<const UUID> 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<UUID> 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<eastl::vector<UUID>> GetAssetsHardReferences(eastl::span<const UUID> 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;
};
/**
+95 -54
View File
@@ -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<const std::byte> p_flatbuffer)
void SasquatchWriter::WriteAsset(const UUID& p_uuid,
eastl::span<const std::byte> p_flatbuffer,
eastl::span<const UUID> 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<std::byte> 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<const std
SasquatchEntry entry;
std::memcpy(entry.m_uuid.data(), p_uuid.ToBytes().data(), UUID::UUID_BYTE_SIZE);
entry.m_offset = m_nextOffset;
entry.m_size = p_flatbuffer.size();
m_entries.push_back(entry);
entry.m_assetOffset = offset;
entry.m_assetSize = p_flatbuffer.size();
entry.m_hardReferencesOffset = entry.m_assetOffset + entry.m_assetSize;
entry.m_hardReferencesSize = p_hardReferences.size() * UUID::UUID_BYTE_SIZE;
std::memcpy(data.data() + m_nextOffset, p_flatbuffer.data(), p_flatbuffer.size());
m_nextOffset += entry.m_size;
std::memcpy(data.data() + entry.m_assetOffset, p_flatbuffer.data(), entry.m_assetSize);
for (std::uint32_t i = 0; i < p_hardReferences.size(); ++i)
{
const std::span<const std::byte, UUID::UUID_BYTE_SIZE> 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<eastl::vector<std::byte>> Sasquatch::GetAssetFlatbuffer(const UUID& p_uuid) const
eastl::vector<std::byte> 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<const std::byte> data = m_file.GetData();
const eastl::span<const std::byte> bytes {data.data() + it->second.m_offset,
static_cast<std::size_t>(it->second.m_size)};
const eastl::span<const std::byte> bytes {data.data() + it->second.m_assetOffset,
static_cast<std::size_t>(it->second.m_assetSize)};
return eastl::vector<std::byte> {bytes.begin(), bytes.end()};
}
@@ -159,40 +185,11 @@ eastl::optional<eastl::vector<std::byte>> Sasquatch::GetAssetFlatbuffer(const UU
eastl::vector<eastl::vector<std::byte>> Sasquatch::GetAssetFlatbuffers(const eastl::span<const UUID> p_uuids) const
{
eastl::vector<eastl::vector<std::byte>> 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<eastl::vector<std::byte>> flatbuffer = GetAssetFlatbuffer(p_uuids[0]);
flatbuffer.has_value())
{
flatbuffers.push_back(std::move(*flatbuffer));
}
return flatbuffers;
}
ankerl::unordered_dense::set<UUID> 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<const std::byte> data = m_file.GetData();
const eastl::span<const std::byte> bytes {data.data() + it->second.m_offset,
static_cast<std::size_t>(it->second.m_size)};
flatbuffers.emplace_back(bytes.begin(), bytes.end());
}
flatbuffers.push_back(GetAssetFlatbuffer(uuid));
}
return flatbuffers;
@@ -200,10 +197,10 @@ eastl::vector<eastl::vector<std::byte>> Sasquatch::GetAssetFlatbuffers(const eas
/****************************************************************************************/
eastl::optional<AssetMetadata> 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<AssetMetadata> Sasquatch::GetAssetMetadata([[maybe_unused]] cons
eastl::vector<AssetMetadata> Sasquatch::GetAssetMetadatas([[maybe_unused]] const eastl::span<const UUID> p_uuids) const
{
ASSERT(EngineAssertHandler, false, "Sasquatch does not support metadata queries, only flatbuffers");
return {};
return eastl::vector<AssetMetadata>{p_uuids.size()};
}
/****************************************************************************************/
eastl::vector<UUID> Sasquatch::GetAssetHardReferences(const UUID& p_uuid) const
{
eastl::vector<UUID> hardReferences;
const auto it = m_entries.find(p_uuid);
if (it == m_entries.end())
{
return hardReferences;
}
const eastl::span<const std::byte> data = m_file.GetData();
const eastl::span<const std::byte> bytes {data.data() + it->second.m_hardReferencesOffset,
static_cast<std::size_t>(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<std::byte, UUID::UUID_BYTE_SIZE> rawUUID;
std::memcpy(rawUUID.data(), bytes.data() + i * UUID::UUID_BYTE_SIZE, UUID::UUID_BYTE_SIZE);
hardReferences.emplace_back(rawUUID);
}
return hardReferences;
}
/****************************************************************************************/
eastl::vector<eastl::vector<UUID>> Sasquatch::GetAssetsHardReferences(eastl::span<const UUID> p_uuids) const
{
eastl::vector<eastl::vector<UUID>> hardReferences;
hardReferences.reserve(p_uuids.size());
for (const UUID& uuid : p_uuids)
{
hardReferences.push_back(GetAssetHardReferences(uuid));
}
return hardReferences;
}
/****************************************************************************************/
@@ -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<const std::byte> uuidBytes = request.Get(0);
const eastl::span<const std::byte> flatbuffer = request.Get(1);
const eastl::span<const std::byte> 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<const std::byte, UUID::UUID_BYTE_SIZE> {uuidBytes.data(), UUID::UUID_BYTE_SIZE}}},
flatbuffer);
const UUID uuid {std::span<const std::byte, UUID::UUID_BYTE_SIZE> {rawUUID.data(), UUID::UUID_BYTE_SIZE}};
const eastl::vector<std::byte> flatbuffer = p_bigFile.GetAssetFlatbuffer(uuid);
const eastl::vector<UUID> hardReferences = p_bigFile.GetAssetHardReferences(uuid);
writer.WriteAsset(uuid, flatbuffer, hardReferences);
}
}
} // namespace Bigfoot
+8 -8
View File
@@ -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);
}
/****************************************************************************************/
@@ -17,7 +17,7 @@ class DataAccessorFixture: public ::testing::Test
class DataAccessorMock: public DataAccessor
{
public:
MOCK_METHOD(eastl::optional<eastl::vector<std::byte>>,
MOCK_METHOD(eastl::vector<std::byte>,
GetAssetFlatbuffer,
(const UUID& p_uuid),
(const, override));
@@ -25,7 +25,7 @@ class DataAccessorFixture: public ::testing::Test
GetAssetFlatbuffers,
(eastl::span<const UUID> p_uuids),
(const, override));
MOCK_METHOD(eastl::optional<AssetMetadata>, GetAssetMetadata, (const UUID& p_uuid), (const, override));
MOCK_METHOD(AssetMetadata, GetAssetMetadata, (const UUID& p_uuid), (const, override));
MOCK_METHOD(eastl::vector<AssetMetadata>,
GetAssetMetadatas,
(eastl::span<const UUID> p_uuids),
+83 -15
View File
@@ -21,6 +21,13 @@ namespace Bigfoot
class SasquatchFixture: public ::testing::Test
{
protected:
struct SasquatchData
{
UUID m_uuid;
eastl::span<const std::byte> m_flatbuffer;
eastl::vector<UUID> 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<AssetA> {m_assetA.GetHeader().uuid};
m_flatbufferB = m_assetB.Pack();
const eastl::vector<SasquatchData> 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<UUID> hardReferences = m_sasquatch->GetAssetHardReferences(uuid);
EXPECT_TRUE(hardReferences.empty());
}
/****************************************************************************************/
TEST_F(SasquatchFixture, GetAssetHardReference_ShouldGetTheAssetHardReferences)
{
const eastl::vector<UUID> 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<UUID, 2> uuids {missingUUID,
m_assetB.GetHeader().uuid};
const eastl::vector<eastl::vector<UUID>> 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<UUID, 2> uuids {m_assetB.GetHeader().uuid, m_assetB.GetHeader().uuid};
const eastl::vector<eastl::vector<UUID>> hardReferences = m_sasquatch->GetAssetsHardReferences(uuids);
ASSERT_EQ(hardReferences.size(), 2);
for (const eastl::vector<UUID>& 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<eastl::vector<std::byte>> savedFlatbuffer = m_sasquatch->GetAssetFlatbuffer(
const eastl::vector<std::byte> 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<UUID> uuids {m_assetA.GetHeader().uuid, UUID {}, m_assetB.GetHeader().uuid};
const eastl::vector<eastl::vector<std::byte>> 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<UUID> uuids {m_assetA.GetHeader().uuid, m_assetA.GetHeader().uuid};
const eastl::vector<eastl::vector<std::byte>> 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);
}
/****************************************************************************************/
@@ -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> {assetA.GetHeader().uuid};
const eastl::vector<std::byte> 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);