Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
7d5d2bd
RC: Add shader compiler base
exdal Oct 24, 2025
fe0e0f3
Add shared lock borrower
exdal Oct 25, 2025
547cd12
Merge branch 'main' into rc
exdal Oct 25, 2025
c68871f
RC: working shader compiler
exdal Oct 29, 2025
ed4c6e7
RC: get shader session messages
exdal Oct 30, 2025
ae061f2
Merge branch 'main' of https://github.com/oxylusengine/Oxylus into rc
exdal Oct 30, 2025
f2401d5
Merge branch 'main' of https://github.com/oxylusengine/Oxylus into rc
exdal Oct 30, 2025
c7c0e93
fix build
exdal Oct 30, 2025
d59b697
add initial meta parsing
exdal Nov 2, 2025
08b46bc
RC: add CLI
exdal Nov 3, 2025
24ae8f2
RC: cache shader modules
exdal Nov 3, 2025
8a0bc1d
RC: add mutex for shader module cache
exdal Nov 3, 2025
71b68fd
RC: add shaders.json
exdal Nov 3, 2025
40eb41d
fix ci
exdal Nov 18, 2025
83cfbd8
Merge branch 'main' into rc
exdal Nov 22, 2025
99a0a45
make lua static
exdal Nov 22, 2025
9263b9d
add file_last_modified
exdal Nov 22, 2025
9770349
remove gnu-like compiler args from msvc
exdal Nov 22, 2025
7619966
remove multiqueues
exdal Nov 30, 2025
56437ac
rc: compiler cache
exdal Dec 3, 2025
6a9c3b2
rc: basic xmake integration
exdal Dec 6, 2025
83ff0c5
rc: add file writing
exdal Dec 10, 2025
b2a7000
rearrange asset metadata
exdal Dec 12, 2025
6cac0ce
cleanup model meta parsing
exdal Dec 13, 2025
8f1aa88
add material meta serialization
exdal Dec 13, 2025
60ba055
remove third party asset handling from asset manager
exdal Dec 14, 2025
035eabf
rc: add model processor
exdal Dec 19, 2025
7f6bfa3
add extended assets
exdal Dec 20, 2025
9ba9d84
fence rcli target
exdal Dec 20, 2025
8be6a3b
Merge branch 'main' of https://github.com/oxylusengine/Oxylus into rc
exdal Dec 21, 2025
f558b03
fix build
exdal Dec 21, 2025
c429276
Merge branch 'main' into rc
Hatrickek Dec 21, 2025
b6b86b5
add .clangd file
Hatrickek Dec 21, 2025
555d633
separate asset file reading
exdal Dec 21, 2025
2dc28a3
remove error logs from asset file reader
exdal Dec 21, 2025
c3cfb71
rc: use lexically normal path instead of absolute
exdal Dec 21, 2025
5b44590
Merge branch 'main' into rc
Hatrickek Dec 21, 2025
e02cfbc
rc: expose model process api
exdal Dec 21, 2025
e6bcb4f
Merge branch 'rc' of https://github.com/oxylusengine/Oxylus into rc
exdal Dec 21, 2025
07135de
move Renderer::new_frame to RendererInstance
Hatrickek Jan 1, 2026
aa3b39f
rc: session level dependency tracking
exdal Jan 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .clangd
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CompileFlags:
CompilationDatabase: build/
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ CMakeSettings.json
/cmake-build-debug-visual-studio
/cmake-build-release-visual-studio
CMakeLists.txt
.clangd

# xmake
.xmake
Expand Down
151 changes: 115 additions & 36 deletions Oxylus/include/Asset/AssetFile.hpp
Original file line number Diff line number Diff line change
@@ -1,54 +1,133 @@
#pragma once

#include <vuk/Types.hpp>
// Keep this file as clean as possible, only include this and nothing more:
#include <glm/ext/quaternion_float.hpp>
#include <span>
#include <string_view>

#include "Asset/AssetMetadata.hpp"
#include "Core/Types.hpp"

