Sasquatch
Bigfoot / Sonarqube (push) Skipped
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Successful in 34s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Successful in 22s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Successful in 44s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 57s
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 Release with ./ConanProfiles/host/clang (Unity Build: ON, Variant: game) (push) Failing after 15s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Failing after 14s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Failing after 21s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 34s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Successful in 23s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Successful in 54s
Bigfoot / Build & Test Debug with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 46s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 38s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Successful in 27s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: game) (push) Successful in 53s
Bigfoot / Build & Test RelWithDebInfo 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 1m0s
Bigfoot / Build & Test RelWithDebInfo with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 47s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: OFF, Variant: game) (push) Failing after 16s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang (Unity Build: ON, Variant: toolmode) (push) Failing after 16s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 21s
Bigfoot / Clang Format Checks (push) Successful in 11s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: ON, Variant: game) (push) Failing after 20s
Bigfoot / Build & Test Release with ./ConanProfiles/host/clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 15s

This commit is contained in:
2026-08-29 00:20:02 +02:00
parent 7804647768
commit f6cde4f025
28 changed files with 1230 additions and 38 deletions
@@ -0,0 +1,232 @@
/*********************************************************************
* \file Sasquatch.cpp
*
* \author Romain BOULLARD
* \date August 2026
*********************************************************************/
#include <Engine/Sasquatch/Sasquatch.hpp>
#include <Engine/EngineAssertHandler.hpp>
#include <algorithm>
#include <cstring>
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):
m_assetCount(p_assetCount),
m_nextOffset(sizeof(SasquatchHeader) + p_assetCount * sizeof(SasquatchEntry)),
m_prefetchedUpTo(0),
m_file(p_file, m_nextOffset + p_totalFlatbufferBytes)
{
m_entries.reserve(p_assetCount);
SasquatchHeader header;
header.m_assetCount = p_assetCount;
std::memcpy(m_file.GetData().data(), &header, sizeof(SasquatchHeader));
}
/****************************************************************************************/
SasquatchWriter::~SasquatchWriter()
{
ASSERT(EngineAssertHandler,
m_entries.size() == m_assetCount,
"SasquatchWriter expected {} assets, only {} were added",
m_assetCount,
m_entries.size());
m_file.Prefetch(sizeof(SasquatchHeader), m_entries.size() * sizeof(SasquatchEntry));
std::memcpy(m_file.GetData().data() + sizeof(SasquatchHeader),
m_entries.data(),
m_entries.size() * sizeof(SasquatchEntry));
}
/****************************************************************************************/
void SasquatchWriter::WriteAsset(const UUID& p_uuid, const eastl::span<const std::byte> p_flatbuffer)
{
ASSERT(EngineAssertHandler,
m_entries.size() < m_assetCount,
"SasquatchWriter can only hold {} assets",
m_assetCount);
const eastl::span<std::byte> data = m_file.GetData();
ASSERT(EngineAssertHandler,
m_nextOffset + p_flatbuffer.size() <= data.size(),
"SasquatchWriter can only write {} bytes",
data.size());
const std::size_t writeEnd = m_nextOffset + p_flatbuffer.size();
if (writeEnd > m_prefetchedUpTo)
{
const std::size_t prefetchEnd = std::min(writeEnd + PREFETCH_BYTES, data.size());
m_file.Prefetch(m_prefetchedUpTo, prefetchEnd - m_prefetchedUpTo);
m_prefetchedUpTo = prefetchEnd;
}
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);
std::memcpy(data.data() + m_nextOffset, p_flatbuffer.data(), p_flatbuffer.size());
m_nextOffset += entry.m_size;
}
#endif
/****************************************************************************************/
#ifdef BIGFOOT_GAME
Sasquatch::Sasquatch(const File& p_file):
m_file(p_file)
{
const eastl::span<const std::byte> data = m_file.GetData();
CRITICAL_ASSERT(EngineAssertHandler,
data.size() >= sizeof(SasquatchHeader),
"Sasquatch file {} is smaller than its header",
p_file.GetPath());
SasquatchHeader header;
std::memcpy(&header, data.data(), sizeof(SasquatchHeader));
CRITICAL_ASSERT(EngineAssertHandler,
header.m_magic == SasquatchHeader::MAGIC,
"Sasquatch file {} has an invalid magic number (got {} / expected {})",
p_file.GetPath(),
header.m_magic,
SasquatchHeader::MAGIC);
CRITICAL_ASSERT(EngineAssertHandler,
header.m_version == SasquatchHeader::VERSION,
"Sasquatch file {} has an unsupported version (got {} / expected {})",
p_file.GetPath(),
header.m_version,
SasquatchHeader::VERSION);
CRITICAL_ASSERT(EngineAssertHandler,
data.size() >= sizeof(SasquatchHeader) + header.m_assetCount * sizeof(SasquatchEntry),
"Sasquatch file {} index is truncated (got {} / expected at least {})",
p_file.GetPath(),
data.size(),
sizeof(SasquatchHeader) + header.m_assetCount * sizeof(SasquatchEntry));
eastl::vector<SasquatchEntry> entries(header.m_assetCount);
std::memcpy(entries.data(), data.data() + sizeof(SasquatchHeader), entries.size() * sizeof(SasquatchEntry));
m_entries.reserve(header.m_assetCount);
for (const SasquatchEntry& entry: entries)
{
CRITICAL_ASSERT(EngineAssertHandler,
entry.m_offset + entry.m_size <= 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});
}
}
/****************************************************************************************/
eastl::optional<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;
}
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)};
return eastl::vector<std::byte> {bytes.begin(), bytes.end()};
}
/****************************************************************************************/
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)
{
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());
}
}
return flatbuffers;
}
/****************************************************************************************/
eastl::optional<AssetMetadata> Sasquatch::GetAssetMetadata(const UUID&) const
{
ASSERT(EngineAssertHandler, false, "Sasquatch does not support metadata queries, only flatbuffers");
return eastl::nullopt;
}
/****************************************************************************************/
eastl::vector<AssetMetadata> Sasquatch::GetAssetMetadatas(const eastl::span<const UUID>) const
{
ASSERT(EngineAssertHandler, false, "Sasquatch does not support metadata queries, only flatbuffers");
return {};
}
/****************************************************************************************/
void Sasquatch::SaveAssetFlatbuffer(const AssetMetadata&, eastl::span<const std::byte>)
{
ASSERT(EngineAssertHandler, false, "Sasquatch is read-only, it cannot save assets");
}
/****************************************************************************************/
void Sasquatch::SaveAssetFlatbuffers(eastl::span<const AssetMetadata>, eastl::span<const eastl::vector<std::byte>>)
{
ASSERT(EngineAssertHandler, false, "Sasquatch is read-only, it cannot save assets");
}
/****************************************************************************************/
bool Sasquatch::Has(const UUID& p_uuid) const
{
return m_entries.find(p_uuid) != m_entries.end();
}
#endif
} // namespace Bigfoot