diff --git a/CMakeLists.txt b/CMakeLists.txt index fb16994..e7e6331 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,6 +80,7 @@ target_link_libraries(Engine PUBLIC dp::thread-pool) target_link_libraries(Engine PUBLIC crcpp) target_link_libraries(Engine PUBLIC odeint) target_link_libraries(Engine PUBLIC zlib) +target_link_libraries(Engine PUBLIC zlibstatic) if(UNIX) target_link_libraries(Engine PUBLIC Threads::Threads) target_link_libraries(Engine PUBLIC dl) @@ -90,6 +91,10 @@ target_link_libraries(Editor PRIVATE Engine) target_include_directories(Editor PRIVATE src/Editor) #target_compile_definitions(Editor PRIVATE EDITOR) +add_executable(AssetViewer "") +target_link_libraries(AssetViewer PRIVATE Engine) +target_include_directories(AssetViewer PRIVATE src/AssetViewer) + target_precompile_headers(Engine PUBLIC @@ -122,16 +127,15 @@ endif() add_subdirectory(src/) -#add_executable(Seele_unit_tests "") -#add_subdirectory(test/) - add_custom_target(SeeleEngine ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/res $ + COMMAND ${CMAKE_COMMAND} -E copy $ $ COMMAND_EXPAND_LISTS DEPENDS Editor slang-build) install( TARGETS + AssetViewer Editor Engine EnTT @@ -145,9 +149,6 @@ install( nlohmann_json ThreadPool zlib - slang - slang-glslang - slang-llvm zlibstatic IrrXML odeint diff --git a/CMakeSettings.json b/CMakeSettings.json index 72b0bcc..6d53b96 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -8,9 +8,9 @@ "generator": "Visual Studio 17 2022 Win64", "intelliSenseMode": "windows-msvc-x64", "cmakeExecutable": "D:/Programms/CMake/bin/cmake.exe", - "inheritEnvironments": [], + "inheritEnvironments": [ "msvc_x64" ], "cmakeCommandArgs": "-DCMAKE_DEBUG_POSTFIX=d -DCMAKE_PLATFORM=x64 -DCMAKE_BUILD_TYPE=Debug", - "buildRoot": "bin/Debug" + "buildRoot": "C:/Users/Dynamitos/Seele/bin/Debug" }, { "name": "Release", diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index d2e776e..3312bdf 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -1,7 +1,7 @@ include (ExternalProject) #--------------ZLIB------------------------------ -add_subdirectory(${ZLIB_ROOT}) +add_subdirectory(${ZLIB_ROOT} ${ZLIB_ROOT}) #--------------FreeType------------------------------ add_subdirectory(${FREETYPE_ROOT}) @@ -60,7 +60,7 @@ ExternalProject_Add(slang-build SOURCE_DIR ${SLANG_ROOT} BINARY_DIR ${SLANG_ROOT} CONFIGURE_COMMAND ${SLANG_ROOT}/premake.bat vs2019 --file=${SLANG_ROOT}/premake5.lua gmake --arch=${CMAKE_PLATFORM} --deps=true - BUILD_COMMAND msbuild slang.sln -p:Configuration=Release -p:Platform=${CMAKE_PLATFORM} + BUILD_COMMAND msbuild slang.sln -p:PlatformToolset=v143 -p:Configuration=Release -p:Platform=${CMAKE_PLATFORM} INSTALL_COMMAND "" ) elseif(UNIX) @@ -73,7 +73,7 @@ ExternalProject_Add(slang-build ) endif() -add_library(slang-llvm INTERFACE) +add_library(slang-llvm SHARED IMPORTED) target_link_libraries(slang-llvm INTERFACE $ $ @@ -81,7 +81,7 @@ target_link_libraries(slang-llvm INTERFACE set_target_properties(slang-llvm PROPERTIES IMPORTED_IMPLIB ${SLANG_BINARY_DIR}/slang.lib) set_target_properties(slang-llvm PROPERTIES IMPORTED_LOCATION ${SLANG_BINARY_DIR}/slang-llvm.dll) -add_library(slang-glslang INTERFACE) +add_library(slang-glslang SHARED IMPORTED) target_link_libraries(slang-glslang INTERFACE $ $ @@ -89,7 +89,7 @@ target_link_libraries(slang-glslang INTERFACE set_target_properties(slang-glslang PROPERTIES IMPORTED_IMPLIB ${SLANG_BINARY_DIR}/slang.lib) set_target_properties(slang-glslang PROPERTIES IMPORTED_LOCATION ${SLANG_BINARY_DIR}/slang-glslang.dll) -add_library(slang INTERFACE) +add_library(slang SHARED IMPORTED) target_include_directories(slang INTERFACE $ diff --git a/external/slang b/external/slang index 1f4c7ca..101f164 160000 --- a/external/slang +++ b/external/slang @@ -1 +1 @@ -Subproject commit 1f4c7cab13341c2e9d48df2b01ed2c048c17c152 +Subproject commit 101f164b036d0c1c012243df69179559b6f40fb8 diff --git a/src/AssetViewer/CMakeLists.txt b/src/AssetViewer/CMakeLists.txt new file mode 100644 index 0000000..3d58048 --- /dev/null +++ b/src/AssetViewer/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(AssetViewer + PRIVATE + main.cpp) \ No newline at end of file diff --git a/src/AssetViewer/main.cpp b/src/AssetViewer/main.cpp new file mode 100644 index 0000000..efb6e48 --- /dev/null +++ b/src/AssetViewer/main.cpp @@ -0,0 +1,62 @@ +#include "Asset/Asset.h" +#include "Asset/MeshAsset.h" +#include "Asset/FontAsset.h" +#include "Asset/TextureAsset.h" +#include "Asset/MaterialAsset.h" +#include "Asset/MaterialInstanceAsset.h" +#include "Graphics/Vulkan/VulkanGraphics.h" +#include "Asset/AssetRegistry.h" + +using namespace Seele; + +AssetRegistry * instance = new AssetRegistry(); + +int main(int argc, char** argv) +{ + //if(argc < 2) + //{ + // return -1; + //} + std::filesystem::path path = "C:\\Users\\Dynamitos\\TrackClear\\Assets\\Dirt.asset"; + std::ifstream stream = std::ifstream(path, std::ios::binary); + + ArchiveBuffer buffer; + buffer.readFromStream(stream); + + // Read asset type + uint64 identifier; + Serialization::load(buffer, identifier); + + // Read name + std::string name; + Serialization::load(buffer, name); + + // Read folder + std::string folderPath; + Serialization::load(buffer, folderPath); + + PAsset asset; + switch (identifier) + { + case TextureAsset::IDENTIFIER: + asset = new TextureAsset(folderPath, name); + break; + case MeshAsset::IDENTIFIER: + asset = new MeshAsset(folderPath, name); + break; + case MaterialAsset::IDENTIFIER: + asset = new MaterialAsset(folderPath, name); + break; + case MaterialInstanceAsset::IDENTIFIER: + asset = new MaterialInstanceAsset(folderPath, name); + // TODO + break; + case FontAsset::IDENTIFIER: + asset = new FontAsset(folderPath, name); + break; + default: + throw new std::logic_error("Unknown Identifier"); + } + asset->load(buffer); + std::cin.get(); +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 85b3389..7d3df86 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,2 +1,3 @@ +add_subdirectory(AssetViewer/) add_subdirectory(Editor/) add_subdirectory(Engine/) \ No newline at end of file diff --git a/src/Editor/Window/GameView.cpp b/src/Editor/Window/GameView.cpp index f8c5dc9..7d5435d 100644 --- a/src/Editor/Window/GameView.cpp +++ b/src/Editor/Window/GameView.cpp @@ -4,6 +4,9 @@ #include "Component/KeyboardInput.h" #include "Actor/CameraActor.h" #include "Asset/AssetRegistry.h" +#include "Asset/MeshLoader.h" +#include "Asset/TextureLoader.h" +#include "Asset/MaterialLoader.h" using namespace Seele; @@ -24,7 +27,176 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate { scene = new Scene(graphics); gameInterface.reload(instance); - gameInterface.getGame()->importAssets(); + AssetRegistry::importMesh(MeshImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/models/arena.fbx", + }); + AssetRegistry::importMesh(MeshImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/models/train.fbx", + }); + AssetRegistry::importMesh(MeshImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/models/bird.fbx", + }); + AssetRegistry::importMesh(MeshImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/models/cube.fbx", + }); + AssetRegistry::importMesh(MeshImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/models/flameThrower.fbx", + }); + AssetRegistry::importMesh(MeshImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/models/player.fbx", + }); + AssetRegistry::importMesh(MeshImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/models/shotgun.fbx", + }); + AssetRegistry::importMesh(MeshImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/models/track.fbx", + }); + AssetRegistry::importMesh(MeshImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/models/zombie.fbx", + }); + + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/Dirt.png", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/DirtGrass.png", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/Grass.png", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/Ice.png", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/Lava.png", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/Obsidian.png", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/Rocks.png", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/Sand.png", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/Water.png", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/Wood.png", + }); + + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level0/blendMap.png", + .importPath = "level0", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level0/heightMap.png", + .importPath = "level0", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level0/trackMap.png", + .importPath = "level0", + }); + AssetRegistry::importMaterial(MaterialImportArgs{ + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level0/TerrainLevel0.asset", + .importPath = "level0", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level1/blendMap.png", + .importPath = "level1", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level1/heightMap.png", + .importPath = "level1", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level1/trackMap.png", + .importPath = "level1", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level2/blendMap.png", + .importPath = "level2", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level2/heightMap.png", + .importPath = "level2", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level2/trackMap.png", + .importPath = "level2", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level3/blendMap.png", + .importPath = "level3", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level3/heightMap.png", + .importPath = "level3", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level3/trackMap.png", + .importPath = "level3", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level4/blendMap.png", + .importPath = "level4", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level4/heightMap.png", + .importPath = "level4", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level4/trackMap.png", + .importPath = "level4", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level5/blendMap.png", + .importPath = "level5", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level5/heightMap.png", + .importPath = "level5", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level5/trackMap.png", + .importPath = "level5", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level6/blendMap.png", + .importPath = "level6", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level6/heightMap.png", + .importPath = "level6", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level6/trackMap.png", + .importPath = "level6", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level7/blendMap.png", + .importPath = "level7", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level7/heightMap.png", + .importPath = "level7", + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/textures/level7/trackMap.png", + .importPath = "level7", + }); + + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/skyboxes/FS000_Day_01.png", + .type = TextureImportType::TEXTURE_CUBEMAP, + }); + AssetRegistry::importTexture(TextureImportArgs { + .filePath = "C:/Users/Dynamitos/TrackClear/old_resources/skyboxes/FS000_Night_01.png", + .type = TextureImportType::TEXTURE_CUBEMAP, + }); + + AssetRegistry::saveRegistry(); systemGraph = new SystemGraph(); gameInterface.getGame()->setupScene(scene, systemGraph); renderGraph.updateViewport(viewport); diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index b88267d..f5ace13 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -3,6 +3,7 @@ #include "Window/GameView.h" #include "Window/InspectorView.h" #include "Asset/AssetRegistry.h" +#include "Asset/TextureLoader.h" #include "Graphics/Vulkan/VulkanGraphics.h" using namespace Seele; @@ -11,10 +12,12 @@ using namespace Seele::Editor; int main() { Gfx::PGraphics graphics = new Vulkan::Graphics(); + GraphicsInitializer initializer; graphics->init(initializer); PWindowManager windowManager = new WindowManager(); - AssetRegistry::init(std::string("C:\\Users\\Dynamitos\\TrackClear"), graphics); + AssetRegistry::init(std::string("C:\\Users\\Dynamitos\\TrackClear\\Assets"), graphics); + WindowCreateInfo mainWindowInfo; mainWindowInfo.title = "SeeleEngine"; mainWindowInfo.width = 1280; diff --git a/src/Engine/Asset/Asset.cpp b/src/Engine/Asset/Asset.cpp index f40bfab..da51349 100644 --- a/src/Engine/Asset/Asset.cpp +++ b/src/Engine/Asset/Asset.cpp @@ -1,64 +1,47 @@ #include "Asset.h" #include "AssetRegistry.h" +#include "Graphics/Graphics.h" using namespace Seele; Asset::Asset() - : fullPath("") + : folderPath("") , name("") - , parentDir("") - , extension("") , status(Status::Uninitialized) , byteSize(0) { } -Asset::Asset(const std::filesystem::path& path) +Asset::Asset(std::string_view _folderPath, std::string_view _name) : status(Status::Uninitialized) + , folderPath(_folderPath) + , name(_name) { - if(path.is_absolute()) + if (folderPath.empty()) { - fullPath = path; + assetId = name; } else { - fullPath = AssetRegistry::getRootFolder(); - fullPath.append(path.generic_string()); + assetId = folderPath + "/" + name; } - - fullPath.make_preferred(); - parentDir = fullPath.parent_path(); - name = fullPath.stem(); - extension = fullPath.extension(); } -Asset::Asset(const std::string &directory, const std::string &fileName) - : Asset(std::filesystem::path(directory + fileName)) -{ -} Asset::~Asset() { } -std::ifstream Asset::getReadStream() const +std::string Asset::getFolderPath() const { - return std::ifstream(fullPath, std::ios::binary); + return folderPath; } -std::ofstream Asset::getWriteStream() const +std::string Asset::getName() const { - return std::ofstream(fullPath, std::ios::binary); + return name; } -std::string Asset::getFileName() const +std::string Asset::getAssetIdentifier() const { - return name.generic_string(); + return assetId; } -std::string Asset::getFullPath() const -{ - return fullPath.generic_string(); -} -std::string Asset::getExtension() const -{ - return extension.generic_string(); -} \ No newline at end of file diff --git a/src/Engine/Asset/Asset.h b/src/Engine/Asset/Asset.h index d2d967d..30e206f 100644 --- a/src/Engine/Asset/Asset.h +++ b/src/Engine/Asset/Asset.h @@ -1,5 +1,6 @@ #pragma once #include "MinimalEngine.h" +#include "Serialization/ArchiveBuffer.h" namespace Seele { @@ -14,39 +15,31 @@ public: Ready }; Asset(); - Asset(const std::string& directory, const std::string& name); - Asset(const std::filesystem::path& path); + Asset(std::string_view folderPath, std::string_view name); virtual ~Asset(); - virtual void save(Gfx::PGraphics graphics) = 0; - virtual void load(Gfx::PGraphics graphics) = 0; + virtual void save(ArchiveBuffer& buffer) const = 0; + virtual void load(ArchiveBuffer& buffer) = 0; - // returns the name of the file, without extension - std::string getFileName() const; - // returns the full absolute path, from root to extension - std::string getFullPath() const; - // returns the file extension, without preceding dot - std::string getExtension() const; - inline Status getStatus() + // returns the assets name + std::string getName() const; + // returns the (virtual) folder path + std::string getFolderPath() const; + // returns the identifier with which it can be found from the asset registry + std::string getAssetIdentifier() const; + + constexpr Status getStatus() { - std::scoped_lock lck(lock); return status; } - inline void setStatus(Status _status) + constexpr void setStatus(Status _status) { - std::scoped_lock lck(lock); status = _status; } protected: - std::mutex lock; - std::ifstream getReadStream() const; - std::ofstream getWriteStream() const; -private: - // Path relative to the project root - std::filesystem::path fullPath; - std::filesystem::path name; - std::filesystem::path parentDir; - std::filesystem::path extension; + std::string folderPath; + std::string name; + std::string assetId; Status status; uint32 byteSize; }; diff --git a/src/Engine/Asset/AssetRegistry.cpp b/src/Engine/Asset/AssetRegistry.cpp index 0f4c2e3..e8f0eca 100644 --- a/src/Engine/Asset/AssetRegistry.cpp +++ b/src/Engine/Asset/AssetRegistry.cpp @@ -3,6 +3,7 @@ #include "FontAsset.h" #include "TextureAsset.h" #include "MaterialAsset.h" +#include "MaterialInstanceAsset.h" #include "FontLoader.h" #include "TextureLoader.h" #include "MaterialLoader.h" @@ -15,12 +16,12 @@ #include using namespace Seele; -using json = nlohmann::json; extern AssetRegistry* instance; AssetRegistry::~AssetRegistry() { + delete assetRoot; } void AssetRegistry::init(const std::string& rootFolder, Gfx::PGraphics graphics) @@ -30,28 +31,47 @@ void AssetRegistry::init(const std::string& rootFolder, Gfx::PGraphics graphics) void AssetRegistry::importMesh(MeshImportArgs args) { + if (get().getOrCreateFolder(args.importPath)->meshes.contains(args.filePath.stem().string())) + { + // skip importing duplicates + return; + } get().meshLoader->importAsset(args); } void AssetRegistry::importTexture(TextureImportArgs args) { + if (get().getOrCreateFolder(args.importPath)->textures.contains(args.filePath.stem().string())) + { + // skip importing duplicates + return; + } get().textureLoader->importAsset(args); } void AssetRegistry::importFont(FontImportArgs args) { + if (get().getOrCreateFolder(args.importPath)->fonts.contains(args.filePath.stem().string())) + { + // skip importing duplicates + return; + } get().fontLoader->importAsset(args); } void AssetRegistry::importMaterial(MaterialImportArgs args) { + if (get().getOrCreateFolder(args.importPath)->materials.contains(args.filePath.stem().string())) + { + // skip importing duplicates + return; + } get().materialLoader->importAsset(args); } - PMeshAsset AssetRegistry::findMesh(const std::string &filePath) { - AssetFolder& folder = get().assetRoot; + AssetFolder* folder = get().assetRoot; std::string fileName = filePath; size_t slashLoc = filePath.rfind("/"); if(slashLoc != -1) @@ -59,30 +79,25 @@ PMeshAsset AssetRegistry::findMesh(const std::string &filePath) folder = get().getOrCreateFolder(filePath.substr(0, slashLoc)); fileName = filePath.substr(slashLoc+1, filePath.size()); } - auto it = folder.meshes.find(fileName); - assert(it != folder.meshes.end()); - return it->second; + return folder->meshes.at(fileName); } PTextureAsset AssetRegistry::findTexture(const std::string &filePath) { + AssetFolder* folder = get().assetRoot; std::string fileName = filePath; size_t slashLoc = filePath.rfind("/"); - if(slashLoc != -1) + if (slashLoc != -1) { - AssetFolder& folder = get().getOrCreateFolder(filePath.substr(0, slashLoc)); - fileName = filePath.substr(slashLoc+1, filePath.size()); - return folder.textures[fileName]; - } - else - { - return get().assetRoot.textures[fileName]; + folder = get().getOrCreateFolder(filePath.substr(0, slashLoc)); + fileName = filePath.substr(slashLoc + 1, filePath.size()); } + return folder->textures.at(fileName); } PFontAsset AssetRegistry::findFont(const std::string& filePath) { - AssetFolder& folder = get().assetRoot; + AssetFolder* folder = get().assetRoot; std::string fileName = filePath; size_t slashLoc = filePath.rfind("/"); if(slashLoc != -1) @@ -90,20 +105,20 @@ PFontAsset AssetRegistry::findFont(const std::string& filePath) folder = get().getOrCreateFolder(filePath.substr(0, slashLoc)); fileName = filePath.substr(slashLoc+1, filePath.size()); } - return folder.fonts[fileName]; + return folder->fonts.at(fileName); } PMaterialAsset AssetRegistry::findMaterial(const std::string &filePath) { - AssetFolder& folder = get().assetRoot; + AssetFolder* folder = get().assetRoot; std::string fileName = filePath; size_t slashLoc = filePath.rfind("/"); - if(slashLoc != -1) + if (slashLoc != -1) { folder = get().getOrCreateFolder(filePath.substr(0, slashLoc)); - fileName = filePath.substr(slashLoc+1, filePath.size()); + fileName = filePath.substr(slashLoc + 1, filePath.size()); } - return folder.materials[fileName]; + return folder->materials.at(fileName); } std::ofstream AssetRegistry::createWriteStream(const std::string& relativePath, std::ios_base::openmode openmode) @@ -125,57 +140,256 @@ AssetRegistry::AssetRegistry() { } +void AssetRegistry::loadRegistry() +{ + get().loadRegistryInternal(); +} + +void AssetRegistry::saveRegistry() +{ + get().saveRegistryInternal(); +} + void AssetRegistry::initialize(const std::filesystem::path &_rootFolder, Gfx::PGraphics _graphics) { this->graphics = _graphics; this->rootFolder = _rootFolder; + this->assetRoot = new AssetFolder(""); this->fontLoader = new FontLoader(graphics); this->meshLoader = new MeshLoader(graphics); this->textureLoader = new TextureLoader(graphics); this->materialLoader = new MaterialLoader(graphics); + loadRegistryInternal(); } -std::string AssetRegistry::getRootFolder() +void AssetRegistry::loadRegistryInternal() { - return get().rootFolder.generic_string(); + peekFolder(assetRoot); + loadFolder(assetRoot); } -void AssetRegistry::registerMesh(PMeshAsset mesh, const std::string& importPath) + +void AssetRegistry::peekFolder(AssetFolder* folder) { - AssetFolder& folder = getOrCreateFolder(importPath); - folder.meshes[mesh->getFileName()] = mesh; + for (const auto& entry : std::filesystem::directory_iterator(rootFolder / folder->folderPath)) + { + const auto& stem = entry.path().stem().string(); + if (entry.is_directory()) + { + if (folder->folderPath.empty()) + { + folder->children[stem] = new AssetFolder(stem); + } + else + { + folder->children[stem] = new AssetFolder(folder->folderPath + "/" + stem); + } + peekFolder(folder->children[stem]); + continue; + } + + auto stream = std::ifstream(entry.path(), std::ios::binary); + + ArchiveBuffer buffer(graphics); + buffer.readFromStream(stream); + + // Read asset type + uint64 identifier; + Serialization::load(buffer, identifier); + + // Read name + std::string name; + Serialization::load(buffer, name); + + // Read folder + std::string folderPath; + Serialization::load(buffer, folderPath); + + PAsset asset; + switch (identifier) + { + case TextureAsset::IDENTIFIER: + asset = new TextureAsset(folderPath, name); + folder->textures[asset->getName()] = asset; + break; + case MeshAsset::IDENTIFIER: + asset = new MeshAsset(folderPath, name); + folder->meshes[asset->getName()] = asset; + break; + case MaterialAsset::IDENTIFIER: + asset = new MaterialAsset(folderPath, name); + folder->materials[asset->getName()] = asset; + break; + case MaterialInstanceAsset::IDENTIFIER: + asset = new MaterialInstanceAsset(folderPath, name); + // TODO + break; + case FontAsset::IDENTIFIER: + asset = new FontAsset(folderPath, name); + folder->fonts[asset->getName()] = asset; + break; + default: + throw new std::logic_error("Unknown Identifier"); + } + } } -void AssetRegistry::registerTexture(PTextureAsset texture, const std::string& importPath) + +void AssetRegistry::loadFolder(AssetFolder* folder) { - AssetFolder& folder = getOrCreateFolder(importPath); - folder.textures[texture->getFileName()] = texture; + for (const auto& entry : std::filesystem::directory_iterator(rootFolder / folder->folderPath)) + { + const auto& path = entry.path(); + if (entry.is_directory()) + { + auto relative = path.stem().string(); + loadFolder(folder->children[relative]); + continue; + } + + auto stream = std::ifstream(path, std::ios::binary); + + ArchiveBuffer buffer(graphics); + buffer.readFromStream(stream); + + // Read asset type + uint64 identifier; + Serialization::load(buffer, identifier); + + // Read name + std::string name; + Serialization::load(buffer, name); + + // Read folder + std::string folderPath; + Serialization::load(buffer, folderPath); + + PAsset asset; + switch (identifier) + { + case TextureAsset::IDENTIFIER: + asset = folder->textures.at(name); + break; + case MeshAsset::IDENTIFIER: + asset = folder->meshes.at(name); + break; + case MaterialAsset::IDENTIFIER: + asset = folder->materials.at(name); + break; + case MaterialInstanceAsset::IDENTIFIER: + //asset = new MaterialInstanceAsset(path); + // TODO + break; + case FontAsset::IDENTIFIER: + asset = folder->fonts.at(name); + break; + default: + throw new std::logic_error("Unknown Identifier"); + } + asset->load(buffer); + } } -void AssetRegistry::registerFont(PFontAsset font, const std::string& importPath) -{ - AssetFolder& folder = getOrCreateFolder(importPath); - folder.fonts[font->getFileName()] = font; +void AssetRegistry::saveRegistryInternal() +{ + saveFolder("", assetRoot); } -void AssetRegistry::registerMaterial(PMaterialAsset material, const std::string& importPath) +void AssetRegistry::saveFolder(const std::filesystem::path& folderPath, AssetFolder* folder) { - AssetFolder& folder = getOrCreateFolder(importPath); - folder.materials[material->getFileName()] = material; + std::filesystem::create_directory(rootFolder / folderPath); + for (const auto& [name, texture] : folder->textures) + { + saveAsset(texture, TextureAsset::IDENTIFIER, folderPath, name); + } + for (const auto& [name, mesh] : folder->meshes) + { + saveAsset(mesh, MeshAsset::IDENTIFIER, folderPath, name); + } + for (const auto& [name, material] : folder->materials) + { + saveAsset(material, MaterialAsset::IDENTIFIER, folderPath, name); + } + for (const auto& [name, font] : folder->fonts) + { + saveAsset(font, FontAsset::IDENTIFIER, folderPath, name); + } + for (auto& [name, child] : folder->children) + { + saveFolder(folderPath / name, child); + } } -AssetRegistry::AssetFolder& AssetRegistry::getOrCreateFolder(std::string fullPath) +void AssetRegistry::saveAsset(PAsset asset, uint64 identifier, const std::filesystem::path& folderPath, std::string name) { - AssetFolder& result = assetRoot; + if (name.empty()) + return; + + std::string path = (folderPath / name).string().append(".asset"); + auto assetStream = createWriteStream(std::move(path), std::ios::binary); + ArchiveBuffer assetBuffer(graphics); + // write identifier + Serialization::save(assetBuffer, identifier); + // write name + Serialization::save(assetBuffer, name); + // write folder + Serialization::save(assetBuffer, folderPath.string()); + // write asset data + asset->save(assetBuffer); + assetBuffer.writeToStream(assetStream); + +} + +std::filesystem::path AssetRegistry::getRootFolder() +{ + return get().rootFolder; +} + +void AssetRegistry::registerMesh(PMeshAsset mesh) +{ + AssetFolder* folder = getOrCreateFolder(mesh->getFolderPath()); + folder->meshes[mesh->getName()] = mesh; +} + +void AssetRegistry::registerTexture(PTextureAsset texture) +{ + AssetFolder* folder = getOrCreateFolder(texture->getFolderPath()); + folder->textures[texture->getName()] = texture; +} + +void AssetRegistry::registerFont(PFontAsset font) +{ + AssetFolder* folder = getOrCreateFolder(font->getFolderPath()); + folder->fonts[font->getName()] = font; +} + +void AssetRegistry::registerMaterial(PMaterialAsset material) +{ + AssetFolder* folder = getOrCreateFolder(material->getFolderPath()); + folder->materials[material->getName()] = material; +} + +AssetRegistry::AssetFolder* AssetRegistry::getOrCreateFolder(std::string fullPath) +{ + AssetFolder* result = assetRoot; + std::string temp = fullPath; while(!fullPath.empty()) { size_t slashLoc = fullPath.find("/"); if(slashLoc == -1) { - return result.children[fullPath]; + if (!result->children.contains(fullPath)) + { + result->children[fullPath] = new AssetFolder(fullPath); + } + return result->children[fullPath]; } std::string folderName = fullPath.substr(0, slashLoc); - result = result.children[folderName]; + if (!result->children.contains(folderName)) + { + result->children[folderName] = new AssetFolder(temp); + } + result = result->children[folderName]; fullPath = fullPath.substr(slashLoc+1, fullPath.size()); } return result; @@ -194,3 +408,15 @@ std::ifstream AssetRegistry::internalCreateReadStream(const std::string& relativ fullPath.append(relativePath); return std::ifstream(fullPath.string(), openmode); } + +AssetRegistry::AssetFolder::AssetFolder(std::string_view folderPath) + : folderPath(folderPath) +{} + +AssetRegistry::AssetFolder::~AssetFolder() +{ + for (const auto& [_, child] : children) + { + delete child; + } +} diff --git a/src/Engine/Asset/AssetRegistry.h b/src/Engine/Asset/AssetRegistry.h index 9796490..c1aad2d 100644 --- a/src/Engine/Asset/AssetRegistry.h +++ b/src/Engine/Asset/AssetRegistry.h @@ -1,8 +1,8 @@ #pragma once #include "MinimalEngine.h" #include "Asset.h" +#include "Containers/Map.h" #include -#include namespace Seele { @@ -22,7 +22,7 @@ public: ~AssetRegistry(); static void init(const std::string& rootFolder, Gfx::PGraphics graphics); - static std::string getRootFolder(); + static std::filesystem::path getRootFolder(); static PMeshAsset findMesh(const std::string& filePath); static PTextureAsset findTexture(const std::string& filePath); @@ -37,35 +37,47 @@ public: static void importFont(struct FontImportArgs args); static void importMaterial(struct MaterialImportArgs args); static void set(AssetRegistry registry); + + static void loadRegistry(); + static void saveRegistry(); + AssetRegistry(); private: struct AssetFolder { - std::map children; + std::string folderPath; + Map children; //Todo: Seele::Map doesn't really work with strings for some reason, so just use std::map for now - std::map textures; - std::map fonts; - std::map meshes; - std::map materials; + Map textures; + Map fonts; + Map meshes; + Map materials; + AssetFolder(std::string_view folderPath); + ~AssetFolder(); }; static AssetRegistry& get(); void initialize(const std::filesystem::path& rootFolder, Gfx::PGraphics graphics); + void loadRegistryInternal(); + void peekFolder(AssetFolder* folder); + void loadFolder(AssetFolder* folder); + void saveRegistryInternal(); + void saveFolder(const std::filesystem::path& folderPath, AssetFolder* folder); + void saveAsset(PAsset asset, uint64 identifier, const std::filesystem::path& folderPath, std::string name); + void registerMesh(PMeshAsset mesh); + void registerTexture(PTextureAsset texture); + void registerFont(PFontAsset font); + void registerMaterial(PMaterialAsset material); - void registerMesh(PMeshAsset mesh, const std::string& importPath); - void registerTexture(PTextureAsset texture, const std::string& importPath); - void registerFont(PFontAsset font, const std::string& importPath); - void registerMaterial(PMaterialAsset material, const std::string& importPath); - - AssetFolder& getOrCreateFolder(std::string foldername); + AssetFolder* getOrCreateFolder(std::string foldername); std::ofstream internalCreateWriteStream(const std::string& relativePath, std::ios_base::openmode openmode = std::ios::out); std::ifstream internalCreateReadStream(const std::string& relaitvePath, std::ios_base::openmode openmode = std::ios::in); std::filesystem::path rootFolder; - AssetFolder assetRoot; + AssetFolder* assetRoot; Gfx::PGraphics graphics; UPTextureLoader textureLoader; UPFontLoader fontLoader; diff --git a/src/Engine/Asset/FontAsset.cpp b/src/Engine/Asset/FontAsset.cpp index 9355ba7..df89c5c 100644 --- a/src/Engine/Asset/FontAsset.cpp +++ b/src/Engine/Asset/FontAsset.cpp @@ -1,5 +1,7 @@ #include "FontAsset.h" #include "Graphics/Graphics.h" +#include "Graphics/Vulkan/VulkanGraphicsEnums.h" +#include using namespace Seele; @@ -7,13 +9,8 @@ FontAsset::FontAsset() { } -FontAsset::FontAsset(const std::string& directory, const std::string& name) - : Asset(directory, name) -{ -} - -FontAsset::FontAsset(const std::filesystem::path& fullPath) - : Asset(fullPath) +FontAsset::FontAsset(std::string_view folderPath, std::string_view name) + : Asset(folderPath, name) { } @@ -22,11 +19,108 @@ FontAsset::~FontAsset() } -void FontAsset::save(Gfx::PGraphics graphics) +void FontAsset::save(ArchiveBuffer& buffer) const { + uint64 numGlyphs = glyphs.size(); + buffer.writeBytes(&numGlyphs, sizeof(uint64)); + for (auto& [index, glyph] : glyphs) + { + Serialization::save(buffer, index); + + Array textureData; + ktxTexture2* kTexture; + ktxTextureCreateInfo createInfo = { + .vkFormat = (uint32_t)glyph.texture->getFormat(), + .baseWidth = glyph.texture->getSizeX(), + .baseHeight = glyph.texture->getSizeY(), + .baseDepth = glyph.texture->getSizeZ(), + .numDimensions = glyph.texture->getSizeZ() > 1 ? 3u : glyph.texture->getSizeY() > 1 ? 2u : 1u, + .numLevels = glyph.texture->getMipLevels(), + .numFaces = glyph.texture->getNumFaces(), + .isArray = false, + .generateMipmaps = false, + }; + ktxTexture2_Create(&createInfo, KTX_TEXTURE_CREATE_ALLOC_STORAGE, &kTexture); + + for (uint32 depth = 0; depth < glyph.texture->getSizeZ(); ++depth) + { + for (uint32 face = 0; face < glyph.texture->getNumFaces(); ++face) + { + // technically, downloading cant be const, because we have to allocate temporary buffers and change layouts + // but practically the texture stays the same + glyph.texture->download(0, depth, face, textureData); + ktxTexture_SetImageFromMemory(ktxTexture(kTexture), 0, depth, face, textureData.data(), textureData.size()); + } + } + char writer[100]; + snprintf(writer, sizeof(writer), "%s version %s", "SeeleEngine", "0.0.1"); + ktxHashList_AddKVPair(&kTexture->kvDataHead, KTX_WRITER_KEY, + (ktx_uint32_t)strlen(writer) + 1, + writer); + + ktxTexture2_TranscodeBasis(kTexture, KTX_TTF_ASTC_4x4_RGBA, 0); + + ktx_uint8_t* texData; + ktx_size_t texSize; + ktxTexture_WriteToMemory(ktxTexture(kTexture), &texData, &texSize); + + buffer.writeBytes(texData, texSize); + free(texData); + + Serialization::save(buffer, glyph.size); + Serialization::save(buffer, glyph.bearing); + Serialization::save(buffer, glyph.advance); + } } -void FontAsset::load(Gfx::PGraphics graphics) +void FontAsset::load(ArchiveBuffer& buffer) { + uint64 numGlyphs = glyphs.size(); + buffer.readBytes(&numGlyphs, sizeof(uint64)); + for (uint64 x = 0; x < numGlyphs; ++x) + { + uint32 index; + Serialization::load(buffer, index); + + Glyph& glyph = glyphs[index]; + + uint64 texSize; + buffer.readBytes(&texSize, sizeof(uint64)); + Array rawTex; + rawTex.resize(texSize); + buffer.readBytes(rawTex.data(), rawTex.size()); + + ktxTexture2* kTexture; + ktxTexture2_CreateFromMemory(rawTex.data(), + rawTex.size(), + KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, + &kTexture); + + ktxTexture2_TranscodeBasis(kTexture, KTX_TTF_BC7_RGBA, 0); + + TextureCreateInfo createInfo = { + .resourceData = { + .size = ktxTexture_GetDataSize(ktxTexture(kTexture)), + .data = ktxTexture_GetData(ktxTexture(kTexture)), + .owner = Gfx::QueueType::GRAPHICS, + }, + .width = kTexture->baseWidth, + .height = kTexture->baseHeight, + .depth = kTexture->baseDepth, + .bArray = kTexture->isArray, + .arrayLayers = kTexture->isArray ? kTexture->numLayers : kTexture->numFaces, + .mipLevels = kTexture->numLevels, + .format = Vulkan::cast((VkFormat)kTexture->vkFormat), + .usage = Gfx::SE_IMAGE_USAGE_SAMPLED_BIT, + }; + + glyph.texture = buffer.getGraphics()->createTexture2D(createInfo); + + ktxTexture_Destroy(ktxTexture(kTexture)); + + Serialization::load(buffer, glyph.size); + Serialization::load(buffer, glyph.bearing); + Serialization::load(buffer, glyph.advance); + } } \ No newline at end of file diff --git a/src/Engine/Asset/FontAsset.h b/src/Engine/Asset/FontAsset.h index 2d2bdf1..c96459d 100644 --- a/src/Engine/Asset/FontAsset.h +++ b/src/Engine/Asset/FontAsset.h @@ -1,5 +1,7 @@ #pragma once #include "Asset.h" +#include "Containers/Map.h" +#include "Math/Math.h" namespace Seele { @@ -7,12 +9,12 @@ DECLARE_NAME_REF(Gfx, Texture2D) class FontAsset : public Asset { public: + static constexpr uint64 IDENTIFIER = 0x10; FontAsset(); - FontAsset(const std::string& directory, const std::string& name); - FontAsset(const std::filesystem::path& fullPath); + FontAsset(std::string_view folderPath, std::string_view name); virtual ~FontAsset(); - virtual void save(Gfx::PGraphics graphics) override; - virtual void load(Gfx::PGraphics graphics) override; + virtual void save(ArchiveBuffer& buffer) const override; + virtual void load(ArchiveBuffer& buffer) override; struct Glyph { diff --git a/src/Engine/Asset/FontLoader.cpp b/src/Engine/Asset/FontLoader.cpp index 0547d8b..666f343 100644 --- a/src/Engine/Asset/FontLoader.cpp +++ b/src/Engine/Asset/FontLoader.cpp @@ -22,11 +22,9 @@ void FontLoader::importAsset(FontImportArgs args) { std::filesystem::path assetPath = args.filePath.filename(); assetPath.replace_extension("asset"); - PFontAsset asset = new FontAsset(assetPath.generic_string()); - std::error_code code; - std::filesystem::copy_file(args.filePath, asset->getFullPath(), code); + PFontAsset asset = new FontAsset(args.importPath, assetPath.stem().string()); asset->setStatus(Asset::Status::Loading); - AssetRegistry::get().registerFont(asset, args.importPath); + AssetRegistry::get().registerFont(asset); import(args, asset); } @@ -39,7 +37,7 @@ void FontLoader::import(FontImportArgs args, PFontAsset asset) FT_Error error = FT_Init_FreeType(&ft); assert(!error); FT_Face face; - error = FT_New_Face(ft, asset->getFullPath().c_str(), 0, &face); + error = FT_New_Face(ft, args.filePath.string().c_str(), 0, &face); assert(!error); FT_Set_Pixel_Sizes(face, 0, 48); for(uint32 c = 0; c < 256; ++c) @@ -59,7 +57,7 @@ void FontLoader::import(FontImportArgs args, PFontAsset asset) imageData.height = face->glyph->bitmap.rows; imageData.resourceData.data = face->glyph->bitmap.buffer; imageData.resourceData.size = imageData.width * imageData.height; - if(imageData.width == 0 || imageData.width == 0) + if(imageData.width == 0 || imageData.height == 0) { glyph.size.x = 1; glyph.size.y = 1; diff --git a/src/Engine/Asset/MaterialAsset.cpp b/src/Engine/Asset/MaterialAsset.cpp index 6dce448..60d5dc3 100644 --- a/src/Engine/Asset/MaterialAsset.cpp +++ b/src/Engine/Asset/MaterialAsset.cpp @@ -8,13 +8,8 @@ MaterialAsset::MaterialAsset() { } -MaterialAsset::MaterialAsset(const std::string& directory, const std::string& name) - : Asset(directory, name) -{ -} - -MaterialAsset::MaterialAsset(const std::filesystem::path& fullPath) - : Asset(fullPath) +MaterialAsset::MaterialAsset(std::string_view folderPath, std::string_view name) + : Asset(folderPath, name) { } @@ -22,13 +17,14 @@ MaterialAsset::~MaterialAsset() { } - -void MaterialAsset::save(Gfx::PGraphics graphics) +void MaterialAsset::save(ArchiveBuffer& buffer) const { + material->save(buffer); } -void MaterialAsset::load(Gfx::PGraphics graphics) +void MaterialAsset::load(ArchiveBuffer& buffer) { - + material = new Material(); + material->load(buffer); } diff --git a/src/Engine/Asset/MaterialAsset.h b/src/Engine/Asset/MaterialAsset.h index 7a8e6c8..d824ebb 100644 --- a/src/Engine/Asset/MaterialAsset.h +++ b/src/Engine/Asset/MaterialAsset.h @@ -7,12 +7,12 @@ DECLARE_REF(Material) class MaterialAsset : public Asset { public: + static constexpr uint64 IDENTIFIER = 0x4; MaterialAsset(); - MaterialAsset(const std::string &directory, const std::string &name); - MaterialAsset(const std::filesystem::path &fullPath); + MaterialAsset(std::string_view folderPath, std::string_view name); virtual ~MaterialAsset(); - virtual void save(Gfx::PGraphics graphics) override; - virtual void load(Gfx::PGraphics graphics) override; + virtual void save(ArchiveBuffer& buffer) const override; + virtual void load(ArchiveBuffer& buffer) override; PMaterial getMaterial() const { return material; } private: PMaterial material; diff --git a/src/Engine/Asset/MaterialInstanceAsset.cpp b/src/Engine/Asset/MaterialInstanceAsset.cpp index 4c0289d..ec17e57 100644 --- a/src/Engine/Asset/MaterialInstanceAsset.cpp +++ b/src/Engine/Asset/MaterialInstanceAsset.cpp @@ -9,13 +9,8 @@ MaterialInstanceAsset::MaterialInstanceAsset() { } -MaterialInstanceAsset::MaterialInstanceAsset(const std::string& directory, const std::string& name) - : Asset(directory, name) -{ -} - -MaterialInstanceAsset::MaterialInstanceAsset(const std::filesystem::path& fullPath) - : Asset(fullPath) +MaterialInstanceAsset::MaterialInstanceAsset(std::string_view folderPath, std::string_view name) + : Asset(folderPath, name) { } @@ -24,10 +19,10 @@ MaterialInstanceAsset::~MaterialInstanceAsset() } -void MaterialInstanceAsset::save(Gfx::PGraphics graphics) +void MaterialInstanceAsset::save(ArchiveBuffer& buffer) const { } -void MaterialInstanceAsset::load(Gfx::PGraphics graphics) +void MaterialInstanceAsset::load(ArchiveBuffer& buffer) { } diff --git a/src/Engine/Asset/MaterialInstanceAsset.h b/src/Engine/Asset/MaterialInstanceAsset.h index 89d3479..5a44e89 100644 --- a/src/Engine/Asset/MaterialInstanceAsset.h +++ b/src/Engine/Asset/MaterialInstanceAsset.h @@ -7,12 +7,12 @@ namespace Seele class MaterialInstanceAsset : public Asset { public: + static constexpr uint64 IDENTIFIER = 0x8; MaterialInstanceAsset(); - MaterialInstanceAsset(const std::string &directory, const std::string &name); - MaterialInstanceAsset(const std::filesystem::path &fullPath); + MaterialInstanceAsset(std::string_view folderPath, std::string_view name); virtual ~MaterialInstanceAsset(); - virtual void save(Gfx::PGraphics graphics) override; - virtual void load(Gfx::PGraphics graphics) override; + virtual void save(ArchiveBuffer& buffer) const override; + virtual void load(ArchiveBuffer& buffer) override; private: PMaterialInstance material; }; diff --git a/src/Engine/Asset/MaterialLoader.cpp b/src/Engine/Asset/MaterialLoader.cpp index 88880b5..a8169d4 100644 --- a/src/Engine/Asset/MaterialLoader.cpp +++ b/src/Engine/Asset/MaterialLoader.cpp @@ -29,9 +29,9 @@ void MaterialLoader::importAsset(MaterialImportArgs args) { std::filesystem::path assetPath = args.filePath.filename(); assetPath.replace_extension("asset"); - PMaterialAsset asset = new MaterialAsset(assetPath.generic_string()); + PMaterialAsset asset = new MaterialAsset(args.importPath, assetPath.stem().string()); asset->setStatus(Asset::Status::Loading); - AssetRegistry::get().registerMaterial(asset, args.importPath); + AssetRegistry::get().registerMaterial(asset); import(args, asset); } diff --git a/src/Engine/Asset/MeshAsset.cpp b/src/Engine/Asset/MeshAsset.cpp index 3eea15b..4ff1cac 100644 --- a/src/Engine/Asset/MeshAsset.cpp +++ b/src/Engine/Asset/MeshAsset.cpp @@ -1,8 +1,10 @@ #include "MeshAsset.h" #include "Graphics/Graphics.h" #include "Graphics/Mesh.h" +#include "AssetRegistry.h" #include "Graphics/VertexShaderInput.h" #include "Material/MaterialInterface.h" +#include "Graphics/StaticMeshVertexInput.h" using namespace Seele; @@ -10,34 +12,64 @@ MeshAsset::MeshAsset() { } -MeshAsset::MeshAsset(const std::string& directory, const std::string& name) - : Asset(directory, name) -{ -} -MeshAsset::MeshAsset(const std::filesystem::path& fullPath) - : Asset(fullPath) +MeshAsset::MeshAsset(std::string_view folderPath, std::string_view name) + : Asset(folderPath, name) { } + MeshAsset::~MeshAsset() { - } -void MeshAsset::save(Gfx::PGraphics graphics) + +void MeshAsset::save(ArchiveBuffer& buffer) const { + uint64 numMeshes = meshes.size(); + Serialization::save(buffer, numMeshes); + for (auto mesh : meshes) + { + mesh->vertexInput->save(buffer); + Array rawIndices; + mesh->indexBuffer->download(rawIndices); + Serialization::save(buffer, rawIndices); + Serialization::save(buffer, mesh->indexBuffer->getIndexType()); + Serialization::save(buffer, mesh->referencedMaterial->getAssetIdentifier()); + } } -void MeshAsset::load(Gfx::PGraphics graphics) + +void MeshAsset::load(ArchiveBuffer& buffer) { + uint64 numMeshes = 0; + Serialization::load(buffer, numMeshes); + meshes.resize(numMeshes); + for (auto& mesh : meshes) + { + PVertexShaderInput vertexInput = new StaticMeshVertexInput(""); + vertexInput->load(buffer); + Array rawIndices; + Serialization::load(buffer, rawIndices); + Gfx::SeIndexType indexType; + Serialization::load(buffer, indexType); + IndexBufferCreateInfo createInfo = { + .resourceData = { + .size = rawIndices.size(), + .data = rawIndices.data(), + }, + .indexType = indexType, + }; + Gfx::PIndexBuffer indexBuffer = buffer.getGraphics()->createIndexBuffer(createInfo); + mesh = new Mesh(vertexInput, indexBuffer); + std::string matname; + Serialization::load(buffer, matname); + mesh->referencedMaterial = AssetRegistry::findMaterial(matname); + } } void MeshAsset::addMesh(PMesh mesh) { - std::scoped_lock lck(lock); meshes.add(mesh); - referencedMaterials.add(mesh->referencedMaterial); } const Array MeshAsset::getMeshes() { - std::scoped_lock lck(lock); return meshes; } \ No newline at end of file diff --git a/src/Engine/Asset/MeshAsset.h b/src/Engine/Asset/MeshAsset.h index 75b6ef2..ac5cb27 100644 --- a/src/Engine/Asset/MeshAsset.h +++ b/src/Engine/Asset/MeshAsset.h @@ -9,16 +9,15 @@ DECLARE_REF(MaterialInterface) class MeshAsset : public Asset { public: + static constexpr uint64 IDENTIFIER = 0x2; MeshAsset(); - MeshAsset(const std::string& directory, const std::string& name); - MeshAsset(const std::filesystem::path& fullPath); + MeshAsset(std::string_view folderPath, std::string_view name); virtual ~MeshAsset(); - virtual void save(Gfx::PGraphics graphics) override; - virtual void load(Gfx::PGraphics graphics) override; + virtual void save(ArchiveBuffer& buffer) const override; + virtual void load(ArchiveBuffer& buffer) override; void addMesh(PMesh mesh); const Array getMeshes(); //Workaround while no editor - Array referencedMaterials; Array meshes; Component::Collider physicsMesh; }; diff --git a/src/Engine/Asset/MeshLoader.cpp b/src/Engine/Asset/MeshLoader.cpp index 539c4aa..4405822 100644 --- a/src/Engine/Asset/MeshLoader.cpp +++ b/src/Engine/Asset/MeshLoader.cpp @@ -33,20 +33,20 @@ void MeshLoader::importAsset(MeshImportArgs args) { std::filesystem::path assetPath = args.filePath.filename(); assetPath.replace_extension("asset"); - PMeshAsset asset = new MeshAsset(assetPath.generic_string()); + PMeshAsset asset = new MeshAsset(args.importPath, assetPath.stem().string()); asset->setStatus(Asset::Status::Loading); - AssetRegistry::get().registerMesh(asset, args.importPath); + AssetRegistry::get().registerMesh(asset); import(args, asset); } -void MeshLoader::loadMaterials(const aiScene* scene, Array& globalMaterials) +void MeshLoader::loadMaterials(const aiScene* scene, const std::string& baseName, const std::filesystem::path& meshDirectory, const std::string& importPath, Array& globalMaterials) { using json = nlohmann::json; for(uint32 i = 0; i < scene->mNumMaterials; ++i) { aiMaterial* material = scene->mMaterials[i]; json matCode; - matCode["name"] = material->GetName().C_Str(); + matCode["name"] = baseName + material->GetName().C_Str(); matCode["profile"] = "BlinnPhong"; //TODO: other shading models aiString texPath; //TODO make samplers based on used textures @@ -89,18 +89,17 @@ void MeshLoader::loadMaterials(const aiScene* scene, Array& globalMat matCode["code"]["normal"] = "return normalTexture.Sample(textureSampler, input.texCoords[0]).xyz;"; } std::string outMatFilename = matCode["name"].get().append(".asset"); - std::ofstream outMatFile = AssetRegistry::createWriteStream(outMatFilename); + std::ofstream outMatFile = std::ofstream(meshDirectory / outMatFilename); outMatFile << std::setw(4) << matCode; outMatFile.flush(); outMatFile.close(); std::cout << "writing json to " << outMatFilename << std::endl; AssetRegistry::importMaterial(MaterialImportArgs{ - .filePath = AssetRegistry::getRootFolder() + "/" + outMatFilename, - .importPath = "", + .filePath = meshDirectory / outMatFilename, + .importPath = importPath, }); - PMaterialAsset asset = AssetRegistry::findMaterial(matCode["name"].get()); - globalMaterials[i] = asset->getMaterial(); + globalMaterials[i] = AssetRegistry::findMaterial(matCode["name"].get()); } } @@ -168,7 +167,7 @@ VertexStreamComponent createVertexStream(uint32 size, aiColor4D* sourceData, Gfx vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS); return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32A32_SFLOAT); } -void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array& materials, Array& globalMeshes, Component::Collider& collider) +void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array& materials, Array& globalMeshes, Component::Collider& collider) { for (uint32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex) { @@ -191,7 +190,7 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array& { if(mesh->HasTextureCoords(i)) { - data.textureCoordinates.add(createVertexStream(mesh->mNumVertices, mesh->mTextureCoords[i], graphics)); + data.textureCoordinates[i] = createVertexStream(mesh->mNumVertices, mesh->mTextureCoords[i], graphics); } } if(mesh->HasNormals()) @@ -243,7 +242,7 @@ void MeshLoader::convertAssimpARGB(unsigned char* dst, aiTexel* src, uint32 numP dst[i * 4 + 3] = src[i].a; } } -void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path& meshDirectory) +void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path& meshDirectory, const std::string& importPath) { for (uint32 i = 0; i < scene->mNumTextures; ++i) { @@ -269,7 +268,7 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path& std::cout << "Loading model texture " << texPngPath.string() << std::endl; AssetRegistry::importTexture(TextureImportArgs { .filePath = texPath, - .importPath = "" + .importPath = importPath, }); } } @@ -288,9 +287,9 @@ void MeshLoader::import(MeshImportArgs args, PMeshAsset meshAsset) aiProcess_FindDegenerates)); const aiScene *scene = importer.ApplyPostProcessing(aiProcess_CalcTangentSpace); - Array globalMaterials(scene->mNumMaterials); - loadTextures(scene, args.filePath.parent_path()); - loadMaterials(scene, globalMaterials); + Array globalMaterials(scene->mNumMaterials); + loadTextures(scene, args.filePath.parent_path(), args.importPath); + loadMaterials(scene, args.filePath.stem().string(), args.filePath.parent_path(), args.importPath, globalMaterials); Array globalMeshes(scene->mNumMeshes); Component::Collider collider; diff --git a/src/Engine/Asset/MeshLoader.h b/src/Engine/Asset/MeshLoader.h index f7d43e1..00cb087 100644 --- a/src/Engine/Asset/MeshLoader.h +++ b/src/Engine/Asset/MeshLoader.h @@ -10,7 +10,7 @@ namespace Seele { DECLARE_REF(Mesh) DECLARE_REF(MeshAsset) -DECLARE_REF(Material) +DECLARE_REF(MaterialAsset) DECLARE_NAME_REF(Gfx, Graphics) struct MeshImportArgs { @@ -24,9 +24,9 @@ public: ~MeshLoader(); void importAsset(MeshImportArgs args); private: - void loadMaterials(const aiScene* scene, Array& globalMaterials); - void loadTextures(const aiScene* scene, const std::filesystem::path& meshPath); - void loadGlobalMeshes(const aiScene* scene, const Array& materials, Array& globalMeshes, Component::Collider& collider); + void loadMaterials(const aiScene* scene, const std::string& baseName, const std::filesystem::path& meshDirectory, const std::string& importPath, Array& globalMaterials); + void loadTextures(const aiScene* scene, const std::filesystem::path& meshDirectory, const std::string& importPath); + void loadGlobalMeshes(const aiScene* scene, const Array& materials, Array& globalMeshes, Component::Collider& collider); void convertAssimpARGB(unsigned char* dst, aiTexel* src, uint32 numPixels); void import(MeshImportArgs args, PMeshAsset meshAsset); diff --git a/src/Engine/Asset/TextureAsset.cpp b/src/Engine/Asset/TextureAsset.cpp index 82aa582..2466610 100644 --- a/src/Engine/Asset/TextureAsset.cpp +++ b/src/Engine/Asset/TextureAsset.cpp @@ -7,66 +7,115 @@ using namespace Seele; +#define KTX_CHECK(x) { ktx_error_code_e err = x; assert(err == KTX_SUCCESS); } TextureAsset::TextureAsset() { } -TextureAsset::TextureAsset(const std::string& directory, const std::string& name) - : Asset(directory, name) + +TextureAsset::TextureAsset(std::string_view folderPath, std::string_view name) + : Asset(folderPath, name) { } -TextureAsset::TextureAsset(const std::filesystem::path& fullPath) - : Asset(fullPath) -{ -} TextureAsset::~TextureAsset() { } -void TextureAsset::save(Gfx::PGraphics graphics) +void TextureAsset::save(ArchiveBuffer& buffer) const { - //TODO: make this an actual file, not just a png wrapper - assert(false && "Editing textures is not yet supported"); + Array textureData; + ktxTexture2* kTexture; + ktxTextureCreateInfo createInfo = { + .vkFormat = (uint32_t)texture->getFormat(), + .baseWidth = texture->getSizeX(), + .baseHeight = texture->getSizeY(), + .baseDepth = texture->getSizeZ(), + .numDimensions = texture->getSizeZ() > 1 ? 3u : texture->getSizeY() > 1 ? 2u : 1u, + .numLevels = texture->getMipLevels(), + .numLayers = 1, + .numFaces = texture->getNumFaces(), + .isArray = false, + .generateMipmaps = false, + }; + KTX_CHECK(ktxTexture2_Create(&createInfo, KTX_TEXTURE_CREATE_ALLOC_STORAGE, &kTexture)); + + for (uint32 depth = 0; depth < texture->getSizeZ(); ++depth) + { + for (uint32 face = 0; face < texture->getNumFaces(); ++face) + { + // technically, downloading cant be const, because we have to allocate temporary buffers and change layouts + // but practically the texture stays the same + const_cast(texture.getHandle())->download(0, depth, face, textureData); + KTX_CHECK(ktxTexture_SetImageFromMemory(ktxTexture(kTexture), 0, depth, face, textureData.data(), textureData.size())); + } + } + char writer[100]; + snprintf(writer, sizeof(writer), "%s version %s", "SeeleEngine", "0.0.1"); + ktxHashList_AddKVPair(&kTexture->kvDataHead, KTX_WRITER_KEY, + (ktx_uint32_t)strlen(writer) + 1, + writer); + + //ktx_error_code_e error = ktxTexture2_CompressBasis(kTexture, 0); + + ktx_uint8_t* texData; + ktx_size_t texSize; + KTX_CHECK(ktxTexture_WriteToMemory(ktxTexture(kTexture), &texData, &texSize)); + + Array rawData(texSize); + std::memcpy(rawData.data(), texData, texSize); + free(texData); + + Serialization::save(buffer, rawData); } -void TextureAsset::load(Gfx::PGraphics graphics) +void TextureAsset::load(ArchiveBuffer& buffer) { setStatus(Status::Loading); - ktxTexture2* kTexture; - // TODO: consider return - std::cout << "Loading texture " << getFullPath() << std::endl; - ktxTexture2_CreateFromNamedFile(getFullPath().c_str(), - KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, - &kTexture); - TextureCreateInfo createInfo; - createInfo.width = kTexture->baseWidth; - createInfo.height = kTexture->baseHeight; - createInfo.depth = kTexture->baseDepth; - createInfo.bArray = kTexture->isArray; - createInfo.arrayLayers = kTexture->isArray ? kTexture->numLayers : kTexture->numFaces; - createInfo.format = Vulkan::cast((VkFormat)kTexture->vkFormat); - createInfo.mipLevels = kTexture->numLevels; - createInfo.usage = Gfx::SE_IMAGE_USAGE_SAMPLED_BIT; - createInfo.resourceData.data = ktxTexture_GetData(ktxTexture(kTexture)); - createInfo.resourceData.size = ktxTexture_GetDataSize(ktxTexture(kTexture)); - createInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; + Array rawData; + Serialization::load(buffer, rawData); + + ktxTexture2* kTexture; + std::cout << "Loading texture " << name << std::endl; + KTX_CHECK(ktxTexture_CreateFromMemory(rawData.data(), + rawData.size(), + KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, + (ktxTexture**) & kTexture)); + + //ktxTexture2_TranscodeBasis(kTexture, KTX_TTF_BC7_RGBA, 0); + + TextureCreateInfo createInfo = { + .resourceData = { + .size = ktxTexture_GetDataSize(ktxTexture(kTexture)), + .data = ktxTexture_GetData(ktxTexture(kTexture)), + .owner = Gfx::QueueType::DEDICATED_TRANSFER, + }, + .width = kTexture->baseWidth, + .height = kTexture->baseHeight, + .depth = kTexture->baseDepth, + .bArray = kTexture->isArray, + .arrayLayers = kTexture->isArray ? kTexture->numLayers : kTexture->numFaces, + .mipLevels = kTexture->numLevels, + .format = Vulkan::cast((VkFormat)kTexture->vkFormat), + .usage = Gfx::SE_IMAGE_USAGE_SAMPLED_BIT, + }; Gfx::PTexture tex; if (kTexture->isCubemap) { - tex = graphics->createTextureCube(createInfo); + tex = buffer.getGraphics()->createTextureCube(createInfo); } else if (kTexture->isArray) { - tex = graphics->createTexture3D(createInfo); + tex = buffer.getGraphics()->createTexture3D(createInfo); } else { - tex = graphics->createTexture2D(createInfo); + tex = buffer.getGraphics()->createTexture2D(createInfo); } tex->transferOwnership(Gfx::QueueType::GRAPHICS); setTexture(tex); + ktxTexture_Destroy(ktxTexture(kTexture)); setStatus(Asset::Status::Ready); } \ No newline at end of file diff --git a/src/Engine/Asset/TextureAsset.h b/src/Engine/Asset/TextureAsset.h index de526d3..264d9ce 100644 --- a/src/Engine/Asset/TextureAsset.h +++ b/src/Engine/Asset/TextureAsset.h @@ -7,20 +7,18 @@ DECLARE_NAME_REF(Gfx, Texture) class TextureAsset : public Asset { public: + static constexpr uint64 IDENTIFIER = 0x1; TextureAsset(); - TextureAsset(const std::string& directory, const std::string& name); - TextureAsset(const std::filesystem::path& fullPath); + TextureAsset(std::string_view folderPath, std::string_view name); virtual ~TextureAsset(); - virtual void save(Gfx::PGraphics graphics) override; - virtual void load(Gfx::PGraphics graphics) override; + virtual void save(ArchiveBuffer& buffer) const override; + virtual void load(ArchiveBuffer& buffer) override; void setTexture(Gfx::PTexture _texture) { - std::scoped_lock lck(lock); texture = _texture; } Gfx::PTexture getTexture() { - std::scoped_lock lck(lock); return texture; } private: diff --git a/src/Engine/Asset/TextureLoader.cpp b/src/Engine/Asset/TextureLoader.cpp index eea7473..53790b3 100644 --- a/src/Engine/Asset/TextureLoader.cpp +++ b/src/Engine/Asset/TextureLoader.cpp @@ -14,9 +14,15 @@ using namespace Seele; TextureLoader::TextureLoader(Gfx::PGraphics graphics) : graphics(graphics) { - placeholderAsset = new TextureAsset(std::filesystem::absolute("./textures/placeholder.ktx")); - placeholderAsset->load(graphics); - AssetRegistry::get().assetRoot.textures[""] = placeholderAsset; + //(std::filesystem::absolute("./textures/placeholder.ktx")); + //placeholderAsset->load(graphics); + //AssetRegistry::get().assetRoot.textures[""] = placeholderAsset; + placeholderAsset = new TextureAsset(); + import(TextureImportArgs{ + .filePath = std::filesystem::absolute("./textures/placeholder.png"), + .importPath = "", + }, placeholderAsset); + AssetRegistry::get().assetRoot->textures[""] = placeholderAsset; } TextureLoader::~TextureLoader() @@ -27,10 +33,10 @@ void TextureLoader::importAsset(TextureImportArgs args) { std::filesystem::path assetPath = args.filePath.filename(); assetPath.replace_extension("asset"); - PTextureAsset asset = new TextureAsset(assetPath.generic_string()); + PTextureAsset asset = new TextureAsset(args.importPath, assetPath.stem().string()); asset->setStatus(Asset::Status::Loading); asset->setTexture(placeholderAsset->getTexture()); - AssetRegistry::get().registerTexture(asset, args.importPath); + AssetRegistry::get().registerTexture(asset); import(args, asset); } @@ -45,22 +51,22 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) unsigned char* data = stbi_load(args.filePath.string().c_str(), &totalWidth, &totalHeight, &n, 4); ktxTexture2* kTexture; ktxTextureCreateInfo createInfo; + createInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM; + createInfo.baseDepth = 1; + createInfo.numLevels = 1; + createInfo.numLayers = 1; + createInfo.isArray = false; + createInfo.generateMipmaps = false; if (args.type == TextureImportType::TEXTURE_CUBEMAP) { uint32 faceWidth = totalWidth / 4; uint32 faceHeight = totalHeight / 3; // Cube map - createInfo.vkFormat = VK_FORMAT_R8G8B8A8_SRGB; createInfo.baseWidth = totalWidth / 4; createInfo.baseHeight = totalHeight / 3; - createInfo.baseDepth = 1; createInfo.numFaces = 6; createInfo.numDimensions = 2; - createInfo.numLevels = 1; - createInfo.numLayers = 1; - createInfo.isArray = false; - createInfo.generateMipmaps = true; ktxTexture2_Create(&createInfo, KTX_TEXTURE_CREATE_ALLOC_STORAGE, @@ -85,21 +91,15 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) loadCubeFace(0, 1, 1); // -X loadCubeFace(1, 0, 2); // +Y loadCubeFace(1, 2, 3); // -Y - loadCubeFace(1, 1, 4); // -Z + loadCubeFace(1, 1, 4); // +Z loadCubeFace(3, 1, 5); // -Z } else { - createInfo.vkFormat = VK_FORMAT_R8G8B8A8_SRGB; createInfo.baseWidth = totalWidth; createInfo.baseHeight = totalHeight; - createInfo.baseDepth = 1; - createInfo.numDimensions = 1 + (totalHeight > 1); - createInfo.numLevels = 1; - createInfo.numLayers = 1; createInfo.numFaces = 1; - createInfo.isArray = false; - createInfo.generateMipmaps = true; + createInfo.numDimensions = 1 + (totalHeight > 1); ktxTexture2_Create(&createInfo, KTX_TEXTURE_CREATE_ALLOC_STORAGE, @@ -108,13 +108,47 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) ktxTexture_SetImageFromMemory(ktxTexture(kTexture), 0, 0, 0, data, totalWidth * totalHeight * 4 * sizeof(unsigned char)); } + std::cout << "starting compression of " << textureAsset->getAssetIdentifier() << std::endl; + ktxBasisParams params = { + .structSize = sizeof(ktxBasisParams), + .uastc = KTX_TRUE, + .threadCount = std::thread::hardware_concurrency(), + .qualityLevel = 0, + }; + //ktx_error_code_e error = ktxTexture2_CompressBasisEx(kTexture, ¶ms); + //assert(error == KTX_SUCCESS); + //error = ktxTexture2_TranscodeBasis(kTexture, KTX_TTF_BC7_RGBA, 0); + //assert(error == KTX_SUCCESS); + stbi_image_free(data); - ktxTexture_WriteToNamedFile(ktxTexture(kTexture), textureAsset->getFullPath().c_str()); - ktxTexture_Destroy(ktxTexture(kTexture)); + TextureCreateInfo texInfo = { + .resourceData = { + .size = ktxTexture_GetDataSize(ktxTexture(kTexture)), + .data = ktxTexture_GetData(ktxTexture(kTexture)), + }, + .width = createInfo.baseWidth, + .height = createInfo.baseHeight, + .depth = createInfo.baseDepth, + .bArray = false, + .arrayLayers = createInfo.numFaces, + .mipLevels = 1, + .samples = 1, + .format = (Gfx::SeFormat)kTexture->vkFormat, + .usage = args.usage, + }; - textureAsset->load(graphics); + if (createInfo.numFaces == 1) + { + textureAsset->setTexture(graphics->createTexture2D(texInfo)); + } + else + { + textureAsset->setTexture(graphics->createTextureCube(texInfo)); + } + + ktxTexture_Destroy(ktxTexture(kTexture)); textureAsset->setStatus(Asset::Status::Ready); ////co_return; } \ No newline at end of file diff --git a/src/Engine/Asset/TextureLoader.h b/src/Engine/Asset/TextureLoader.h index 1109312..e632cf3 100644 --- a/src/Engine/Asset/TextureLoader.h +++ b/src/Engine/Asset/TextureLoader.h @@ -1,6 +1,7 @@ #pragma once #include "MinimalEngine.h" #include "Containers/List.h" +#include "Graphics/GraphicsEnums.h" #include namespace Seele @@ -18,6 +19,7 @@ struct TextureImportArgs std::filesystem::path filePath; std::string importPath; TextureImportType type = TextureImportType::TEXTURE_2D; + Gfx::SeImageUsageFlagBits usage = Gfx::SE_IMAGE_USAGE_SAMPLED_BIT; }; class TextureLoader { diff --git a/src/Engine/CMakeLists.txt b/src/Engine/CMakeLists.txt index c214030..a103123 100644 --- a/src/Engine/CMakeLists.txt +++ b/src/Engine/CMakeLists.txt @@ -1,5 +1,6 @@ target_sources(Engine PRIVATE + Concepts.h EngineTypes.h Game.h MinimalEngine.h @@ -8,6 +9,7 @@ target_sources(Engine target_sources(Engine PUBLIC FILE_SET HEADERS FILES + Concepts.h Game.h EngineTypes.h MinimalEngine.h) @@ -20,6 +22,7 @@ add_subdirectory(Graphics/) add_subdirectory(Material/) add_subdirectory(Math/) add_subdirectory(Physics/) +add_subdirectory(Serialization/) add_subdirectory(Scene/) add_subdirectory(System/) add_subdirectory(UI/) diff --git a/src/Engine/Concepts.h b/src/Engine/Concepts.h index 80fc1c3..ead3805 100644 --- a/src/Engine/Concepts.h +++ b/src/Engine/Concepts.h @@ -5,4 +5,13 @@ namespace Seele { template concept invocable = std::invocable; + +template +concept serializable = requires(T t, Archive& a) +{ + t->save(a); + t->load(a); +}; +template +concept enumeration = std::is_enum_v; } \ No newline at end of file diff --git a/src/Engine/Containers/List.h b/src/Engine/Containers/List.h index 567636c..3b6bb2b 100644 --- a/src/Engine/Containers/List.h +++ b/src/Engine/Containers/List.h @@ -34,7 +34,7 @@ public: : node(i.node) { } - IteratorBase(IteratorBase&& i) + IteratorBase(IteratorBase&& i) noexcept : node(std::move(i.node)) { } @@ -49,7 +49,7 @@ public: } return *this; } - IteratorBase& operator=(IteratorBase&& other) + IteratorBase& operator=(IteratorBase&& other) noexcept { if(this != &other) { diff --git a/src/Engine/Containers/Map.h b/src/Engine/Containers/Map.h index 2b2c51a..45d14e3 100644 --- a/src/Engine/Containers/Map.h +++ b/src/Engine/Containers/Map.h @@ -250,9 +250,7 @@ public: constexpr mapped_type& operator[](const key_type& key) { root = splay(root, key); - if (!isValid(root) - || comp(getNode(root)->pair.key, key) - || comp(key, getNode(root)->pair.key)) + if (!isValid(root) || !equal(getNode(root)->pair.key, key)) { root = insert(root, key); _size++; @@ -263,9 +261,7 @@ public: constexpr mapped_type& operator[](key_type&& key) { root = splay(root, std::move(key)); - if (!isValid(root) - || comp(getNode(root)->pair.key, key) - || comp(key, getNode(root)->pair.key)) + if (!isValid(root) || !equal(getNode(root)->pair.key, key)) { root = insert(root, std::move(key)); _size++; @@ -273,13 +269,32 @@ public: markIteratorsDirty(); return getNode(root)->pair.value; } + + constexpr mapped_type& at(const key_type& key) + { + root = splay(root, key); + if (!isValid(root) || !equal(getNode(root)->pair.key, key)) + { + throw std::logic_error("Key not found"); + } + markIteratorsDirty(); + return getNode(root)->pair.value; + } + constexpr mapped_type& at(key_type&& key) + { + root = splay(root, std::move(key)); + if (!isValid(root) || !equal(getNode(root)->pair.key, key)) + { + throw std::logic_error("Key not found"); + } + markIteratorsDirty(); + return getNode(root)->pair.value; + } constexpr iterator find(const key_type& key) { root = splay(root, key); refreshIterators(); - if (!isValid(root) - || comp(getNode(root)->pair.key, key) - || comp(key, getNode(root)->pair.key)) + if (!isValid(root) || !equal(getNode(root)->pair.key, key)) { return endIt; } @@ -289,9 +304,7 @@ public: { root = splay(root, std::move(key)); refreshIterators(); - if (!isValid(root) - || comp(getNode(root)->pair.key, key) - || comp(key, getNode(root)->pair.key)) + if (!isValid(root) || !equal(getNode(root)->pair.key, key)) { return endIt; } @@ -324,6 +337,14 @@ public: { return find(std::move(key)) != endIt; } + constexpr bool contains(const key_type& key) + { + return exists(key); + } + constexpr bool contains(key_type&& key) + { + return exists(key); + } constexpr iterator begin() { if(iteratorsDirty) @@ -476,13 +497,13 @@ private: r = splay(r, key); Node* node = getNode(r); - if (!(comp(node->pair.key, key) || comp(key, node->pair.key))) + if (equal(node->pair.key, key)) return r; Node *newNode = &nodeContainer.emplace(std::forward(key)); node = getNode(r); - if (comp(key, node->pair.key)) + if (comp(newNode->pair.key, node->pair.key)) { newNode->rightChild = r; newNode->leftChild = node->leftChild; @@ -506,7 +527,7 @@ private: r = splay(r, key); Node* node = getNode(r); - if (comp(node->pair.key, key) || comp(key, node->pair.key)) + if (!equal(node->pair.key, key)) return r; if (!isValid(node->leftChild)) @@ -549,9 +570,7 @@ private: size_t splay(size_t r, KeyType&& key) { Node* node = getNode(r); - if (node == nullptr - || !(comp(node->pair.key, key) - || comp(key, node->pair.key))) + if (node == nullptr || equal(node->pair.key, key)) { return r; } @@ -602,5 +621,9 @@ private: return (!isValid(node->rightChild)) ? r : rotateLeft(r); } } + bool equal(const key_type& a, const key_type& b) + { + return !comp(a, b) && !comp(b, a); + } }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Game.h b/src/Engine/Game.h index d4f51e5..36b1c53 100644 --- a/src/Engine/Game.h +++ b/src/Engine/Game.h @@ -10,7 +10,6 @@ class Game public: Game(AssetRegistry* registry) {} virtual ~Game() {} - virtual void importAssets() = 0; virtual void setupScene(PScene scene, PSystemGraph graph) = 0; }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/CMakeLists.txt b/src/Engine/Graphics/CMakeLists.txt index 4c7c7a3..f61c4ee 100644 --- a/src/Engine/Graphics/CMakeLists.txt +++ b/src/Engine/Graphics/CMakeLists.txt @@ -12,8 +12,6 @@ target_sources(Engine Mesh.cpp MeshBatch.h MeshBatch.cpp - RenderMaterial.h - RenderMaterial.cpp ShaderCompiler.h ShaderCompiler.cpp VertexShaderInput.h @@ -31,7 +29,6 @@ target_sources(Engine Graphics.h Mesh.h MeshBatch.h - RenderMaterial.h ShaderCompiler.h VertexShaderInput.h StaticMeshVertexInput.h) diff --git a/src/Engine/Graphics/GraphicsEnums.cpp b/src/Engine/Graphics/GraphicsEnums.cpp index 16465c9..63f530c 100644 --- a/src/Engine/Graphics/GraphicsEnums.cpp +++ b/src/Engine/Graphics/GraphicsEnums.cpp @@ -1,6 +1,117 @@ #include "GraphicsEnums.h" using namespace Seele; +using namespace Seele::Gfx; uint32 Gfx::currentFrameIndex = 0; -double Gfx::currentFrameDelta = 0; \ No newline at end of file +double Gfx::currentFrameDelta = 0; + +FormatCompatibilityInfo Gfx::getFormatInfo(SeFormat format) +{ + switch(format) { + case SE_FORMAT_R4G4_UNORM_PACK8: + case SE_FORMAT_R8_UNORM: + case SE_FORMAT_R8_SNORM: + case SE_FORMAT_R8_USCALED: + case SE_FORMAT_R8_SSCALED: + case SE_FORMAT_R8_UINT: + case SE_FORMAT_R8_SINT: + case SE_FORMAT_R8_SRGB: + return FormatCompatibilityInfo { + .blockSize = 1, + .blockExtent = UVector(1, 1, 1), + .texelsPerBlock = 1, + }; + case SE_FORMAT_R10X6_UNORM_PACK16: + case SE_FORMAT_R12X4_UNORM_PACK16: + //case SE_FORMAT_A4R4G4B4_UNORM_PACK16: + //case SE_FORMAT_A4B4G4R4_UNORM_PACK16: + case SE_FORMAT_R4G4B4A4_UNORM_PACK16: + case SE_FORMAT_B4G4R4A4_UNORM_PACK16: + case SE_FORMAT_R5G6B5_UNORM_PACK16: + case SE_FORMAT_B5G6R5_UNORM_PACK16: + case SE_FORMAT_R5G5B5A1_UNORM_PACK16: + case SE_FORMAT_B5G5R5A1_UNORM_PACK16: + case SE_FORMAT_A1R5G5B5_UNORM_PACK16: + case SE_FORMAT_R8G8_UNORM: + case SE_FORMAT_R8G8_SNORM: + case SE_FORMAT_R8G8_USCALED: + case SE_FORMAT_R8G8_SSCALED: + case SE_FORMAT_R8G8_UINT: + case SE_FORMAT_R8G8_SINT: + case SE_FORMAT_R8G8_SRGB: + case SE_FORMAT_R16_UNORM: + case SE_FORMAT_R16_SNORM: + case SE_FORMAT_R16_USCALED: + case SE_FORMAT_R16_SSCALED: + case SE_FORMAT_R16_UINT: + case SE_FORMAT_R16_SINT: + case SE_FORMAT_R16_SFLOAT: + return FormatCompatibilityInfo { + .blockSize = 2, + .blockExtent = UVector(1, 1, 1), + .texelsPerBlock = 1, + }; + case SE_FORMAT_BC7_UNORM_BLOCK: + case SE_FORMAT_BC7_SRGB_BLOCK: + return FormatCompatibilityInfo { + .blockSize = 16, + .blockExtent = UVector(4, 4, 1), + .texelsPerBlock = 16, + }; + case SE_FORMAT_R10X6G10X6_UNORM_2PACK16: + case SE_FORMAT_R12X4G12X4_UNORM_2PACK16: + //case SE_FORMAT_R16G16_S10_5_NV: + case SE_FORMAT_R8G8B8A8_UNORM: + case SE_FORMAT_R8G8B8A8_SNORM: + case SE_FORMAT_R8G8B8A8_USCALED: + case SE_FORMAT_R8G8B8A8_SSCALED: + case SE_FORMAT_R8G8B8A8_UINT: + case SE_FORMAT_R8G8B8A8_SINT: + case SE_FORMAT_R8G8B8A8_SRGB: + case SE_FORMAT_B8G8R8A8_UNORM: + case SE_FORMAT_B8G8R8A8_SNORM: + case SE_FORMAT_B8G8R8A8_USCALED: + case SE_FORMAT_B8G8R8A8_SSCALED: + case SE_FORMAT_B8G8R8A8_UINT: + case SE_FORMAT_B8G8R8A8_SINT: + case SE_FORMAT_B8G8R8A8_SRGB: + case SE_FORMAT_A8B8G8R8_UNORM_PACK32: + case SE_FORMAT_A8B8G8R8_SNORM_PACK32: + case SE_FORMAT_A8B8G8R8_USCALED_PACK32: + case SE_FORMAT_A8B8G8R8_SSCALED_PACK32: + case SE_FORMAT_A8B8G8R8_UINT_PACK32: + case SE_FORMAT_A8B8G8R8_SINT_PACK32: + case SE_FORMAT_A8B8G8R8_SRGB_PACK32: + case SE_FORMAT_A2R10G10B10_UNORM_PACK32: + case SE_FORMAT_A2R10G10B10_SNORM_PACK32: + case SE_FORMAT_A2R10G10B10_USCALED_PACK32: + case SE_FORMAT_A2R10G10B10_SSCALED_PACK32: + case SE_FORMAT_A2R10G10B10_UINT_PACK32: + case SE_FORMAT_A2R10G10B10_SINT_PACK32: + case SE_FORMAT_A2B10G10R10_UNORM_PACK32: + case SE_FORMAT_A2B10G10R10_SNORM_PACK32: + case SE_FORMAT_A2B10G10R10_USCALED_PACK32: + case SE_FORMAT_A2B10G10R10_SSCALED_PACK32: + case SE_FORMAT_A2B10G10R10_UINT_PACK32: + case SE_FORMAT_A2B10G10R10_SINT_PACK32: + case SE_FORMAT_R16G16_UNORM: + case SE_FORMAT_R16G16_SNORM: + case SE_FORMAT_R16G16_USCALED: + case SE_FORMAT_R16G16_SSCALED: + case SE_FORMAT_R16G16_UINT: + case SE_FORMAT_R16G16_SINT: + case SE_FORMAT_R16G16_SFLOAT: + case SE_FORMAT_R32_UINT: + case SE_FORMAT_R32_SINT: + case SE_FORMAT_R32_SFLOAT: + case SE_FORMAT_B10G11R11_UFLOAT_PACK32: + case SE_FORMAT_E5B9G9R9_UFLOAT_PACK32: + return FormatCompatibilityInfo{ + .blockSize = 4, + .blockExtent = Vector(1, 1, 1), + .texelsPerBlock = 1, + }; + } + throw new std::logic_error("not yet implemented"); +} diff --git a/src/Engine/Graphics/GraphicsEnums.h b/src/Engine/Graphics/GraphicsEnums.h index 77ecf02..a53046f 100644 --- a/src/Engine/Graphics/GraphicsEnums.h +++ b/src/Engine/Graphics/GraphicsEnums.h @@ -1,5 +1,6 @@ #pragma once #include "MinimalEngine.h" +#include "Math/Vector.h" namespace Seele { @@ -1003,6 +1004,16 @@ typedef enum SeFormat SE_FORMAT_MAX_ENUM = 0x7FFFFFFF } SeFormat; +struct FormatCompatibilityInfo +{ + // std::string class + uint32 blockSize; + UVector blockExtent; + uint32 texelsPerBlock; +}; + +FormatCompatibilityInfo getFormatInfo(SeFormat format); + typedef enum SeImageType { SE_IMAGE_TYPE_1D = 0, diff --git a/src/Engine/Graphics/GraphicsInitializer.h b/src/Engine/Graphics/GraphicsInitializer.h index 037a7e0..b1c5874 100644 --- a/src/Engine/Graphics/GraphicsInitializer.h +++ b/src/Engine/Graphics/GraphicsInitializer.h @@ -1,9 +1,9 @@ #pragma once #include "GraphicsEnums.h" +#include "Containers/Map.h" namespace Seele { - struct GraphicsInitializer { const char *applicationName; diff --git a/src/Engine/Graphics/GraphicsResources.cpp b/src/Engine/Graphics/GraphicsResources.cpp index e321e02..e196653 100644 --- a/src/Engine/Graphics/GraphicsResources.cpp +++ b/src/Engine/Graphics/GraphicsResources.cpp @@ -94,7 +94,7 @@ ShaderCollection& ShaderMap::createShaders( return collection; } -void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount, SeDescriptorBindingFlags bindingFlags) +void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount, SeDescriptorBindingFlags bindingFlags, SeShaderStageFlags shaderStages) { if (descriptorBindings.size() <= bindingIndex) { @@ -105,6 +105,7 @@ void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorTyp binding.descriptorType = type; binding.descriptorCount = arrayCount; binding.bindingFlags = bindingFlags; + binding.shaderStages = shaderStages; } PDescriptorSet DescriptorLayout::allocateDescriptorSet() diff --git a/src/Engine/Graphics/GraphicsResources.h b/src/Engine/Graphics/GraphicsResources.h index de62d50..3ca0a37 100644 --- a/src/Engine/Graphics/GraphicsResources.h +++ b/src/Engine/Graphics/GraphicsResources.h @@ -1,4 +1,5 @@ #pragma once +#include "Math/Math.h" #include "GraphicsEnums.h" #include "Containers/Array.h" #include "Containers/List.h" @@ -158,9 +159,9 @@ public: : binding(other.binding), descriptorType(other.descriptorType), descriptorCount(other.descriptorCount), shaderStages(other.shaderStages) { } - uint32_t binding; + uint32 binding; SeDescriptorType descriptorType; - uint32_t descriptorCount; + uint32 descriptorCount; SeDescriptorBindingFlags bindingFlags = 0; SeShaderStageFlags shaderStages; }; @@ -217,11 +218,12 @@ public: return *this; } virtual void create() = 0; - virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1, SeDescriptorBindingFlags bindingFlags = 0); + virtual void addDescriptorBinding(uint32 binding, SeDescriptorType type, uint32 arrayCount = 1, SeDescriptorBindingFlags bindingFlags = 0, SeShaderStageFlags shaderStages = SeShaderStageFlagBits::SE_SHADER_STAGE_ALL); virtual void reset(); virtual PDescriptorSet allocateDescriptorSet(); const Array &getBindings() const { return descriptorBindings; } - inline uint32 getSetIndex() const { return setIndex; } + constexpr uint32 getSetIndex() const { return setIndex; } + constexpr void setSetIndex(uint32 _setIndex) { setIndex = _setIndex; } protected: Array descriptorBindings; @@ -371,7 +373,7 @@ public: } virtual void updateRegion(BulkResourceData update) = 0; - + virtual void download(Array& buffer) = 0; protected: // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; @@ -396,6 +398,7 @@ public: return indexType; } + virtual void download(Array& buffer) = 0; protected: // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; @@ -543,6 +546,7 @@ public: virtual uint32 getSizeX() const = 0; virtual uint32 getSizeY() const = 0; virtual uint32 getSizeZ() const = 0; + virtual uint32 getNumFaces() const { return 1; } virtual SeSampleCountFlags getNumSamples() const = 0; virtual uint32 getMipLevels() const = 0; virtual void changeLayout(SeImageLayout newLayout) = 0; @@ -550,6 +554,7 @@ public: virtual class Texture3D* getTexture3D() { return nullptr; } virtual class TextureCube* getTextureCube() { return nullptr; } virtual void* getNativeHandle() { return nullptr; } + virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) = 0; protected: // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; @@ -612,6 +617,7 @@ public: virtual uint32 getSizeX() const = 0; virtual uint32 getSizeY() const = 0; virtual uint32 getSizeZ() const = 0; + virtual uint32 getNumFaces() const { return 6; } virtual SeSampleCountFlags getNumSamples() const = 0; virtual uint32 getMipLevels() const = 0; virtual void changeLayout(SeImageLayout newLayout) = 0; diff --git a/src/Engine/Graphics/Mesh.cpp b/src/Engine/Graphics/Mesh.cpp index c0e1835..fe76da0 100644 --- a/src/Engine/Graphics/Mesh.cpp +++ b/src/Engine/Graphics/Mesh.cpp @@ -1,5 +1,6 @@ #include "Mesh.h" #include "VertexShaderInput.h" +#include "Graphics/Graphics.h" using namespace Seele; diff --git a/src/Engine/Graphics/Mesh.h b/src/Engine/Graphics/Mesh.h index 9fc4da8..5338532 100644 --- a/src/Engine/Graphics/Mesh.h +++ b/src/Engine/Graphics/Mesh.h @@ -1,6 +1,6 @@ #pragma once #include "GraphicsResources.h" -#include "Material/MaterialInterface.h" +#include "Asset/MaterialAsset.h" namespace Seele { @@ -14,7 +14,7 @@ public: Gfx::PIndexBuffer indexBuffer; PVertexShaderInput vertexInput; - PMaterialInterface referencedMaterial; + PMaterialAsset referencedMaterial; private: }; DEFINE_REF(Mesh) diff --git a/src/Engine/Graphics/MeshBatch.cpp b/src/Engine/Graphics/MeshBatch.cpp index d628c12..d4db156 100644 --- a/src/Engine/Graphics/MeshBatch.cpp +++ b/src/Engine/Graphics/MeshBatch.cpp @@ -2,6 +2,7 @@ #include "GraphicsResources.h" #include "VertexShaderInput.h" #include "Material/MaterialInterface.h" +#include "Graphics/Graphics.h" using namespace Seele; diff --git a/src/Engine/Graphics/MeshBatch.h b/src/Engine/Graphics/MeshBatch.h index 14705b1..6a676ef 100644 --- a/src/Engine/Graphics/MeshBatch.h +++ b/src/Engine/Graphics/MeshBatch.h @@ -1,5 +1,6 @@ #pragma once #include "GraphicsEnums.h" +#include "Containers/Array.h" namespace Seele { @@ -47,8 +48,4 @@ struct MeshBatch MeshBatch& operator=(const MeshBatch& other) = default; MeshBatch& operator=(MeshBatch&& other) = default; }; -struct StaticMeshBatch : public MeshBatch -{ - uint32 index; -}; } // namespace Seele diff --git a/src/Engine/Graphics/RenderMaterial.cpp b/src/Engine/Graphics/RenderMaterial.cpp deleted file mode 100644 index 8b07183..0000000 --- a/src/Engine/Graphics/RenderMaterial.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "RenderMaterial.h" - -using namespace Seele; -using namespace Seele::Gfx; \ No newline at end of file diff --git a/src/Engine/Graphics/RenderMaterial.h b/src/Engine/Graphics/RenderMaterial.h deleted file mode 100644 index 04d992a..0000000 --- a/src/Engine/Graphics/RenderMaterial.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once -#include "GraphicsResources.h" - -namespace Seele -{ -namespace Gfx -{ -class MaterialShaderMap;//TODO implement -class MaterialRenderContext; -struct UniformExpressionCache -{ - Gfx::PUniformBuffer uniformBuffer; - uint8 bUpToDate; - - const MaterialShaderMap* cachedUniformExpressionShaderMap; -}; -class Material; -class RenderMaterial -{ -public: - mutable UniformExpressionCache uniformExpressionCache; - RenderMaterial(); - virtual ~RenderMaterial(); - - void evaluateUniformExpressions(UniformExpressionCache& outUniforExpressionCache, const MaterialRenderContext& context); - - void cacheUniformExpressions(bool bRecreatueUniformBuffer); - - void invalidateUniformExpressionCache(bool bRecreateUniformBuffer); - - void updateUniformExpressionCacheIfNeeded() const; - - const Material* getMaterial() const - { - const RenderMaterial* unused = nullptr; - return &getMaterialWithFallback(unused); - } - - virtual const Material& getMaterialWithFallback(const RenderMaterial*& outFallbackRenderMaterial) const = 0; - - virtual Material* getMaterialNoFallback() const { return nullptr; } -}; -} // namespace Gfx -} // namespace Seele diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index 68efdad..61d6fd8 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -35,6 +35,11 @@ void BasePassMeshProcessor::processMeshBatch( const PVertexShaderInput vertexInput = batch.vertexInput; const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput->getType()); + if(collection == nullptr) + { + material->createShaders(graphics, Gfx::RenderPassType::BasePass, vertexInput->getType()); + collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput->getType()); + } assert(collection != nullptr); Gfx::PRenderCommand renderCommand = graphics->createRenderCommand(); @@ -158,7 +163,7 @@ void BasePass::render() descriptorSets[INDEX_LIGHT_ENV]->writeChanges(); graphics->beginRenderPass(renderPass); - for (auto &&meshBatch : passData.staticDrawList) + for (const auto& meshBatch : passData.staticDrawList) { processor->processMeshBatch(meshBatch, viewport, renderPass, basePassLayout, primitiveLayout, descriptorSets); } diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index e8c42dd..976e076 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -28,7 +28,7 @@ DEFINE_REF(BasePassMeshProcessor) DECLARE_REF(CameraActor) struct BasePassData { - Array staticDrawList; + Array staticDrawList; Gfx::PStructuredBuffer sceneDataBuffer; }; class BasePass : public RenderPass diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp index 1d214f6..eca355e 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -34,6 +34,11 @@ void DepthPrepassMeshProcessor::processMeshBatch( const PVertexShaderInput vertexInput = batch.vertexInput; const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::DepthPrepass, vertexInput->getType()); + if (collection == nullptr) + { + material->createShaders(graphics, Gfx::RenderPassType::DepthPrepass, vertexInput->getType()); + collection = material->getShaders(Gfx::RenderPassType::DepthPrepass, vertexInput->getType()); + } assert(collection != nullptr); Gfx::PRenderCommand renderCommand = graphics->createRenderCommand(); @@ -128,7 +133,7 @@ void DepthPrepass::render() Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); depthAttachment->getTexture()->transferOwnership(Gfx::QueueType::GRAPHICS); graphics->beginRenderPass(renderPass); - for (auto &&meshBatch : passData.staticDrawList) + for (const auto& meshBatch : passData.staticDrawList) { processor->processMeshBatch(meshBatch, viewport, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets); } diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.h b/src/Engine/Graphics/RenderPass/DepthPrepass.h index 0fc97c5..a6d6cef 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.h +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.h @@ -25,7 +25,7 @@ private: DEFINE_REF(DepthPrepassMeshProcessor) struct DepthPrepassData { - Array staticDrawList; + Array staticDrawList; Gfx::PStructuredBuffer sceneDataBuffer; }; class DepthPrepass : public RenderPass diff --git a/src/Engine/Graphics/StaticMeshVertexInput.cpp b/src/Engine/Graphics/StaticMeshVertexInput.cpp index 1115b63..939146a 100644 --- a/src/Engine/Graphics/StaticMeshVertexInput.cpp +++ b/src/Engine/Graphics/StaticMeshVertexInput.cpp @@ -47,16 +47,15 @@ void StaticMeshVertexInput::init(Gfx::PGraphics graphics) { elements.add(accessStreamComponent(VertexStreamComponent(graphics->getNullVertexBuffer(), 0, 0, Gfx::SE_FORMAT_R32G32B32A32_SFLOAT), 4)); } - if(data.textureCoordinates.size()) + const int32 baseTexCoordAttribute = 5; + for(uint32 coordinateIndex = 0; coordinateIndex < MAX_TEXCOORDS; ++coordinateIndex) { - const int32 baseTexCoordAttribute = 5; - for(uint32 coordinateIndex = 0; coordinateIndex < data.textureCoordinates.size(); ++coordinateIndex) - { - elements.add(accessStreamComponent( - data.textureCoordinates[coordinateIndex], - static_cast(baseTexCoordAttribute + coordinateIndex) - )); - } + if (data.textureCoordinates[coordinateIndex].vertexBuffer == nullptr) + continue; + elements.add(accessStreamComponent( + data.textureCoordinates[coordinateIndex], + static_cast(baseTexCoordAttribute + coordinateIndex) + )); } initDeclaration(graphics, elements); } @@ -66,4 +65,17 @@ void StaticMeshVertexInput::setData(StaticMeshDataType&& _data) data = std::move(_data); } +void StaticMeshVertexInput::save(ArchiveBuffer& buffer) +{ + Serialization::save(buffer, name); + Serialization::save(buffer, data); +} + +void StaticMeshVertexInput::load(ArchiveBuffer& buffer) +{ + Serialization::load(buffer, name); + Serialization::load(buffer, data); + init(buffer.getGraphics()); +} + IMPLEMENT_VERTEX_INPUT_TYPE(StaticMeshVertexInput, "StaticMeshVertexInput") \ No newline at end of file diff --git a/src/Engine/Graphics/StaticMeshVertexInput.h b/src/Engine/Graphics/StaticMeshVertexInput.h index bec9aa3..3df4bd5 100644 --- a/src/Engine/Graphics/StaticMeshVertexInput.h +++ b/src/Engine/Graphics/StaticMeshVertexInput.h @@ -10,7 +10,7 @@ struct StaticMeshDataType VertexStreamComponent tangentBasisComponents[3]; //Dont forget these are 4 component vectors - Array textureCoordinates; + VertexStreamComponent textureCoordinates[4]; VertexStreamComponent colorComponent; }; @@ -21,9 +21,38 @@ public: StaticMeshVertexInput(std::string name); virtual ~StaticMeshVertexInput(); virtual void init(Gfx::PGraphics graphics) override; + virtual void save(ArchiveBuffer& buffer) override; + virtual void load(ArchiveBuffer& buffer) override; void setData(StaticMeshDataType&& data); private: StaticMeshDataType data; }; DEFINE_REF(StaticMeshVertexInput) -} \ No newline at end of file +namespace Serialization +{ + static void save(ArchiveBuffer& buffer, StaticMeshDataType& type) + { + Serialization::save(buffer, type.positionStream); + Serialization::save(buffer, type.tangentBasisComponents[0]); + Serialization::save(buffer, type.tangentBasisComponents[1]); + Serialization::save(buffer, type.tangentBasisComponents[2]); + Serialization::save(buffer, type.textureCoordinates[0]); + Serialization::save(buffer, type.textureCoordinates[1]); + Serialization::save(buffer, type.textureCoordinates[2]); + Serialization::save(buffer, type.textureCoordinates[3]); + Serialization::save(buffer, type.colorComponent); + } + static void load(ArchiveBuffer& buffer, StaticMeshDataType& type) + { + Serialization::load(buffer, type.positionStream); + Serialization::load(buffer, type.tangentBasisComponents[0]); + Serialization::load(buffer, type.tangentBasisComponents[1]); + Serialization::load(buffer, type.tangentBasisComponents[2]); + Serialization::load(buffer, type.textureCoordinates[0]); + Serialization::load(buffer, type.textureCoordinates[1]); + Serialization::load(buffer, type.textureCoordinates[2]); + Serialization::load(buffer, type.textureCoordinates[3]); + Serialization::load(buffer, type.colorComponent); + } +} // namespace Serialization +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/VertexShaderInput.cpp b/src/Engine/Graphics/VertexShaderInput.cpp index 27bc739..9b76586 100644 --- a/src/Engine/Graphics/VertexShaderInput.cpp +++ b/src/Engine/Graphics/VertexShaderInput.cpp @@ -6,6 +6,54 @@ using namespace Seele; +void Seele::Serialization::save(ArchiveBuffer& buffer, VertexStreamComponent& comp) +{ + if (comp.vertexBuffer == nullptr) + { + Serialization::save(buffer, (uint32)0); + } + else + { + Serialization::save(buffer, comp.vertexBuffer->getNumVertices()); + Serialization::save(buffer, comp.vertexBuffer->getVertexSize()); + Array rawBuffer; + comp.vertexBuffer->download(rawBuffer); + Serialization::save(buffer, rawBuffer); + Serialization::save(buffer, comp.streamOffset); + Serialization::save(buffer, comp.offset); + Serialization::save(buffer, comp.stride); + Serialization::save(buffer, comp.type); + } +} +void Seele::Serialization::load(ArchiveBuffer& buffer, VertexStreamComponent& comp) +{ + uint32 numVertices; + Serialization::load(buffer, numVertices); + if (numVertices == 0) + { + comp.vertexBuffer = nullptr; + } + else + { + uint32 vertexSize; + Serialization::load(buffer, vertexSize); + Array rawBuffer; + Serialization::load(buffer, rawBuffer); + VertexBufferCreateInfo createInfo = { + .resourceData = { + .size = rawBuffer.size(), + .data = rawBuffer.data(), + }, + .vertexSize = vertexSize, + .numVertices = numVertices, + }; + comp.vertexBuffer = buffer.getGraphics()->createVertexBuffer(createInfo); + Serialization::load(buffer, comp.streamOffset); + Serialization::load(buffer, comp.offset); + Serialization::load(buffer, comp.stride); + Serialization::load(buffer, comp.type); + } +} List& VertexInputType::getTypeList() { @@ -90,7 +138,6 @@ Gfx::VertexElement VertexShaderInput::accessStreamComponent(const VertexStreamCo { VertexStream vertexStream; vertexStream.vertexBuffer = component.vertexBuffer; - assert(component.stride < UINT8_MAX && component.offset < UINT8_MAX && component.offset < UINT8_MAX); vertexStream.stride = static_cast(component.stride); vertexStream.offset = static_cast(component.offset); @@ -101,7 +148,6 @@ Gfx::VertexElement VertexShaderInput::accessPositionStreamComponent(const Vertex { VertexStream vertexStream; vertexStream.vertexBuffer = component.vertexBuffer; - assert(component.stride < UINT8_MAX && component.offset < UINT8_MAX && component.offset < UINT8_MAX); vertexStream.stride = static_cast(component.stride); vertexStream.offset = static_cast(component.offset); @@ -116,4 +162,4 @@ void VertexShaderInput::initDeclaration(Gfx::PGraphics graphics, Array& elements) { positionDeclaration = graphics->createVertexDeclaration(elements); -} \ No newline at end of file +} diff --git a/src/Engine/Graphics/VertexShaderInput.h b/src/Engine/Graphics/VertexShaderInput.h index 1d3eb4c..3263b8c 100644 --- a/src/Engine/Graphics/VertexShaderInput.h +++ b/src/Engine/Graphics/VertexShaderInput.h @@ -2,6 +2,7 @@ #include "MinimalEngine.h" #include "GraphicsEnums.h" #include "GraphicsResources.h" +#include "Serialization/ArchiveBuffer.h" namespace Seele { @@ -75,8 +76,11 @@ struct VertexStreamComponent {} }; -#define STRUCTMEMBER_VERTEXSTREAMCOMPONENT(vertexBuffer, vertexType, member, memberType) \ - VertexStreamComponent(vertexBuffer, offsetof(vertexType, member), sizeof(vertexType), memberType) +namespace Serialization +{ + void save(ArchiveBuffer& buffer, VertexStreamComponent& comp); + void load(ArchiveBuffer& buffer, VertexStreamComponent& comp); +} // namespace Serialization class VertexInputType { @@ -120,6 +124,8 @@ public: void getPositionOnlyStream(VertexInputStreamArray& outVertexStreams) const; virtual bool supportsTesselation() { return false; } virtual VertexInputType* getType() const { return nullptr; } + virtual void save(ArchiveBuffer& buffer) {} + virtual void load(ArchiveBuffer& buffer) {} Gfx::PVertexDeclaration getDeclaration() const {return declaration;} Gfx::PVertexDeclaration getPositionDeclaration() const {return positionDeclaration;} std::string getName() const { return name; } diff --git a/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp b/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp index 1f638f7..bde1459 100644 --- a/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp @@ -182,7 +182,7 @@ void Allocation::markFree(SubAllocation *allocation) if (allocHandle == nullptr) { - allocHandle = new SubAllocation(this, allocation->alignedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize); + allocHandle = new SubAllocation(this, allocation->allocatedOffset, allocation->size, allocation->alignedOffset, allocation->allocatedSize); freeRanges[allocation->allocatedOffset] = allocHandle; } activeAllocations.erase(allocation->allocatedOffset); @@ -226,8 +226,7 @@ PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2 { std::scoped_lock lck(lock); const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements; - uint8 memoryTypeIndex; - VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex)); + uint32 memoryTypeIndex = findMemoryType(requirements.memoryTypeBits, properties); uint32 heapIndex = memProperties.memoryTypes[memoryTypeIndex].heapIndex; if (memRequirements2.pNext != nullptr) @@ -243,10 +242,13 @@ PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2 } for (auto alloc : heaps[heapIndex].allocations) { - PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment); - if (suballoc != nullptr) + if(alloc->memoryTypeIndex == memoryTypeIndex) { - return suballoc; + PSubAllocation suballoc = alloc->getSuballocation(requirements.size, requirements.alignment); + if (suballoc != nullptr) + { + return suballoc; + } } } @@ -273,22 +275,17 @@ void Allocator::free(Allocation *allocation) } } } -VkResult Allocator::findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex) +uint32 Allocator::findMemoryType(uint32 typeFilter, VkMemoryPropertyFlags properties) { - for (uint8 memoryIndex = 0; memoryIndex < memProperties.memoryTypeCount && typeBits; ++memoryIndex) + for (uint32 i = 0; i < memProperties.memoryTypeCount; i++) { - if ((typeBits & 1) == 1) + if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) { - if ((memProperties.memoryTypes[memoryIndex].propertyFlags & properties) == properties) - { - *typeIndex = memoryIndex; - return VK_SUCCESS; - } + return i; } - typeBits >>= 1; } - return VK_ERROR_FORMAT_NOT_SUPPORTED; + throw std::runtime_error("error finding memory"); } StagingBuffer::StagingBuffer() diff --git a/src/Engine/Graphics/Vulkan/VulkanAllocator.h b/src/Engine/Graphics/Vulkan/VulkanAllocator.h index 6d3ff73..409b5c8 100644 --- a/src/Engine/Graphics/Vulkan/VulkanAllocator.h +++ b/src/Engine/Graphics/Vulkan/VulkanAllocator.h @@ -155,7 +155,7 @@ private: Array allocations; }; Array heaps; - VkResult findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex); + uint32 findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties); std::mutex lock; PGraphics graphics; VkPhysicalDeviceMemoryProperties memProperties; diff --git a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp index de2dbcf..34dd3c7 100644 --- a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp @@ -208,7 +208,6 @@ void *ShaderBuffer::lockRegion(uint64 regionOffset, uint64 regionSize, bool bWri else { PCmdBuffer current = graphics->getQueueCommands(owner)->getCommands(); - graphics->getQueueCommands(owner)->submitCommands(); current->waitForCommand(); requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); @@ -466,6 +465,13 @@ void VertexBuffer::updateRegion(BulkResourceData update) unlock(); } +void VertexBuffer::download(Array& buffer) +{ + void* data = lock(false); + buffer.resize(size); + std::memcpy(buffer.data(), data, size); + unlock(); +} void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { @@ -509,6 +515,14 @@ IndexBuffer::~IndexBuffer() { } +void IndexBuffer::download(Array& buffer) +{ + void* data = lock(false); + buffer.resize(size); + std::memcpy(buffer.data(), data, size); + unlock(); +} + void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp index f9dd1b1..004554a 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp @@ -166,7 +166,12 @@ void CmdBuffer::refreshFence() void CmdBuffer::waitForCommand(uint32 timeout) { - std::scoped_lock lock(handleLock); + manager->submitCommands(); + if (state == State::InsideBegin) + { + // is already done + return; + } fence->wait(timeout); refreshFence(); } diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h index 4265dcf..e8099f8 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h @@ -21,7 +21,6 @@ private: PGraphics graphics; Array bindings; VkDescriptorSetLayout layoutHandle; - std::string name; friend class DescriptorAllocator; }; DEFINE_REF(DescriptorLayout) diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp index 8782e65..315d99b 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp @@ -501,7 +501,7 @@ void Graphics::createDevice(GraphicsInitializer initializer) numQueuesForFamily++; } } - if ((currProps.queueFlags & VK_QUEUE_COMPUTE_BIT) == VK_QUEUE_COMPUTE_BIT) + if (currProps.queueFlags & VK_QUEUE_COMPUTE_BIT) { if (computeQueueInfo.familyIndex == -1) { @@ -526,7 +526,7 @@ void Graphics::createDevice(GraphicsInitializer initializer) } } } - if ((currProps.queueFlags & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT) + if (currProps.queueFlags & VK_QUEUE_TRANSFER_BIT) { if (transferQueueInfo.familyIndex == -1) { @@ -587,6 +587,7 @@ void Graphics::createDevice(GraphicsInitializer initializer) deviceInfo.ppEnabledExtensionNames = initializer.deviceExtensions.data(); deviceInfo.enabledLayerCount = (uint32_t)initializer.layers.size(); deviceInfo.ppEnabledLayerNames = initializer.layers.data(); + deviceInfo.pEnabledFeatures = &features; VK_CHECK(vkCreateDevice(physicalDevice, &deviceInfo, nullptr, &handle)); std::cout << "Vulkan handle: " << handle << std::endl; diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.h b/src/Engine/Graphics/Vulkan/VulkanGraphics.h index f35378a..96f0c83 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.h @@ -68,7 +68,6 @@ public: virtual Gfx::PPipelineLayout createPipelineLayout(Gfx::PPipelineLayout baseLayout = nullptr) override; virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override; - protected: Array getRequiredExtensions(); void initInstance(GraphicsInitializer initInfo); diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h index 335eaca..38130fc 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h @@ -170,7 +170,7 @@ public: virtual ~VertexBuffer(); virtual void updateRegion(BulkResourceData update) override; - + virtual void download(Array& buffer) override; protected: // Inherited via Vulkan::Buffer virtual VkAccessFlags getSourceAccessMask(); @@ -189,6 +189,7 @@ public: IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData); virtual ~IndexBuffer(); + virtual void download(Array& buffer) override; protected: // Inherited via Vulkan::Buffer virtual VkAccessFlags getSourceAccessMask(); @@ -248,6 +249,7 @@ public: void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, VkPipelineStageFlags dstStage); void changeLayout(Gfx::SeImageLayout newLayout); + void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer); private: //Updates via reference @@ -314,6 +316,7 @@ public: return textureHandle->getMipLevels(); } virtual void changeLayout(Gfx::SeImageLayout newLayout) override; + virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) override; virtual void* getNativeHandle() override { return textureHandle; @@ -369,6 +372,7 @@ public: return textureHandle->getMipLevels(); } virtual void changeLayout(Gfx::SeImageLayout newLayout) override; + virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) override; virtual void* getNativeHandle() override { return textureHandle; @@ -424,6 +428,7 @@ public: return textureHandle->getMipLevels(); } virtual void changeLayout(Gfx::SeImageLayout newLayout) override; + virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) override; virtual void* getNativeHandle() override { return textureHandle; diff --git a/src/Engine/Graphics/Vulkan/VulkanTexture.cpp b/src/Engine/Graphics/Vulkan/VulkanTexture.cpp index be616cb..11cfe52 100644 --- a/src/Engine/Graphics/Vulkan/VulkanTexture.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanTexture.cpp @@ -4,6 +4,7 @@ #include "VulkanGraphicsEnums.h" #include "VulkanAllocator.h" #include "VulkanCommandBuffer.h" +#include "Graphics/GraphicsEnums.h" #include using namespace Seele; @@ -127,7 +128,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.mipLevel = 0; region.imageSubresource.baseArrayLayer = 0; - region.imageSubresource.layerCount = layerCount; + region.imageSubresource.layerCount = arrayCount * layerCount; region.imageOffset = {0, 0, 0}; region.imageExtent = {sizeX, sizeY, sizeZ}; @@ -212,6 +213,35 @@ void TextureHandle::changeLayout(Gfx::SeImageLayout newLayout) layout = newLayout; } +void TextureHandle::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) +{ + uint64 imageSize = sizeX * sizeY * sizeZ * Gfx::getFormatInfo(format).blockSize; + + PStagingBuffer stagingbuffer = graphics->getStagingManager()->allocateStagingBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true); + auto prevlayout = layout; + changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); + Gfx::FormatCompatibilityInfo formatInfo = Gfx::getFormatInfo(format); + VkBufferImageCopy region = { + .bufferOffset = 0, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = mipLevel, + .baseArrayLayer = arrayLayer * layerCount + face, + .layerCount = 1, + }, + .imageOffset = { 0, 0, 0 }, + .imageExtent = { sizeX, sizeY, sizeZ }, + }; + vkCmdCopyImageToBuffer(cmdBuffer->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingbuffer->getHandle(), 1, ®ion); + changeLayout(prevlayout); + buffer.resize(stagingbuffer->getSize()); + void* data = stagingbuffer->getMappedPointer(); + std::memcpy(buffer.data(), data, buffer.size()); +} + void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner) { VkImageMemoryBarrier imageBarrier = @@ -307,6 +337,11 @@ void Texture2D::changeLayout(Gfx::SeImageLayout newLayout) textureHandle->changeLayout(newLayout); } +void Texture2D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) +{ + textureHandle->download(mipLevel, arrayLayer, face, buffer); +} + void Texture2D::executeOwnershipBarrier(Gfx::QueueType newOwner) { textureHandle->executeOwnershipBarrier(newOwner); @@ -334,6 +369,10 @@ void Texture3D::changeLayout(Gfx::SeImageLayout newLayout) textureHandle->changeLayout(newLayout); } +void Texture3D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) +{ + textureHandle->download(mipLevel, arrayLayer, face, buffer); +} void Texture3D::executeOwnershipBarrier(Gfx::QueueType newOwner) { textureHandle->executeOwnershipBarrier(newOwner); @@ -361,6 +400,10 @@ void TextureCube::changeLayout(Gfx::SeImageLayout newLayout) textureHandle->changeLayout(newLayout); } +void TextureCube::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array& buffer) +{ + textureHandle->download(mipLevel, arrayLayer, face, buffer); +} void TextureCube::executeOwnershipBarrier(Gfx::QueueType newOwner) { textureHandle->executeOwnershipBarrier(newOwner); diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp index 089de6c..700c63f 100644 --- a/src/Engine/Material/Material.cpp +++ b/src/Engine/Material/Material.cpp @@ -40,9 +40,53 @@ Gfx::PDescriptorSet Material::createDescriptorSet() return descriptorSet; } -PMaterialInstance Material::instantiate() +void Material::save(ArchiveBuffer& buffer) const { - return new MaterialInstance(graphics, this); + MaterialInterface::save(buffer); + Serialization::save(buffer,materialName); + Serialization::save(buffer, layout->getSetIndex()); + const auto& bindings = layout->getBindings(); + Serialization::save(buffer, bindings.size()); + for (const auto& binding : bindings) + { + Serialization::save(buffer, binding.binding); + Serialization::save(buffer, binding.bindingFlags); + Serialization::save(buffer, binding.descriptorCount); + Serialization::save(buffer, binding.descriptorType); + Serialization::save(buffer, binding.shaderStages); + } +} + +void Material::load(ArchiveBuffer& buffer) +{ + graphics = buffer.getGraphics(); + MaterialInterface::load(buffer); + Serialization::load(buffer, materialName); + uint32 setIndex; + Serialization::load(buffer, setIndex); + uint64 numBindings; + Serialization::load(buffer, numBindings); + layout = graphics->createDescriptorLayout(); + for (uint64 i = 0; i < numBindings; ++i) + { + uint32 binding; + Serialization::load(buffer, binding); + + Gfx::SeDescriptorBindingFlags bindingFlags; + Serialization::load(buffer, bindingFlags); + + uint32 descriptorCount; + Serialization::load(buffer, descriptorCount); + + Gfx::SeDescriptorType descriptorType; + Serialization::load(buffer, descriptorType); + + Gfx::SeShaderStageFlags shaderStages; + Serialization::load(buffer, shaderStages); + + layout->addDescriptorBinding(binding, descriptorType, descriptorCount, bindingFlags, shaderStages); + } + layout->create(); } const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const @@ -50,8 +94,8 @@ const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass Gfx::ShaderPermutation permutation; permutation.passType = renderPass; std::string vertexInputName = vertexInput->getName(); - std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName)); - std::memcpy(permutation.vertexInputName, vertexInputName.c_str(), sizeof(permutation.vertexInputName)); + std::strncpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName)); + std::strncpy(permutation.vertexInputName, vertexInputName.c_str(), sizeof(permutation.vertexInputName)); return shaderMap.findShaders(Gfx::PermutationId(permutation)); } diff --git a/src/Engine/Material/Material.h b/src/Engine/Material/Material.h index 35d9f8e..8c9ac7b 100644 --- a/src/Engine/Material/Material.h +++ b/src/Engine/Material/Material.h @@ -7,13 +7,15 @@ DECLARE_REF(MaterialInstance) class Material : public MaterialInterface { public: + Material() {} Material(Gfx::PGraphics graphics, Array parameter, Gfx::PDescriptorLayout layout, uint32 uniformDataSize, uint32 uniformBinding, std::string materialName); virtual ~Material(); virtual Gfx::PDescriptorSet createDescriptorSet(); virtual Gfx::PDescriptorLayout getDescriptorLayout() const { return layout; } virtual const std::string& getName() { return materialName; } - PMaterialInstance instantiate(); + virtual void save(ArchiveBuffer& buffer) const; + virtual void load(ArchiveBuffer& buffer); virtual const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const; virtual Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput); @@ -29,4 +31,5 @@ private: friend class MaterialInstance; }; DEFINE_REF(Material) + } // namespace Seele diff --git a/src/Engine/Material/MaterialInterface.cpp b/src/Engine/Material/MaterialInterface.cpp index 2ea0371..73b1fbe 100644 --- a/src/Engine/Material/MaterialInterface.cpp +++ b/src/Engine/Material/MaterialInterface.cpp @@ -27,9 +27,10 @@ MaterialInterface::~MaterialInterface() { } + PShaderParameter MaterialInterface::getParameter(const std::string& name) { - for (auto param : parameters) + for (const auto& param : parameters) { if(param->name.compare(name) == 0) { @@ -37,4 +38,42 @@ PShaderParameter MaterialInterface::getParameter(const std::string& name) } } return nullptr; -} \ No newline at end of file +} + +void MaterialInterface::save(ArchiveBuffer& buffer) const +{ + Serialization::save(buffer, uniformDataSize); + Serialization::save(buffer, uniformBinding); + uint64 length = parameters.size(); + Serialization::save(buffer, length); + for (const auto& param : parameters) + { + Serialization::save(buffer, param); + } +} + +void MaterialInterface::load(ArchiveBuffer& buffer) +{ + graphics = buffer.getGraphics(); + Serialization::load(buffer, uniformDataSize); + Serialization::load(buffer, uniformBinding); + + if (uniformDataSize != 0) + { + uniformData.resize(uniformDataSize); + UniformBufferCreateInfo uniformInitializer = { + .resourceData = { + .size = uniformDataSize, + .data = nullptr, + } + }; + uniformBuffer = graphics->createUniformBuffer(uniformInitializer); + } + uint64 length; + Serialization::load(buffer, length); + parameters.resize(length); + for (auto& param : parameters) + { + Serialization::load(buffer, param); + } +} diff --git a/src/Engine/Material/MaterialInterface.h b/src/Engine/Material/MaterialInterface.h index f142d4a..afa039e 100644 --- a/src/Engine/Material/MaterialInterface.h +++ b/src/Engine/Material/MaterialInterface.h @@ -9,12 +9,16 @@ DECLARE_NAME_REF(Gfx, UniformBuffer) class MaterialInterface { public: + MaterialInterface() {} MaterialInterface(Gfx::PGraphics graphics, Array parameter, uint32 uniformDataSize, uint32 uniformBinding); virtual ~MaterialInterface(); PShaderParameter getParameter(const std::string& name); virtual Gfx::PDescriptorSet createDescriptorSet() = 0; virtual Gfx::PDescriptorLayout getDescriptorLayout() const = 0; + virtual void save(ArchiveBuffer& buffer) const; + virtual void load(ArchiveBuffer& buffer); + // The name of the generated material shader, opposed to the name of the .asset file virtual const std::string& getName() = 0; virtual const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const = 0; diff --git a/src/Engine/Material/ShaderExpression.cpp b/src/Engine/Material/ShaderExpression.cpp index 435eced..e42b01c 100644 --- a/src/Engine/Material/ShaderExpression.cpp +++ b/src/Engine/Material/ShaderExpression.cpp @@ -1,6 +1,8 @@ #include "ShaderExpression.h" #include "Graphics/GraphicsResources.h" #include "Asset/TextureAsset.h" +#include "Asset/AssetRegistry.h" +#include "Graphics/Graphics.h" using namespace Seele; @@ -15,8 +17,23 @@ ShaderParameter::~ShaderParameter() { } +void ShaderParameter::save(ArchiveBuffer& buffer) const +{ + Serialization::save(buffer, name); + Serialization::save(buffer, byteOffset); + Serialization::save(buffer, binding); +} + +void ShaderParameter::load(ArchiveBuffer& buffer) +{ + Serialization::load(buffer, name); + Serialization::load(buffer, byteOffset); + Serialization::load(buffer, binding); +} + FloatParameter::FloatParameter(std::string name, uint32 byteOffset, uint32 binding) : ShaderParameter(name, byteOffset, binding) + , data(0) { } @@ -24,6 +41,18 @@ FloatParameter::~FloatParameter() { } +void FloatParameter::save(ArchiveBuffer& buffer) const +{ + ShaderParameter::save(buffer); + Serialization::save(buffer, data); +} + +void FloatParameter::load(ArchiveBuffer& buffer) +{ + ShaderParameter::load(buffer); + Serialization::load(buffer, data); +} + void FloatParameter::updateDescriptorSet(Gfx::PDescriptorSet, uint8* dst) { std::memcpy(dst + byteOffset, &data, sizeof(float)); @@ -31,6 +60,7 @@ void FloatParameter::updateDescriptorSet(Gfx::PDescriptorSet, uint8* dst) VectorParameter::VectorParameter(std::string name, uint32 byteOffset, uint32 binding) : ShaderParameter(name, byteOffset, binding) + , data() { } @@ -38,11 +68,24 @@ VectorParameter::~VectorParameter() { } + void VectorParameter::updateDescriptorSet(Gfx::PDescriptorSet, uint8* dst) { std::memcpy(dst + byteOffset, &data, sizeof(Vector)); } +void VectorParameter::save(ArchiveBuffer& buffer) const +{ + ShaderParameter::save(buffer); + Serialization::save(buffer, data); +} + +void VectorParameter::load(ArchiveBuffer& buffer) +{ + ShaderParameter::load(buffer); + Serialization::load(buffer, data); +} + TextureParameter::TextureParameter(std::string name, uint32 byteOffset, uint32 binding) : ShaderParameter(name, byteOffset, binding) { @@ -57,6 +100,20 @@ void TextureParameter::updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, ui descriptorSet->updateTexture(binding, data->getTexture()); } +void TextureParameter::save(ArchiveBuffer& buffer) const +{ + ShaderParameter::save(buffer); + Serialization::save(buffer, data->getAssetIdentifier()); +} + +void TextureParameter::load(ArchiveBuffer& buffer) +{ + ShaderParameter::load(buffer); + std::string filename; + Serialization::load(buffer, filename); + data = AssetRegistry::findTexture(filename); +} + SamplerParameter::SamplerParameter(std::string name, uint32 byteOffset, uint32 binding) : ShaderParameter(name, byteOffset, binding) { @@ -72,6 +129,18 @@ void SamplerParameter::updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, ui descriptorSet->updateSampler(binding, data); } + +void SamplerParameter::save(ArchiveBuffer& buffer) const +{ + ShaderParameter::save(buffer); +} + +void SamplerParameter::load(ArchiveBuffer& buffer) +{ + ShaderParameter::load(buffer); + data = buffer.getGraphics()->createSamplerState({}); +} + CombinedTextureParameter::CombinedTextureParameter(std::string name, uint32 byteOffset, uint32 binding) : ShaderParameter(name, byteOffset, binding) { @@ -82,7 +151,56 @@ CombinedTextureParameter::~CombinedTextureParameter() } + void CombinedTextureParameter::updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8*) { descriptorSet->updateTexture(binding, data->getTexture(), sampler); +} + +void CombinedTextureParameter::save(ArchiveBuffer& buffer) const +{ + ShaderParameter::save(buffer); + Serialization::save(buffer, data->getAssetIdentifier()); +} + +void CombinedTextureParameter::load(ArchiveBuffer& buffer) +{ + ShaderParameter::load(buffer); + std::string filename; + Serialization::load(buffer, filename); + data = AssetRegistry::findTexture(filename); + sampler = buffer.getGraphics()->createSamplerState({}); +} + +void Serialization::save(ArchiveBuffer& buffer, const PShaderParameter& parameter) +{ + Serialization::save(buffer, parameter->getIdentifier()); + parameter->save(buffer); +} + +void Serialization::load(ArchiveBuffer& buffer, PShaderParameter& parameter) +{ + uint64 identifier = 0; + Serialization::load(buffer, identifier); + switch (identifier) + { + case FloatParameter::IDENTIFIER: + parameter = new FloatParameter(); + break; + case VectorParameter::IDENTIFIER: + parameter = new VectorParameter(); + break; + case TextureParameter::IDENTIFIER: + parameter = new TextureParameter(); + break; + case SamplerParameter::IDENTIFIER: + parameter = new SamplerParameter(); + break; + case CombinedTextureParameter::IDENTIFIER: + parameter = new CombinedTextureParameter(); + break; + default: + throw std::runtime_error("Unknown Identifier"); + } + parameter->load(buffer); } \ No newline at end of file diff --git a/src/Engine/Material/ShaderExpression.h b/src/Engine/Material/ShaderExpression.h index 3a5fdb2..b4a4b33 100644 --- a/src/Engine/Material/ShaderExpression.h +++ b/src/Engine/Material/ShaderExpression.h @@ -1,5 +1,7 @@ #pragma once #include "MinimalEngine.h" +#include "Math/Math.h" +#include "Asset/TextureAsset.h" namespace Seele { @@ -20,53 +22,86 @@ struct ShaderParameter : public ShaderExpression std::string name; uint32 byteOffset; uint32 binding; + ShaderParameter() {} ShaderParameter(std::string name, uint32 byteOffset, uint32 binding); virtual ~ShaderParameter(); // update a descriptorset, in case of a uniform buffer, copy the data to the dst + byteOffset virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) = 0; + virtual uint64 getIdentifier() const = 0; + virtual void save(ArchiveBuffer& buffer) const; + virtual void load(ArchiveBuffer& buffer); }; DEFINE_REF(ShaderParameter) struct FloatParameter : public ShaderParameter { + static constexpr uint64 IDENTIFIER = 0x01; float data; + FloatParameter() {} FloatParameter(std::string name, uint32 byteOffset, uint32 binding); virtual ~FloatParameter(); virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override; + virtual uint64 getIdentifier() const override { return IDENTIFIER; } + virtual void save(ArchiveBuffer& buffer) const override; + virtual void load(ArchiveBuffer& buffer) override; }; DEFINE_REF(FloatParameter) struct VectorParameter : public ShaderParameter { + static constexpr uint64 IDENTIFIER = 0x02; Vector data; + VectorParameter() {} VectorParameter(std::string name, uint32 byteOffset, uint32 binding); virtual ~VectorParameter(); virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override; + virtual uint64 getIdentifier() const override { return IDENTIFIER; } + virtual void save(ArchiveBuffer& buffer) const override; + virtual void load(ArchiveBuffer& buffer) override; }; DEFINE_REF(VectorParameter) -DECLARE_REF(TextureAsset) struct TextureParameter : public ShaderParameter { + static constexpr uint64 IDENTIFIER = 0x04; PTextureAsset data; + TextureParameter() {} TextureParameter(std::string name, uint32 byteOffset, uint32 binding); virtual ~TextureParameter(); virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override; + virtual uint64 getIdentifier() const override { return IDENTIFIER; } + virtual void save(ArchiveBuffer& buffer) const override; + virtual void load(ArchiveBuffer& buffer) override; }; DEFINE_REF(TextureParameter) DECLARE_NAME_REF(Gfx, SamplerState) struct SamplerParameter : public ShaderParameter { + static constexpr uint64 IDENTIFIER = 0x08; Gfx::PSamplerState data; + SamplerParameter() {} SamplerParameter(std::string name, uint32 byteOffset, uint32 binding); virtual ~SamplerParameter(); virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override; + virtual uint64 getIdentifier() const override { return IDENTIFIER; } + virtual void save(ArchiveBuffer& buffer) const override; + virtual void load(ArchiveBuffer& buffer) override; }; DEFINE_REF(SamplerParameter) struct CombinedTextureParameter : public ShaderParameter { + static constexpr uint64 IDENTIFIER = 0x10; PTextureAsset data; Gfx::PSamplerState sampler; + CombinedTextureParameter() {} CombinedTextureParameter(std::string name, uint32 byteOffset, uint32 binding); virtual ~CombinedTextureParameter(); virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override; + virtual uint64 getIdentifier() const override { return IDENTIFIER; } + virtual void save(ArchiveBuffer& buffer) const override; + virtual void load(ArchiveBuffer& buffer) override; }; DEFINE_REF(CombinedTextureParameter) +namespace Serialization +{ + void save(ArchiveBuffer& buffer, const PShaderParameter& parameter); + void load(ArchiveBuffer& buffer, PShaderParameter& parameter); +} // namespace Serialization } // namespace Seele diff --git a/src/Engine/Math/Vector.cpp b/src/Engine/Math/Vector.cpp index c6c12f5..d814d2e 100644 --- a/src/Engine/Math/Vector.cpp +++ b/src/Engine/Math/Vector.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "Serialization/ArchiveBuffer.h" using namespace Seele; diff --git a/src/Engine/Math/Vector.h b/src/Engine/Math/Vector.h index af363b0..e810180 100644 --- a/src/Engine/Math/Vector.h +++ b/src/Engine/Math/Vector.h @@ -8,6 +8,8 @@ #include #pragma warning(pop) #include +#include "Serialization/ArchiveBuffer.h" + namespace Seele { typedef glm::vec2 Vector2; @@ -15,11 +17,11 @@ typedef glm::vec3 Vector; typedef glm::vec4 Vector4; typedef glm::uvec2 UVector2; -typedef glm::uvec3 UVector3; +typedef glm::uvec3 UVector; typedef glm::uvec4 UVector4; typedef glm::ivec2 IVector2; -typedef glm::ivec3 IVector3; +typedef glm::ivec3 IVector; typedef glm::ivec4 IVector4; typedef glm::quat Quaternion; @@ -97,8 +99,34 @@ static inline Vector toRotator(const Quaternion &other) } void to_json(nlohmann::json& j, const Vector& vec); void from_json(nlohmann::json& j, Vector& vec); + +namespace Serialization +{ + static void save(ArchiveBuffer& buffer, const IVector2& vec) + { + save(buffer, vec.x); + save(buffer, vec.y); + } + static void load(ArchiveBuffer& buffer, IVector2& vec) + { + save(buffer, vec.x); + save(buffer, vec.y); + } + static void save(ArchiveBuffer& buffer, const Vector& vec) + { + save(buffer, vec.x); + save(buffer, vec.y); + save(buffer, vec.z); + } + static void load(ArchiveBuffer& buffer, Vector& vec) + { + save(buffer, vec.x); + save(buffer, vec.y); + save(buffer, vec.z); + } +} // namespace Serialization } // namespace Seele std::ostream& operator<<(std::ostream& stream, const Seele::Vector2& vector); std::ostream& operator<<(std::ostream& stream, const Seele::Vector& vector); -std::ostream& operator<<(std::ostream& stream, const Seele::Vector4& vector); \ No newline at end of file +std::ostream& operator<<(std::ostream& stream, const Seele::Vector4& vector); diff --git a/src/Engine/MinimalEngine.h b/src/Engine/MinimalEngine.h index 4975020..c62f2d7 100644 --- a/src/Engine/MinimalEngine.h +++ b/src/Engine/MinimalEngine.h @@ -1,7 +1,5 @@ #pragma once -#include "Containers/Map.h" #include "EngineTypes.h" -#include "Math/Math.h" #include #define DEFINE_REF(x) \ @@ -206,7 +204,7 @@ public: } return *this; } - constexpr RefPtr &operator=(RefPtr &&rhs) + constexpr RefPtr &operator=(RefPtr &&rhs) noexcept { if (this != &rhs) { @@ -260,7 +258,6 @@ public: { return RefPtr(new T(*getHandle())); } - private: RefObject *object; }; diff --git a/src/Engine/Physics/PhysicsSystem.cpp b/src/Engine/Physics/PhysicsSystem.cpp index 54715ff..955cb65 100644 --- a/src/Engine/Physics/PhysicsSystem.cpp +++ b/src/Engine/Physics/PhysicsSystem.cpp @@ -22,7 +22,7 @@ void PhysicsSystem::update(float deltaTime) Array initialBodies; readRigidBodies(initialBodies); - std::cout << "Updating " << initialBodies.size() << " bodies" << std::endl; + //std::cout << "Updating " << initialBodies.size() << " bodies" << std::endl; Array bodies = integratePhysics(initialBodies, 0, deltaTime); writeRigidBodies(bodies); diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index f61e9e6..51e9635 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -5,6 +5,7 @@ #include "Component/Transform.h" #include "Asset/AssetRegistry.h" #include "Asset/TextureAsset.h" +#include "Asset/MaterialAsset.h" using namespace Seele; @@ -28,9 +29,9 @@ void Scene::update(float deltaTime) physics.update(deltaTime); } -Array Scene::getStaticMeshes() +Array Scene::getStaticMeshes() { - Array result; + Array result; auto view = registry.view(); uint32 sceneDataIndex = 0; sceneData.clear(); @@ -44,7 +45,7 @@ Array Scene::getStaticMeshes() for(auto& m : mesh.mesh->meshes) { auto& batch = result.add(); - batch.material = m->referencedMaterial; + batch.material = m->referencedMaterial->getMaterial(); batch.isBackfaceCullingDisabled = false; batch.isCastingShadow = true; batch.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; diff --git a/src/Engine/Scene/Scene.h b/src/Engine/Scene/Scene.h index 10f33bf..c571080 100644 --- a/src/Engine/Scene/Scene.h +++ b/src/Engine/Scene/Scene.h @@ -69,7 +69,7 @@ public: { registry.view().each(func); } - Array getStaticMeshes(); + Array getStaticMeshes(); LightEnv getLightBuffer() const; Component::Skybox getSkybox(); Gfx::PStructuredBuffer getSceneDataBuffer() const { return sceneDataBuffer; } diff --git a/src/Engine/Serialization/ArchiveBuffer.cpp b/src/Engine/Serialization/ArchiveBuffer.cpp new file mode 100644 index 0000000..601411c --- /dev/null +++ b/src/Engine/Serialization/ArchiveBuffer.cpp @@ -0,0 +1,60 @@ +#include "ArchiveBuffer.h" +#include "Graphics/Graphics.h" + +using namespace Seele; + +ArchiveBuffer::ArchiveBuffer() +{} + +ArchiveBuffer::ArchiveBuffer(Gfx::PGraphics graphics) + : graphics(graphics) +{} + +void ArchiveBuffer::writeBytes(const void* data, uint64 size) +{ + if (size + position >= memory.size()) + { + memory.resize(size + position); + } + std::memcpy(memory.data() + position, data, size); + position += size; +} + +void ArchiveBuffer::readBytes(void* dest, uint64 size) +{ + assert(position + size <= memory.size()); + std::memcpy(dest, memory.data() + position, size); + position += size; +} + +void ArchiveBuffer::writeToStream(std::ostream& stream) +{ + uint64 bufferLength = memory.size(); + stream.write((char*)&version, sizeof(uint64)); + stream.write((char*)&bufferLength, sizeof(uint64)); + stream.write((char*)memory.data(), memory.size()); +} + +void ArchiveBuffer::readFromStream(std::istream& stream) +{ + stream.read((char*)&version, sizeof(uint64)); + uint64 bufferLength = 0; + stream.read((char*)&bufferLength, sizeof(uint64)); + memory.resize(bufferLength); + stream.read((char*)memory.data(), bufferLength); +} + +bool ArchiveBuffer::eof() const +{ + return position == memory.size(); +} + +void ArchiveBuffer::rewind() +{ + position = 0; +} + +Gfx::PGraphics& ArchiveBuffer::getGraphics() +{ + return graphics; +} diff --git a/src/Engine/Serialization/ArchiveBuffer.h b/src/Engine/Serialization/ArchiveBuffer.h index 4e07e71..e9563c2 100644 --- a/src/Engine/Serialization/ArchiveBuffer.h +++ b/src/Engine/Serialization/ArchiveBuffer.h @@ -1,13 +1,146 @@ #pragma once -#include "Array.h" +#include "MinimalEngine.h" +#include "Containers/Array.h" +#include "Concepts.h" +#include namespace Seele { +DECLARE_NAME_REF(Gfx, Graphics) class ArchiveBuffer { public: - + ArchiveBuffer(); + ArchiveBuffer(Gfx::PGraphics graphics); + void writeBytes(const void* data, uint64 size); + void readBytes(void* dest, uint64 size); + void writeToStream(std::ostream& stream); + void readFromStream(std::istream& stream); + bool eof() const; + void rewind(); + Gfx::PGraphics& getGraphics(); private: + Gfx::PGraphics graphics; + uint64 version = 0; + uint64 position = 0; Array memory; }; +namespace Serialization +{ + template + static void save(ArchiveBuffer& buffer, const T& type) + { + buffer.writeBytes(&type, sizeof(type)); + } + template + static void load(ArchiveBuffer& buffer, T& type) + { + buffer.readBytes(&type, sizeof(type)); + } + template + static void save(ArchiveBuffer& buffer, const T& type) + { + buffer.writeBytes(&type, sizeof(type)); + } + template + static void load(ArchiveBuffer& buffer, T& type) + { + buffer.readBytes(&type, sizeof(type)); + } + template + static void save(ArchiveBuffer& buffer, const T& type) + { + buffer.writeBytes(&type, sizeof(type)); + } + template + static void load(ArchiveBuffer& buffer, T& type) + { + buffer.readBytes(&type, sizeof(type)); + } + //template + //static void save(ArchiveBuffer& buffer, const T& type) + //{ + // type->save(buffer); + //} + //template + //static void load(ArchiveBuffer& buffer, T& type) + //{ + // type->load(buffer); + //} + static void save(ArchiveBuffer& buffer, const std::string& type) + { + uint64 length = type.size(); + buffer.writeBytes(&length, sizeof(uint64)); + buffer.writeBytes(type.data(), type.size() * sizeof(char)); + } + static void load(ArchiveBuffer& buffer, std::string& type) + { + uint64 length = 0; + buffer.readBytes(&length, sizeof(uint64)); + type.resize(length); + buffer.readBytes(type.data(), length * sizeof(char)); + } + //template + //static void save(ArchiveBuffer& buffer, const RefPtr& ptr) + //{ + // Serialization::save(buffer, *ptr.getHandle()); + //} + //template + //static void load(ArchiveBuffer& buffer, RefPtr& ptr) + //{ + // Serialization::load(buffer, *ptr.getHandle()); + //} + template + static void save(ArchiveBuffer& buffer, const Array& type) + { + uint64 length = type.size(); + buffer.writeBytes(&length, sizeof(uint64)); + buffer.writeBytes(type.data(), sizeof(T) * type.size()); + } + template + static void load(ArchiveBuffer& buffer, Array& type) + { + uint64 length = 0; + buffer.readBytes(&length, sizeof(uint64)); + type.resize(length); + buffer.readBytes(type.data(), sizeof(T) * type.size()); + } + + template + static void save(ArchiveBuffer& buffer, const Array& type) + { + uint64 length = type.size(); + buffer.writeBytes(&length, sizeof(uint64)); + buffer.writeBytes(type.data(), sizeof(T) * type.size()); + } + template + static void load(ArchiveBuffer& buffer, Array& type) + { + uint64 length = 0; + buffer.readBytes(&length, sizeof(uint64)); + type.resize(length); + buffer.readBytes(type.data(), sizeof(T) * type.size()); + } + template + static void save(ArchiveBuffer& buffer, const Array& type) requires (!std::is_integral_v && !std::is_floating_point_v) + { + uint64 length = type.size(); + buffer.writeBytes(&length, sizeof(uint64)); + for (const auto& x : type) + { + save(buffer, x); + } + } + template + static void load(ArchiveBuffer& buffer, Array& type) + { + uint64 length = 0; + buffer.readBytes(&length, sizeof(uint64)); + type.resize(length); + for (auto& x : type) + { + load(buffer, x); + } + } +} // namespace Serialization } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Serialization/CMakeLists.txt b/src/Engine/Serialization/CMakeLists.txt index 1c12ffe..3e27498 100644 --- a/src/Engine/Serialization/CMakeLists.txt +++ b/src/Engine/Serialization/CMakeLists.txt @@ -1,6 +1,7 @@ target_sources(Engine PRIVATE - ArchiveBuffer.h) + ArchiveBuffer.h + ArchiveBuffer.cpp) target_sources(Engine diff --git a/src/Engine/UI/Elements/Element.h b/src/Engine/UI/Elements/Element.h index b803b73..1b9d883 100644 --- a/src/Engine/UI/Elements/Element.h +++ b/src/Engine/UI/Elements/Element.h @@ -1,5 +1,7 @@ #pragma once #include "MinimalEngine.h" +#include "Containers/Array.h" +#include "Math/Math.h" namespace Seele { diff --git a/test/Engine/CMakeLists.txt b/test/Engine/CMakeLists.txt index 3bf7e40..5fb8aa3 100644 --- a/test/Engine/CMakeLists.txt +++ b/test/Engine/CMakeLists.txt @@ -8,4 +8,5 @@ target_sources(Seele_unit_tests target_include_directories(Seele_unit_tests PUBLIC ./) add_subdirectory(Containers/) add_subdirectory(Graphics/) -add_subdirectory(Math/) \ No newline at end of file +add_subdirectory(Math/) +add_subdirectory(Serialization/) \ No newline at end of file diff --git a/test/Engine/Serialization/ArchiveBuffer.cpp b/test/Engine/Serialization/ArchiveBuffer.cpp new file mode 100644 index 0000000..4f7f2db --- /dev/null +++ b/test/Engine/Serialization/ArchiveBuffer.cpp @@ -0,0 +1,10 @@ +#include "EngineTest.h" +#include + +using namespace Seele; + +BOOST_AUTO_TEST_SUITE(SaveLoadKtx) + +BOOST_AUTO_TEST_CASE(empty_constructur) +{ +} \ No newline at end of file diff --git a/test/Engine/Serialization/CMakeLists.txt b/test/Engine/Serialization/CMakeLists.txt new file mode 100644 index 0000000..3bc4f3c --- /dev/null +++ b/test/Engine/Serialization/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(Seele_unit_tests + PRIVATE + ArchiveBuffer.cpp) \ No newline at end of file