namespace ox {
enum class AssetType : u32 {
None = 0,
Shader,
Model,
Texture,
Material,
Font,
Scene,
Audio,
Script,
template <typename T = u8>
struct AssetDataView {
u32 begin = 0;
u32 end = 0;

auto as_str(std::span<u8> asset_data) -> std::string_view {
auto* ptr_begin = reinterpret_cast<c8*>(asset_data.data() + begin);
auto* ptr_end = reinterpret_cast<c8*>(asset_data.data() + end);
return std::string_view(ptr_begin, ptr_end);
}

auto as_span(std::span<u8> asset_data) -> std::span<T> {
auto* ptr_begin = reinterpret_cast<T*>(asset_data.data() + begin);
auto* ptr_end = reinterpret_cast<T*>(asset_data.data() + end);
return std::span(ptr_begin, ptr_end);
}

auto at(std::span<u8> asset_data, u32 index) -> T* {
if (index >= end * sizeof(T)) {
return nullptr;
}

auto* ptr_begin = reinterpret_cast<T*>(asset_data.data() + begin);
return ptr_begin + static_cast<usize>(index);
}

auto empty() const -> bool { return begin == 0 && end == 0; }
auto size() const -> usize { return (end * sizeof(T)) - (begin * sizeof(T)); }
auto size_bytes() const -> usize { return end - begin; }
};

// List of file extensions supported by Engine.
enum class AssetFileType : u32 {
None = 0,
Binary,
Meta,
GLB,
GLTF,
PNG,
JPEG,
DDS,
JSON,
KTX2,
LUA,
struct ShaderAssetEntry {
enum EntryPointKind : u32 {
Vertex = 0,
Fragment,
Compute,
Count,
};

struct EntryPoint {
EntryPointKind kind = EntryPointKind::Count;
AssetDataView<c8> name = {};
AssetDataView<u32> code = {};
};

AssetDataView<EntryPoint> entry_points = {};
};

enum class AssetFileFlags : u64 {
None = 0,
struct ModelAssetEntry {
struct Meshlet {
u32 indirect_vertex_index_offset = 0;
u32 local_triangle_index_offset = 0;
u32 vertex_count = 0;
u32 triangle_count = 0;
};

struct Bounds {
glm::vec3 aabb_center = {};
glm::vec3 aabb_extent = {};
glm::vec3 sphere_center = {};
f32 sphere_radius = 0.0f;
};

struct Lod {
AssetDataView<u32> indices = {};
AssetDataView<Meshlet> meshlets = {};
AssetDataView<Bounds> meshlet_bounds = {};
AssetDataView<u8> local_triangle_indices = {};
AssetDataView<u32> indirect_vertex_indices = {};
f32 error = 0.0f;
};

struct Node {
AssetDataView<c8> name = {};
AssetDataView<u32> child_indices = {};
AssetDataView<u32> mesh_indices = {};
glm::vec3 translation = {};
glm::quat rotation = glm::quat::wxyz(1.0f, 0.0f, 0.0f, 0.0f);
glm::vec3 scale = {};
};

struct Mesh {
AssetDataView<glm::vec3> vertex_positions = {};
AssetDataView<glm::vec3> vertex_normals = {};
AssetDataView<glm::vec2> vertex_texcoords = {};
AssetDataView<Lod> lods = {};
Bounds bounds = {};
};

AssetDataView<Node> nodes = {};
AssetDataView<Mesh> meshes = {};
};

union AssetEntry {
u8 bytes = 0;
ShaderAssetEntry shader;
ModelAssetEntry model;
};
consteval void enable_bitmask(AssetFileFlags);

struct TextureAssetFileHeader {
vuk::Extent3D extent = {};
vuk::Format format = vuk::Format::eUndefined;
struct AssetFileEntryInfo {
UUID uuid = {};
u32 data_size = 0;
u32 data_offset = 0;
AssetType type = AssetType::None;
AssetEntry entry = {};
};

enum class AssetFileFlags : u32 {
None = 0,
Packed = 1 << 0,
};
consteval void enable_bitmask(AssetFileFlags);

struct AssetFileHeader {
c8 magic[2] = {'O', 'X'};
u16 version = 1;
constexpr static u32 MAGIC = 1129470031; // OXRC
u32 magic = 0;
u16 version = 10;
AssetFileFlags flags = AssetFileFlags::None;
AssetType type = AssetType::None;
union {
TextureAssetFileHeader texture_header = {};
};
u32 file_entry_count = 0;
};

} // namespace ox
134 changes: 47 additions & 87 deletions Oxylus/include/Asset/AssetManager.hpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
#pragma once

#include <simdjson.h>

#include "Asset/AssetFile.hpp"
#include "Asset/AssetMetadata.hpp"
#include "Asset/AudioSource.hpp"
#include "Asset/Material.hpp"
#include "Asset/Model.hpp"
#include "Asset/Texture.hpp"
#include "Core/UUID.hpp"
#include "Memory/Borrowed.hpp"
#include "Memory/SlotMap.hpp"
#include "Scene/Scene.hpp"
#include "Scripting/LuaSystem.hpp"
#include "Utils/JsonWriter.hpp"

namespace ox {
struct Asset {
UUID uuid = {};
struct ExtendedAsset {
std::filesystem::path path = {};
std::vector<u8> embedded_data = {}; // Optional
u32 data_size = 0;
u32 data_offset = 0;
AssetEntry entry = {};
};

struct Asset {
AssetType type = AssetType::None;
union {
ModelID model_id = ModelID::Invalid;
Expand All @@ -42,112 +47,67 @@ class AssetManager {
public:
constexpr static auto MODULE_NAME = "AssetManager";

struct AssetMetaFile {
simdjson::padded_string contents;
simdjson::ondemand::parser parser;
simdjson::simdjson_result<simdjson::ondemand::document> doc;
};

auto init() -> std::expected<void, std::string>;
auto deinit() -> std::expected<void, std::string>;

auto registry() const -> const AssetRegistry&;

auto read_meta_file(const std::filesystem::path& path) -> std::unique_ptr<AssetMetaFile>;

auto load_deferred_assets() -> void;

auto create_asset(AssetType type, const std::filesystem::path& path = {}) -> UUID;

static auto to_asset_file_type(const std::filesystem::path& path) -> AssetFileType;
static auto to_asset_type_sv(AssetType type) -> std::string_view;

auto import_asset(const std::filesystem::path& path) -> UUID;

auto delete_asset(const UUID& uuid) -> void;
static auto read_asset_file(const std::filesystem::path& path) -> std::vector<AssetFileEntryInfo>;

// ── Registered Assets ─────────────────────────────────────────────────
// Assets that already exist in project root and have meta file with
// valid UUID's.
//
// Add already existing asset into the registry.
// File must end with `.oxasset` extension.
auto register_asset(const std::filesystem::path& path) -> UUID;
auto register_asset(const UUID& uuid, AssetType type, const std::filesystem::path& path) -> bool;
auto init(this AssetManager&) -> std::expected<void, std::string>;
auto deinit(this AssetManager&) -> std::expected<void, std::string>;

auto export_asset(const UUID& uuid, const std::filesystem::path& path) -> bool;
auto export_texture(const UUID& uuid, JsonWriter& writer, const std::filesystem::path& path) -> bool;
auto export_model(const UUID& uuid, JsonWriter& writer, const std::filesystem::path& path) -> bool;
auto export_scene(const UUID& uuid, JsonWriter& writer, const std::filesystem::path& path) -> bool;
auto export_material(const UUID& uuid, JsonWriter& writer, const std::filesystem::path& path) -> bool;
auto export_script(const UUID& uuid, JsonWriter& writer, const std::filesystem::path& path) -> bool;
auto asset_root_path(this AssetManager&, AssetType type) -> std::filesystem::path;
auto get_registry(this AssetManager&) -> const AssetRegistry&;

auto load_asset(const UUID& uuid) -> bool;
auto unload_asset(const UUID& uuid) -> bool;
auto create(this AssetManager&, AssetType type, const ExtendedAsset &extended_asset) -> UUID;
auto import(this AssetManager&, const std::filesystem::path& path) -> bool;

auto load_model(const UUID& uuid) -> bool;
auto unload_model(const UUID& uuid) -> bool;
// TODO: Rename #_asset to just #
auto delete_asset(this AssetManager&, const UUID& uuid) -> void;

auto load_texture(const UUID& uuid, const TextureLoadInfo& info = {}) -> bool;
auto unload_texture(const UUID& uuid) -> bool;
auto is_texture_loaded(const UUID& uuid) -> bool;
auto load_asset(this AssetManager&, const UUID& uuid) -> bool;
auto unload_asset(this AssetManager&, const UUID& uuid) -> bool;

auto load_material(
const UUID& uuid,
const Material& material_info,
option<ankerl::unordered_dense::map<UUID, TextureLoadInfo>> texture_info_map = nullopt
) -> bool;
auto unload_material(const UUID& uuid) -> bool;
auto is_valid(this AssetManager&, const UUID& uuid) -> bool;
auto is_loaded(this AssetManager&, const UUID& uuid) -> bool;

auto load_scene(const UUID& uuid) -> bool;
auto unload_scene(const UUID& uuid) -> bool;
auto get_asset(this AssetManager&, const UUID& uuid) -> Borrowed<Asset>;
auto get_asset_info(this AssetManager&, const UUID& uuid) -> Borrowed<ExtendedAsset>;

auto load_audio(const UUID& uuid) -> bool;
auto unload_audio(const UUID& uuid) -> bool;
auto get_model(this AssetManager&, const UUID& uuid) -> Model*;
auto get_model(this AssetManager&, ModelID mesh_id) -> Model*;

auto load_script(const UUID& uuid) -> bool;
auto unload_script(const UUID& uuid) -> bool;
auto get_texture(this AssetManager&, const UUID& uuid) -> Borrowed<Texture>;
auto get_texture(this AssetManager&, TextureID texture_id) -> Borrowed<Texture>;

auto get_asset(const UUID& uuid) -> Asset*;
auto get_material(this AssetManager&, const UUID& uuid) -> Borrowed<Material>;
auto get_material(this AssetManager&, MaterialID material_id) -> Borrowed<Material>;
auto set_material_dirty(this AssetManager&, MaterialID material_id) -> void;
auto set_material_dirty(this AssetManager&, const UUID& uuid) -> void;
auto get_dirty_material_ids(this AssetManager&) -> std::vector<MaterialID>;

auto get_model(const UUID& uuid) -> Model*;
auto get_model(ModelID mesh_id) -> Model*;
auto get_scene(this AssetManager&, const UUID& uuid) -> Scene*;
auto get_scene(this AssetManager&, SceneID scene_id) -> Scene*;

auto get_texture(const UUID& uuid) -> Texture*;
auto get_texture(TextureID texture_id) -> Texture*;
auto get_audio(this AssetManager&, const UUID& uuid) -> AudioSource*;
auto get_audio(this AssetManager&, AudioID audio_id) -> AudioSource*;

auto get_material(const UUID& uuid) -> Material*;
auto get_material(MaterialID material_id) -> Material*;
auto set_material_dirty(MaterialID material_id) -> void;
auto set_material_dirty(const UUID& uuid) -> void;
auto set_all_materials_dirty(this AssetManager& self) -> void;
auto get_dirty_material_ids(this AssetManager& self) -> std::vector<MaterialID>;

auto get_scene(const UUID& uuid) -> Scene*;
auto get_scene(SceneID scene_id) -> Scene*;

auto get_audio(const UUID& uuid) -> AudioSource*;
auto get_audio(AudioID audio_id) -> AudioSource*;

auto get_script(const UUID& uuid) -> LuaSystem*;
auto get_script(ScriptID script_id) -> LuaSystem*;
auto get_script(this AssetManager&, const UUID& uuid) -> LuaSystem*;
auto get_script(this AssetManager&, ScriptID script_id) -> LuaSystem*;

private:
AssetRegistry asset_registry = {};

std::shared_mutex registry_mutex = {};
std::shared_mutex textures_mutex = {};
std::shared_mutex materials_mutex = {};
AssetRegistry asset_registry = {};
ankerl::unordered_dense::map<UUID, ExtendedAsset> extended_registry = {};

std::vector<MaterialID> dirty_materials = {};

SlotMap<Model, ModelID> model_map = {};

std::shared_mutex textures_mutex = {};
SlotMap<Texture, TextureID> texture_map = {};

std::shared_mutex materials_mutex = {};
SlotMap<Material, MaterialID> material_map = {};

SlotMap<std::unique_ptr<Scene>, SceneID> scene_map = {};
SlotMap<AudioSource, AudioID> audio_map = {};
SlotMap<std::unique_ptr<LuaSystem>, ScriptID> script_map = {};

std::vector<std::function<void()>> deferred_load_queue = {};
};
} // namespace ox
Loading
Loading