From b770625dfc492c3eb47f6326c63b8a3f57797f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20J=C3=B6nsson?= Date: Thu, 7 Mar 2024 21:18:41 +0100 Subject: [PATCH] Improved serializer and implemented concept serializers --- .../src/Sandbox/NodeGraph/IONodeGraphEditor.h | 3 +- .../src/Sandbox/Utility/AnimatedIcon.cpp | 4 +- .../src/Sandbox/Utility/EditorResources.cpp | 5 +- Volt/Volt/src/Volt/Asset/Asset.h | 1 + .../Volt/Asset/Importers/AssetImporter.cpp | 10 +- .../Asset/Importers/DDSTextureImporter.cpp | 12 +- .../Volt/Asset/Importers/DDSTextureImporter.h | 2 +- .../Importers/DefaultTextureImporter.cpp | 15 +- .../Asset/Importers/DefaultTextureImporter.h | 4 +- .../Volt/Asset/Importers/PrefabImporter.cpp | 4 +- .../Volt/Asset/Importers/SceneImporter.cpp | 20 +- .../src/Volt/Asset/Importers/SceneImporter.h | 14 +- .../Volt/Asset/Importers/TextureImporter.cpp | 6 +- .../Volt/Asset/Importers/TextureImporter.h | 6 +- .../Asset/ImportersNew/AssetSerializer.cpp | 13 +- .../Volt/Asset/ImportersNew/AssetSerializer.h | 2 +- .../Asset/ImportersNew/MeshSerializer.cpp | 4 +- .../Asset/ImportersNew/SceneSerializer.cpp | 470 ++++++++++++++++++ .../Volt/Asset/ImportersNew/SceneSerializer.h | 54 ++ ...hImporter.cpp => SourceMeshSerializer.cpp} | 4 +- ...eMeshImporter.h => SourceMeshSerializer.h} | 2 +- .../ImportersNew/SourceTextureSerializer.cpp | 29 ++ .../ImportersNew/SourceTextureSerializer.h | 13 + .../Asset/ImportersNew/TextureSerializer.cpp | 107 ++++ .../Asset/ImportersNew/TextureSerializer.h | 13 + .../Serialization/AssetSerializationCommon.h | 5 - Volt/Volt/src/Volt/Core/Buffer.h | 1 + .../Volt/Core/Graphics/VulkanAllocator.cpp | 7 + .../src/Volt/Core/Graphics/VulkanAllocator.h | 2 + Volt/Volt/src/Volt/Project/ProjectManager.cpp | 4 +- .../src/Volt/Rendering/Texture/Image2D.cpp | 6 + .../Volt/src/Volt/Rendering/Texture/Image2D.h | 2 + .../src/Volt/Rendering/Texture/ImageCommon.h | 1 + Volt/Volt/src/Volt/Scene/Scene.h | 1 + .../Utility/FileIO/BinaryStreamReader.cpp | 5 + .../Volt/Utility/FileIO/BinaryStreamReader.h | 50 +- .../Utility/FileIO/BinaryStreamWriter.cpp | 16 +- .../Volt/Utility/FileIO/BinaryStreamWriter.h | 111 +++-- .../Utility/FileIO/YAMLFileStreamWriter.cpp | 23 + .../Utility/FileIO/YAMLFileStreamWriter.h | 18 + .../Utility/FileIO/YAMLMemoryStreamWriter.cpp | 12 + .../Utility/FileIO/YAMLMemoryStreamWriter.h | 15 + .../Volt/Utility/FileIO/YAMLStreamWriter.cpp | 20 +- .../Volt/Utility/FileIO/YAMLStreamWriter.h | 7 +- Volt/Volt/src/Volt/Utility/ImageUtility.h | 50 +- 45 files changed, 1024 insertions(+), 149 deletions(-) create mode 100644 Volt/Volt/src/Volt/Asset/ImportersNew/SceneSerializer.cpp create mode 100644 Volt/Volt/src/Volt/Asset/ImportersNew/SceneSerializer.h rename Volt/Volt/src/Volt/Asset/ImportersNew/{SourceMeshImporter.cpp => SourceMeshSerializer.cpp} (82%) rename Volt/Volt/src/Volt/Asset/ImportersNew/{SourceMeshImporter.h => SourceMeshSerializer.h} (85%) create mode 100644 Volt/Volt/src/Volt/Asset/ImportersNew/SourceTextureSerializer.cpp create mode 100644 Volt/Volt/src/Volt/Asset/ImportersNew/SourceTextureSerializer.h create mode 100644 Volt/Volt/src/Volt/Asset/ImportersNew/TextureSerializer.cpp create mode 100644 Volt/Volt/src/Volt/Asset/ImportersNew/TextureSerializer.h create mode 100644 Volt/Volt/src/Volt/Utility/FileIO/YAMLFileStreamWriter.cpp create mode 100644 Volt/Volt/src/Volt/Utility/FileIO/YAMLFileStreamWriter.h create mode 100644 Volt/Volt/src/Volt/Utility/FileIO/YAMLMemoryStreamWriter.cpp create mode 100644 Volt/Volt/src/Volt/Utility/FileIO/YAMLMemoryStreamWriter.h diff --git a/Volt/Sandbox/src/Sandbox/NodeGraph/IONodeGraphEditor.h b/Volt/Sandbox/src/Sandbox/NodeGraph/IONodeGraphEditor.h index 131621df7..755c8613b 100644 --- a/Volt/Sandbox/src/Sandbox/NodeGraph/IONodeGraphEditor.h +++ b/Volt/Sandbox/src/Sandbox/NodeGraph/IONodeGraphEditor.h @@ -250,7 +250,8 @@ inline IONodeGraphEditor::IONodeGraphEditor(const std: SetGraphTypeText("GRAPHKEY"); } - myHeaderTexture = Volt::TextureImporter::ImportTexture("Editor/Textures/Graph/Translucency.dds"); + myHeaderTexture = CreateRef(); + Volt::TextureImporter::ImportTexture("Editor/Textures/Graph/Translucency.dds", *myHeaderTexture); { Ref editorContext = CreateRef(); diff --git a/Volt/Sandbox/src/Sandbox/Utility/AnimatedIcon.cpp b/Volt/Sandbox/src/Sandbox/Utility/AnimatedIcon.cpp index bcce90e3b..ec5127ddb 100644 --- a/Volt/Sandbox/src/Sandbox/Utility/AnimatedIcon.cpp +++ b/Volt/Sandbox/src/Sandbox/Utility/AnimatedIcon.cpp @@ -19,7 +19,9 @@ AnimatedIcon::AnimatedIcon(const std::filesystem::path& firstFrame, uint32_t fra for (uint32_t frame = 1; frame <= frameCount; frame++) { const std::filesystem::path path = dirPath / (filename + std::to_string(frame) + firstFrame.extension().string()); - myTextures.emplace_back(Volt::TextureImporter::ImportTexture(path)); + + myTextures.emplace_back() = CreateRef(); + Volt::TextureImporter::ImportTexture(path, *myTextures.back()); } VT_CORE_ASSERT(!myTextures.empty(), "No frames found!"); diff --git a/Volt/Sandbox/src/Sandbox/Utility/EditorResources.cpp b/Volt/Sandbox/src/Sandbox/Utility/EditorResources.cpp index b2995e7cb..9f30882f2 100644 --- a/Volt/Sandbox/src/Sandbox/Utility/EditorResources.cpp +++ b/Volt/Sandbox/src/Sandbox/Utility/EditorResources.cpp @@ -142,9 +142,10 @@ Ref EditorResources::GetEditorMesh(EditorMesh mesh) Ref EditorResources::TryLoadIcon(const std::filesystem::path& path) { - Ref texture = Volt::TextureImporter::ImportTexture(path); + Ref texture = CreateRef(); + Volt::TextureImporter::ImportTexture(path, *texture); - if (!texture) + if (!texture->IsValid()) { texture = Volt::Renderer::GetDefaultData().whiteTexture; } diff --git a/Volt/Volt/src/Volt/Asset/Asset.h b/Volt/Volt/src/Volt/Asset/Asset.h index 3d63c8708..5522f532d 100644 --- a/Volt/Volt/src/Volt/Asset/Asset.h +++ b/Volt/Volt/src/Volt/Asset/Asset.h @@ -53,6 +53,7 @@ namespace Volt PostProcessingMaterial = BIT(25), PostProcessingStack = BIT(26), MotionWeave = BIT(27), + TextureSource = BIT(28) }; inline AssetType operator|(AssetType aLhs, AssetType aRhs) diff --git a/Volt/Volt/src/Volt/Asset/Importers/AssetImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/AssetImporter.cpp index b895564ed..93546a5a8 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/AssetImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/AssetImporter.cpp @@ -32,7 +32,8 @@ namespace Volt { bool TextureSourceImporter::Load(const AssetMetadata& metadata, Ref& asset) const { - asset = CreateRef(); + Ref texture = std::reinterpret_pointer_cast(asset); + const auto filePath = AssetManager::GetFilesystemPath(metadata.filePath); if (!std::filesystem::exists(filePath)) @@ -41,17 +42,14 @@ namespace Volt asset->SetFlag(AssetFlag::Missing, true); return false; } - auto mesh = TextureImporter::ImportTexture(filePath); - if (!mesh) + if (!TextureImporter::ImportTexture(filePath, *texture)) { asset->SetFlag(AssetFlag::Invalid, true); return false; } - asset = mesh; - - Renderer::AddTexture(std::reinterpret_pointer_cast(asset)->GetImage()); + Renderer::AddTexture(texture->GetImage()); return true; } diff --git a/Volt/Volt/src/Volt/Asset/Importers/DDSTextureImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/DDSTextureImporter.cpp index a0b983a7b..4303ea5a5 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/DDSTextureImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/DDSTextureImporter.cpp @@ -59,6 +59,9 @@ namespace Volt case tdl::DDSFile::DXGIFormat::BC5_UNorm: return ImageFormat::BC5; + case tdl::DDSFile::DXGIFormat::BC6H_SF16: return ImageFormat::BC6H_SF16; + case tdl::DDSFile::DXGIFormat::BC6H_UF16: return ImageFormat::BC6H_UF16; + case tdl::DDSFile::DXGIFormat::BC7_UNorm: return ImageFormat::BC7; case tdl::DDSFile::DXGIFormat::BC7_UNorm_SRGB: return ImageFormat::BC7SRGB; } @@ -67,7 +70,7 @@ namespace Volt } } - Ref DDSTextureImporter::ImportTextureImpl(const std::filesystem::path& path) + bool DDSTextureImporter::ImportTextureImpl(const std::filesystem::path& path, Texture2D& outTexture) { tdl::DDSFile dds; auto returnCode = dds.Load(path.string().c_str()); @@ -79,7 +82,7 @@ namespace Volt if (dds.GetTextureDimension() != tdl::DDSFile::TextureDimension::Texture2D) { VT_CORE_ERROR("Texture {0} is not 2D!", path.string().c_str()); - return nullptr; + return false; } auto imageData = dds.GetImageData(); @@ -171,9 +174,8 @@ namespace Volt Utility::TransitionImageLayout(image->GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); image->OverrideLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - Ref texture = CreateRef(); - texture->myImage = image; + outTexture.myImage = image; - return texture; + return true; } } diff --git a/Volt/Volt/src/Volt/Asset/Importers/DDSTextureImporter.h b/Volt/Volt/src/Volt/Asset/Importers/DDSTextureImporter.h index de10cdec3..f7924fd50 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/DDSTextureImporter.h +++ b/Volt/Volt/src/Volt/Asset/Importers/DDSTextureImporter.h @@ -10,6 +10,6 @@ namespace Volt ~DDSTextureImporter() override = default; protected: - Ref ImportTextureImpl(const std::filesystem::path& path) override; + bool ImportTextureImpl(const std::filesystem::path& path, Texture2D& outTexture) override; }; } diff --git a/Volt/Volt/src/Volt/Asset/Importers/DefaultTextureImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/DefaultTextureImporter.cpp index 9969a6ef1..6611a5b54 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/DefaultTextureImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/DefaultTextureImporter.cpp @@ -2,12 +2,13 @@ #include "DefaultTextureImporter.h" #include "Volt/Rendering/Texture/Texture2D.h" +#include "Volt/Rendering/Texture/Image2D.h" #include namespace Volt { - Ref DefaultTextureImporter::ImportTextureImpl(const std::filesystem::path& path) + bool DefaultTextureImporter::ImportTextureImpl(const std::filesystem::path& path, Texture2D& outTexture) { int32_t width; int32_t height; @@ -34,9 +35,17 @@ namespace Volt format = ImageFormat::RGBA32F; } - Ref texture = CreateRef(format, width, height, data); + ImageSpecification imageSpec{}; + imageSpec.format = format; + imageSpec.usage = ImageUsage::Texture; + imageSpec.width = width; + imageSpec.height = height; + + Ref image = Image2D::Create(imageSpec, data); + outTexture.myImage = image; + stbi_image_free(data); - return texture; + return true; } } diff --git a/Volt/Volt/src/Volt/Asset/Importers/DefaultTextureImporter.h b/Volt/Volt/src/Volt/Asset/Importers/DefaultTextureImporter.h index 005ed9844..d6e7ebef5 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/DefaultTextureImporter.h +++ b/Volt/Volt/src/Volt/Asset/Importers/DefaultTextureImporter.h @@ -10,6 +10,6 @@ namespace Volt ~DefaultTextureImporter() override = default; protected: - Ref ImportTextureImpl(const std::filesystem::path& path) override; + bool ImportTextureImpl(const std::filesystem::path& path, Texture2D& outTexture) override; }; -} \ No newline at end of file +} diff --git a/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp index 4844e7139..12cdf9c47 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/PrefabImporter.cpp @@ -6,7 +6,7 @@ #include "Volt/Asset/Importers/SceneImporter.h" -#include "Volt/Utility/FileIO/YAMLStreamWriter.h" +#include "Volt/Utility/FileIO/YAMLFileStreamWriter.h" #include "Volt/Utility/FileIO/YAMLStreamReader.h" namespace Volt @@ -69,7 +69,7 @@ namespace Volt { const Ref prefab = std::reinterpret_pointer_cast(asset); - YAMLStreamWriter streamWriter{ AssetManager::GetFilesystemPath(metadata.filePath) }; + YAMLFileStreamWriter streamWriter{ AssetManager::GetFilesystemPath(metadata.filePath) }; streamWriter.BeginMap(); streamWriter.BeginMapNamned("Prefab"); diff --git a/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.cpp index 378492e65..6585b0570 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.cpp @@ -22,11 +22,11 @@ namespace Volt { template - void RegisterSerializationFunction(std::unordered_map>& outTypes) + void RegisterSerializationFunction(std::unordered_map>& outTypes) { VT_PROFILE_FUNCTION(); - outTypes[std::type_index{ typeid(T) }] = [](YAMLStreamWriter& streamWriter, const uint8_t* data, const size_t offset) + outTypes[std::type_index{ typeid(T) }] = [](YAMLFileStreamWriter& streamWriter, const uint8_t* data, const size_t offset) { const T& var = *reinterpret_cast(&data[offset]); streamWriter.SetKey("data", var); @@ -188,7 +188,7 @@ namespace Volt std::filesystem::path scenePath = directoryPath / (metadata.filePath.stem().string() + ".vtscene"); - YAMLStreamWriter streamWriter{ scenePath }; + YAMLFileStreamWriter streamWriter{ scenePath }; streamWriter.BeginMap(); streamWriter.BeginMapNamned("Scene"); streamWriter.SetKey("name", metadata.filePath.stem().string()); @@ -285,7 +285,7 @@ namespace Volt { const auto layerPath = layerFolderPath / ("layer_" + std::to_string(layer.id) + ".vtlayer"); - YAMLStreamWriter streamWriter{ layerPath }; + YAMLFileStreamWriter streamWriter{ layerPath }; streamWriter.BeginMap(); streamWriter.BeginMapNamned("Layer"); { @@ -332,7 +332,7 @@ namespace Volt Entity entity = entities.at(i); const auto entityPath = entitiesDirectoryPath / (entity.ToString() + ".entity"); - YAMLStreamWriter streamWriter{ entityPath }; + YAMLFileStreamWriter streamWriter{ entityPath }; SerializeEntity(entity, metadata, scene, streamWriter); streamWriter.WriteToDisk(); @@ -424,7 +424,7 @@ namespace Volt } } - void SceneImporter::SerializeWorldEngine(const Ref& scene, YAMLStreamWriter& streamWriter) const + void SceneImporter::SerializeWorldEngine(const Ref& scene, YAMLFileStreamWriter& streamWriter) const { auto& worldEngine = scene->m_worldEngine; @@ -532,7 +532,7 @@ namespace Volt return scene->CreateEntityWithUUID(entityId); } - void SceneImporter::SerializeEntity(entt::entity id, const AssetMetadata& metadata, const Ref& scene, YAMLStreamWriter& streamWriter) const + void SceneImporter::SerializeEntity(entt::entity id, const AssetMetadata& metadata, const Ref& scene, YAMLFileStreamWriter& streamWriter) const { streamWriter.BeginMap(); streamWriter.BeginMapNamned("Entity"); @@ -594,7 +594,7 @@ namespace Volt streamWriter.EndMap(); } - void SceneImporter::SerializeClass(const uint8_t* data, const size_t offset, const IComponentTypeDesc* compDesc, YAMLStreamWriter& streamWriter, bool isSubComponent) const + void SceneImporter::SerializeClass(const uint8_t* data, const size_t offset, const IComponentTypeDesc* compDesc, YAMLFileStreamWriter& streamWriter, bool isSubComponent) const { if (!isSubComponent) { @@ -655,7 +655,7 @@ namespace Volt } } - void SceneImporter::SerializeArray(const uint8_t* data, const size_t offset, const IArrayTypeDesc* arrayDesc, YAMLStreamWriter& streamWriter) const + void SceneImporter::SerializeArray(const uint8_t* data, const size_t offset, const IArrayTypeDesc* arrayDesc, YAMLFileStreamWriter& streamWriter) const { const void* arrayPtr = &data[offset]; @@ -704,7 +704,7 @@ namespace Volt streamWriter.EndSequence(); } - void SceneImporter::SerializeMono(entt::entity id, const Ref& scene, YAMLStreamWriter& streamWriter) const + void SceneImporter::SerializeMono(entt::entity id, const Ref& scene, YAMLFileStreamWriter& streamWriter) const { const auto& scriptFieldCache = scene->GetScriptFieldCache(); diff --git a/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.h b/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.h index b955e01a4..b7be92041 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.h +++ b/Volt/Volt/src/Volt/Asset/Importers/SceneImporter.h @@ -2,7 +2,7 @@ #include "Volt/Asset/Importers/AssetImporter.h" -#include "Volt/Utility/FileIO/YAMLStreamWriter.h" +#include "Volt/Utility/FileIO/YAMLFileStreamWriter.h" #include "Volt/Utility/FileIO/YAMLStreamReader.h" #include "Volt/Scene/Entity.h" @@ -32,7 +32,7 @@ namespace Volt bool Load(const AssetMetadata& metadata, Ref& asset) const override; void Save(const AssetMetadata& metadata, const Ref& asset) const override; - void SerializeEntity(entt::entity id, const AssetMetadata& metadata, const Ref& scene, YAMLStreamWriter& streamWriter) const; + void SerializeEntity(entt::entity id, const AssetMetadata& metadata, const Ref& scene, YAMLFileStreamWriter& streamWriter) const; void DeserializeEntity(const Ref& scene, const AssetMetadata& metadata, YAMLStreamReader& streamReader) const; void DeserializeMono(entt::entity id, const Ref& scene, YAMLStreamReader& streamReader) const; @@ -50,21 +50,21 @@ namespace Volt void SaveEntities(const AssetMetadata& metadata, const Ref& scene, const std::filesystem::path& sceneDirectory) const; void LoadEntities(const AssetMetadata& metadata, const Ref& scene, const std::filesystem::path& sceneDirectory) const; - void SerializeWorldEngine(const Ref& scene, YAMLStreamWriter& streamWriter) const; + void SerializeWorldEngine(const Ref& scene, YAMLFileStreamWriter& streamWriter) const; void DeserializeWorldEngine(const Ref& scene, YAMLStreamReader& streamReader) const; void LoadCellEntities(const AssetMetadata& metadata, const Ref& scene, const std::filesystem::path& sceneDirectory) const; Entity CreateEntityFromUUIDThreadSafe(EntityID entityId, const Ref& scene) const; - void SerializeClass(const uint8_t* data, const size_t offset, const IComponentTypeDesc* compDesc, YAMLStreamWriter& streamWriter, bool isSubComponent) const; - void SerializeArray(const uint8_t* data, const size_t offset, const IArrayTypeDesc* arrayDesc, YAMLStreamWriter& streamWriter) const; - void SerializeMono(entt::entity id, const Ref& scene, YAMLStreamWriter& streamWriter) const; + void SerializeClass(const uint8_t* data, const size_t offset, const IComponentTypeDesc* compDesc, YAMLFileStreamWriter& streamWriter, bool isSubComponent) const; + void SerializeArray(const uint8_t* data, const size_t offset, const IArrayTypeDesc* arrayDesc, YAMLFileStreamWriter& streamWriter) const; + void SerializeMono(entt::entity id, const Ref& scene, YAMLFileStreamWriter& streamWriter) const; void DeserializeClass(uint8_t* data, const size_t offset, const IComponentTypeDesc* compDesc, YAMLStreamReader& streamReader) const; void DeserializeArray(uint8_t* data, const size_t offset, const IArrayTypeDesc* arrayDesc, YAMLStreamReader& streamReader) const; - inline static std::unordered_map> s_typeSerializers; + inline static std::unordered_map> s_typeSerializers; inline static std::unordered_map> s_typeDeserializers; }; } diff --git a/Volt/Volt/src/Volt/Asset/Importers/TextureImporter.cpp b/Volt/Volt/src/Volt/Asset/Importers/TextureImporter.cpp index 4f130f708..c4a57aba9 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/TextureImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/Importers/TextureImporter.cpp @@ -17,9 +17,9 @@ namespace Volt s_importers.clear(); } - Ref TextureImporter::ImportTexture(const std::filesystem::path& path) + bool TextureImporter::ImportTexture(const std::filesystem::path& path, Texture2D& outTexture) { - return s_importers[FormatFromExtension(path)]->ImportTextureImpl(path); + return s_importers[FormatFromExtension(path)]->ImportTextureImpl(path, outTexture); } TextureImporter::TextureFormat TextureImporter::FormatFromExtension(const std::filesystem::path& path) @@ -34,4 +34,4 @@ namespace Volt return TextureFormat::Other; } -} \ No newline at end of file +} diff --git a/Volt/Volt/src/Volt/Asset/Importers/TextureImporter.h b/Volt/Volt/src/Volt/Asset/Importers/TextureImporter.h index 4a6cd0c4d..c4bc98970 100644 --- a/Volt/Volt/src/Volt/Asset/Importers/TextureImporter.h +++ b/Volt/Volt/src/Volt/Asset/Importers/TextureImporter.h @@ -16,10 +16,10 @@ namespace Volt static void Initialize(); static void Shutdown(); - static Ref ImportTexture(const std::filesystem::path& path); + static bool ImportTexture(const std::filesystem::path& path, Texture2D& outTexture); protected: - virtual Ref ImportTextureImpl(const std::filesystem::path& path) = 0; + virtual bool ImportTextureImpl(const std::filesystem::path& path, Texture2D& outTexture) = 0; private: enum class TextureFormat @@ -31,4 +31,4 @@ namespace Volt static TextureFormat FormatFromExtension(const std::filesystem::path& path); inline static std::unordered_map> s_importers; }; -} \ No newline at end of file +} diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/AssetSerializer.cpp b/Volt/Volt/src/Volt/Asset/ImportersNew/AssetSerializer.cpp index 5ef2a9811..e5f67b16f 100644 --- a/Volt/Volt/src/Volt/Asset/ImportersNew/AssetSerializer.cpp +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/AssetSerializer.cpp @@ -3,28 +3,19 @@ namespace Volt { - void AssetSerializer::WriteMetadata(const AssetMetadata& metadata, const uint32_t version, BinaryStreamWriter& streamWriter) + size_t AssetSerializer::WriteMetadata(const AssetMetadata& metadata, const uint32_t version, BinaryStreamWriter& streamWriter) { - SerializedAssetMetadataHeader metadataHeader{}; - metadataHeader.assetMetadataSize = sizeof(SerializedAssetMetadata); - SerializedAssetMetadata serializedMetadata{}; serializedMetadata.handle = metadata.handle; serializedMetadata.type = metadata.type; serializedMetadata.version = version; - streamWriter.Write(metadataHeader); - streamWriter.Write(serializedMetadata); + return streamWriter.Write(serializedMetadata); } SerializedAssetMetadata AssetSerializer::ReadMetadata(BinaryStreamReader& streamReader) { - SerializedAssetMetadataHeader header{}; SerializedAssetMetadata result{}; - - streamReader.Read(header); - VT_CORE_ASSERT(sizeof(SerializedAssetMetadata) == header.assetMetadataSize, "Size mismatch!"); - streamReader.Read(result); return result; } diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/AssetSerializer.h b/Volt/Volt/src/Volt/Asset/ImportersNew/AssetSerializer.h index a01d3361c..e4043499c 100644 --- a/Volt/Volt/src/Volt/Asset/ImportersNew/AssetSerializer.h +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/AssetSerializer.h @@ -17,7 +17,7 @@ namespace Volt virtual void Serialize(const AssetMetadata& metadata, const Ref& asset) const = 0; virtual bool Deserialize(const AssetMetadata& metadata, Ref destinationAsset) const = 0; - static void WriteMetadata(const AssetMetadata& metadata, const uint32_t version, BinaryStreamWriter& streamWriter); + [[nodiscard]] static size_t WriteMetadata(const AssetMetadata& metadata, const uint32_t version, BinaryStreamWriter& streamWriter); static SerializedAssetMetadata ReadMetadata(BinaryStreamReader& streamReader); }; } diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/MeshSerializer.cpp b/Volt/Volt/src/Volt/Asset/ImportersNew/MeshSerializer.cpp index 11cf2cc75..58b5977bf 100644 --- a/Volt/Volt/src/Volt/Asset/ImportersNew/MeshSerializer.cpp +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/MeshSerializer.cpp @@ -49,7 +49,7 @@ namespace Volt Ref mesh = std::reinterpret_pointer_cast(asset); BinaryStreamWriter streamWriter{}; - AssetSerializer::WriteMetadata(metadata, CURRENT_ASSET_VERSION, streamWriter); + const size_t compressedDataOffset = AssetSerializer::WriteMetadata(metadata, CURRENT_ASSET_VERSION, streamWriter); MeshSerializationData serializationData{}; serializationData.materialHandle = mesh->GetMaterial()->handle; @@ -62,7 +62,7 @@ namespace Volt streamWriter.Write(serializationData); const auto filePath = AssetManager::GetFilesystemPath(metadata.filePath); - streamWriter.WriteToDisk(filePath, true, sizeof(SerializedAssetMetadata)); + streamWriter.WriteToDisk(filePath, false, compressedDataOffset); } bool MeshSerializer::Deserialize(const AssetMetadata& metadata, Ref destinationAsset) const diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/SceneSerializer.cpp b/Volt/Volt/src/Volt/Asset/ImportersNew/SceneSerializer.cpp new file mode 100644 index 000000000..f3df0372e --- /dev/null +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/SceneSerializer.cpp @@ -0,0 +1,470 @@ +#include "vtpch.h" +#include "SceneSerializer.h" + +#include "Volt/Asset/AssetManager.h" + +#include "Volt/Components/CoreComponents.h" +#include "Volt/Components/RenderingComponents.h" + +#include "Volt/Scene/Scene.h" +#include "Volt/Scene/Entity.h" +#include "Volt/Scene/Reflection/ComponentReflection.h" +#include "Volt/Scene/Reflection/ComponentRegistry.h" + +#include "Volt/Scripting/Mono/MonoScriptClass.h" +#include "Volt/Scripting/Mono/MonoScriptEngine.h" + +#include "Volt/Core/BinarySerializer.h" + +#include "Volt/Utility/Algorithms.h" +#include "Volt/Utility/FileSystem.h" + +#include "Volt/Utility/FileIO/YAMLMemoryStreamWriter.h" +#include "Volt/Utility/FileIO/YAMLStreamReader.h" + +namespace Volt +{ + inline static constexpr uint32_t CURRENT_ASSET_VERSION = 1; + inline static constexpr uint32_t ENTITY_MAGIC_VAL = 1515; + + template + void RegisterSerializationFunction(std::unordered_map>& outTypes) + { + VT_PROFILE_FUNCTION(); + + outTypes[std::type_index{ typeid(T) }] = [](YAMLMemoryStreamWriter& streamWriter, const uint8_t* data, const size_t offset) + { + const T& var = *reinterpret_cast(&data[offset]); + streamWriter.SetKey("data", var); + }; + } + + template + void RegisterDeserializationFunction(std::unordered_map>& outTypes) + { + VT_PROFILE_FUNCTION(); + + outTypes[std::type_index{ typeid(T) }] = [](YAMLStreamReader& streamReader, uint8_t* data, const size_t offset) + { + *reinterpret_cast(&data[offset]) = streamReader.ReadKey("data", T()); + }; + } + + SceneSerializer::SceneSerializer() + { + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + + RegisterSerializationFunction(s_typeSerializers); + RegisterSerializationFunction(s_typeSerializers); + + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + + RegisterDeserializationFunction(s_typeDeserializers); + RegisterDeserializationFunction(s_typeDeserializers); + + s_instance = this; + } + + SceneSerializer::~SceneSerializer() + { + s_instance = nullptr; + } + + void SceneSerializer::Serialize(const AssetMetadata& metadata, const Ref& asset) const + { + const Ref scene = std::reinterpret_pointer_cast(asset); + + std::filesystem::path directoryPath = AssetManager::GetFilesystemPath(metadata.filePath); + if (!std::filesystem::is_directory(directoryPath)) + { + directoryPath = directoryPath.parent_path(); + } + + std::filesystem::path scenePath = directoryPath / (metadata.filePath.stem().string() + ".vtasset"); + + // Serialize scene file + { + YAMLMemoryStreamWriter streamWriter{}; + streamWriter.BeginMap(); + streamWriter.BeginMapNamned("Scene"); + streamWriter.SetKey("name", metadata.filePath.stem().string()); + + streamWriter.BeginMapNamned("Settings"); + streamWriter.SetKey("useWorldEngine", scene->m_sceneSettings.useWorldEngine); + streamWriter.EndMap(); + + if (scene->m_sceneSettings.useWorldEngine) + { + SerializeWorldEngine(scene, streamWriter); + } + + streamWriter.EndMap(); + streamWriter.EndMap(); + + BinaryStreamWriter sceneFileWriter{}; + const size_t compressedDataOffset = AssetSerializer::WriteMetadata(metadata, CURRENT_ASSET_VERSION, sceneFileWriter); + + auto buffer = streamWriter.WriteAndGetBuffer(); + sceneFileWriter.Write(buffer); + buffer.Release(); + + sceneFileWriter.WriteToDisk(scenePath, true, compressedDataOffset); // #TODO_Ivar: Fix compressed offset + } + } + + bool SceneSerializer::Deserialize(const AssetMetadata& metadata, Ref destinationAsset) const + { + return false; + } + + void SceneSerializer::SerializeEntity(entt::entity id, const AssetMetadata& metadata, const Ref& scene, YAMLMemoryStreamWriter& streamWriter) const + { + streamWriter.BeginMap(); + streamWriter.BeginMapNamned("Entity"); + + auto& registry = scene->GetRegistry(); + + Entity entity{ id, scene }; + + streamWriter.SetKey("id", entity.GetID()); + streamWriter.SetKey("cellId", scene->m_worldEngine.GetCellIDFromEntity(entity)); + streamWriter.BeginSequence("components"); + { + for (auto&& curr : registry.storage()) + { + auto& storage = curr.second; + + if (!storage.contains(id)) + { + continue; + } + + const IComponentTypeDesc* componentDesc = reinterpret_cast(ComponentRegistry::GetTypeDescFromName(storage.type().name())); + if (!componentDesc) + { + continue; + } + + const uint8_t* componentPtr = reinterpret_cast(storage.get(id)); + SerializeClass(componentPtr, 0, componentDesc, streamWriter, false); + } + } + streamWriter.EndSequence(); + + if (registry.any_of(id)) + { + SerializeMono(id, scene, streamWriter); + } + + if (registry.any_of(id)) + { + std::filesystem::path vpPath = (ProjectManager::GetDirectory() / metadata.filePath.parent_path() / "Layers" / ("ent_" + std::to_string((uint32_t)id) + ".entVp")); + auto& vpComp = registry.get(id); + + // #TODO_Ivar: This is kind of questionable after TGA + if (std::filesystem::exists(vpPath)) + { + using std::filesystem::perms; + std::filesystem::permissions(vpPath, perms::_All_write); + } + + BinarySerializer binaryVp(vpPath, sizeof(uint32_t) * vpComp.vertexColors.size() + sizeof(vpComp.meshHandle)); + + binaryVp.Serialize(vpComp.vertexColors.data(), sizeof(uint32_t) * vpComp.vertexColors.size()); + binaryVp.Serialize(vpComp.meshHandle); + binaryVp.WriteToFile(); + } + + streamWriter.EndMap(); + streamWriter.EndMap(); + } + + void SceneSerializer::SerializeWorldEngine(const Ref& scene, YAMLMemoryStreamWriter& streamWriter) const + { + auto& worldEngine = scene->m_worldEngine; + + streamWriter.BeginMapNamned("WorldEngine"); + streamWriter.SetKey("cellSize", worldEngine.GetSettings().cellSize); + streamWriter.SetKey("worldSize", worldEngine.GetSettings().worldSize); + + streamWriter.EndMap(); + } + + void SceneSerializer::SerializeEntities(const AssetMetadata& metadata, const Ref& scene, const std::filesystem::path& sceneDirectory) const + { + std::filesystem::path entitiesDirectoryPath = sceneDirectory / "Entities"; + if (!std::filesystem::exists(entitiesDirectoryPath)) + { + std::filesystem::create_directories(entitiesDirectoryPath); + } + + const auto entities = scene->GetAllEditedEntities(); + if (!entities.empty()) + { + Algo::ForEachParallel([entitiesDirectoryPath, entities, metadata, scene, this](uint32_t threadIdx, uint32_t i) + { + Entity entity = entities.at(i); + const auto entityPath = entitiesDirectoryPath / (entity.ToString() + ".vtasset"); + + YAMLMemoryStreamWriter streamWriter{}; + SerializeEntity(entity, metadata, scene, streamWriter); + + auto buffer = streamWriter.WriteAndGetBuffer(); + + BinaryStreamWriter binaryStreamWriter{}; + binaryStreamWriter.Write(ENTITY_MAGIC_VAL); + binaryStreamWriter.Write(buffer); + + buffer.Release(); + + binaryStreamWriter.WriteToDisk(entityPath, true, 0); + }, + static_cast(entities.size())); + } + + const auto removedEntities = scene->GetAllRemovedEntities(); + if (!removedEntities.empty()) + { + Algo::ForEachParallel([removedEntities, entitiesDirectoryPath](uint32_t threadIdx, uint32_t i) + { + EntityID id = removedEntities.at(i); + + const std::filesystem::path entityFilePath = entitiesDirectoryPath / (std::to_string(id) + ".entity"); + if (std::filesystem::exists(entityFilePath)) + { + FileSystem::MoveToRecycleBin(entityFilePath); + } + + }, static_cast(removedEntities.size())); + } + + VT_CORE_INFO("[SceneImporter]: Saved {0} entities!", entities.size()); + VT_CORE_INFO("[SceneImporter]: Removed {0} entities!", removedEntities.size()); + + scene->ClearEditedEntities(); + } + + void SceneSerializer::SerializeClass(const uint8_t* data, const size_t offset, const IComponentTypeDesc* compDesc, YAMLMemoryStreamWriter& streamWriter, bool isSubComponent) const + { + if (!isSubComponent) + { + streamWriter.BeginMap(); + } + + streamWriter.SetKey("guid", compDesc->GetGUID()); + streamWriter.BeginSequence("members"); + + for (const auto& member : compDesc->GetMembers()) + { + if ((member.flags & ComponentMemberFlag::NoSerialize) != ComponentMemberFlag::None) + { + continue; + } + + streamWriter.BeginMap(); + streamWriter.SetKey("name", member.name); + + if (member.typeDesc != nullptr) + { + switch (member.typeDesc->GetValueType()) + { + case ValueType::Component: + streamWriter.SetKey("data", "component"); + SerializeClass(data, offset + member.offset, reinterpret_cast(member.typeDesc), streamWriter, true); + break; + + case ValueType::Enum: + streamWriter.SetKey("data", "enum"); + streamWriter.SetKey("enumValue", *reinterpret_cast(&data[offset + member.offset])); + break; + + case ValueType::Array: + { + streamWriter.SetKey("data", "array"); + SerializeArray(data, offset + member.offset, reinterpret_cast(member.typeDesc), streamWriter); + break; + } + } + } + else + { + if (s_typeSerializers.contains(member.typeIndex)) + { + s_typeSerializers.at(member.typeIndex)(streamWriter, data, offset + member.offset); + } + } + + streamWriter.EndMap(); + } + + streamWriter.EndSequence(); + + if (!isSubComponent) + { + streamWriter.EndMap(); + } + } + + void SceneSerializer::SerializeArray(const uint8_t* data, const size_t offset, const IArrayTypeDesc* arrayDesc, YAMLMemoryStreamWriter& streamWriter) const + { + const void* arrayPtr = &data[offset]; + + const bool isNonDefaultType = arrayDesc->GetElementTypeDesc() != nullptr; + const auto& typeIndex = arrayDesc->GetElementTypeIndex(); + + if (!isNonDefaultType && !s_typeSerializers.contains(typeIndex)) + { + return; + } + + streamWriter.BeginSequence("values"); + for (size_t i = 0; i < arrayDesc->Size(arrayPtr); i++) + { + const uint8_t* elementData = reinterpret_cast(arrayDesc->At(arrayPtr, i)); + + streamWriter.BeginMap(); + if (isNonDefaultType) + { + switch (arrayDesc->GetElementTypeDesc()->GetValueType()) + { + case ValueType::Component: + streamWriter.SetKey("value", "component"); + SerializeClass(elementData, 0, reinterpret_cast(arrayDesc->GetElementTypeDesc()), streamWriter, true); + break; + + case ValueType::Enum: + streamWriter.SetKey("value", *reinterpret_cast(elementData)); + break; + + case ValueType::Array: + streamWriter.SetKey("value", "array"); + SerializeArray(elementData, 0, reinterpret_cast(arrayDesc->GetElementTypeDesc()), streamWriter); + break; + } + } + else + { + if (s_typeSerializers.contains(typeIndex)) + { + s_typeSerializers.at(typeIndex)(streamWriter, elementData, 0); + } + } + streamWriter.EndMap(); + } + streamWriter.EndSequence(); + } + + void SceneSerializer::SerializeMono(entt::entity id, const Ref& scene, YAMLMemoryStreamWriter& streamWriter) const + { + const auto& scriptFieldCache = scene->GetScriptFieldCache(); + + streamWriter.BeginSequence("MonoScripts"); + { + MonoScriptComponent& monoScriptComp = scene->GetRegistry().get(id); + if (monoScriptComp.scriptIds.size() == monoScriptComp.scriptNames.size()) + { + for (size_t i = 0; i < monoScriptComp.scriptIds.size(); ++i) + { + const auto& scriptId = monoScriptComp.scriptIds.at(i); + const auto& scriptName = monoScriptComp.scriptNames.at(i); + + streamWriter.BeginMap(); + streamWriter.BeginMapNamned("ScriptEntry"); + + streamWriter.SetKey("name", scriptName); + streamWriter.SetKey("id", scriptId); + + if (scriptFieldCache.GetCache().contains(scriptId)) + { + streamWriter.BeginSequence("members"); + const auto& fieldMap = scriptFieldCache.GetCache().at(scriptId); + for (const auto& [name, value] : fieldMap) + { + streamWriter.BeginMap(); + streamWriter.SetKey("name", name); + + if (value->field.type.IsString()) + { + auto cStr = value->data.As(); + std::string str(cStr); + + streamWriter.SetKey("data", str); + } + else + { + if (s_typeSerializers.contains(value->field.type.typeIndex)) + { + s_typeSerializers.at(value->field.type.typeIndex)(streamWriter, value->data.As(), 0); + } + } + + streamWriter.EndMap(); + } + + streamWriter.EndSequence(); + } + + streamWriter.EndMap(); + streamWriter.EndMap(); + } + } + } + streamWriter.EndSequence(); + } +} diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/SceneSerializer.h b/Volt/Volt/src/Volt/Asset/ImportersNew/SceneSerializer.h new file mode 100644 index 000000000..63327d0b0 --- /dev/null +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/SceneSerializer.h @@ -0,0 +1,54 @@ +#pragma once + +#include "Volt/Asset/ImportersNew/AssetSerializer.h" + +#include "Volt/Scene/Entity.h" + +#include + +namespace Volt +{ + class YAMLMemoryStreamWriter; + class YAMLStreamReader; + + class Scene; + class IArrayTypeDesc; + class MonoScriptFieldCache; + class IComponentTypeDesc; + + class SceneSerializer : public AssetSerializer + { + public: + SceneSerializer(); + ~SceneSerializer() override; + + void Serialize(const AssetMetadata& metadata, const Ref& asset) const override; + bool Deserialize(const AssetMetadata& metadata, Ref destinationAsset) const override; + + void SerializeEntity(entt::entity id, const AssetMetadata& metadata, const Ref& scene, YAMLMemoryStreamWriter& streamWriter) const; + void DeserializeEntity(const Ref& scene, const AssetMetadata& metadata, YAMLStreamReader& streamReader) const; + void DeserializeMono(entt::entity id, const Ref& scene, YAMLStreamReader& streamReader) const; + + private: + inline static SceneSerializer* s_instance = nullptr; + + void SerializeWorldEngine(const Ref& scene, YAMLMemoryStreamWriter& streamWriter) const; + void DeserializeWorldEngine(const Ref& scene, YAMLStreamReader& streamReader) const; + + void SerializeEntities(const AssetMetadata& metadata, const Ref& scene, const std::filesystem::path& sceneDirectory) const; + + void LoadCellEntities(const AssetMetadata& metadata, const Ref& scene, const std::filesystem::path& sceneDirectory) const; + + Entity CreateEntityFromUUIDThreadSafe(EntityID entityId, const Ref& scene) const; + + void SerializeClass(const uint8_t* data, const size_t offset, const IComponentTypeDesc* compDesc, YAMLMemoryStreamWriter& streamWriter, bool isSubComponent) const; + void SerializeArray(const uint8_t* data, const size_t offset, const IArrayTypeDesc* arrayDesc, YAMLMemoryStreamWriter& streamWriter) const; + void SerializeMono(entt::entity id, const Ref& scene, YAMLMemoryStreamWriter& streamWriter) const; + + void DeserializeClass(uint8_t* data, const size_t offset, const IComponentTypeDesc* compDesc, YAMLStreamReader& streamReader) const; + void DeserializeArray(uint8_t* data, const size_t offset, const IArrayTypeDesc* arrayDesc, YAMLStreamReader& streamReader) const; + + inline static std::unordered_map> s_typeSerializers; + inline static std::unordered_map> s_typeDeserializers; + }; +} diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshImporter.cpp b/Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshSerializer.cpp similarity index 82% rename from Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshImporter.cpp rename to Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshSerializer.cpp index 6ec21f684..cbf36e8bc 100644 --- a/Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshImporter.cpp +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshSerializer.cpp @@ -1,12 +1,12 @@ #include "vtpch.h" -#include "SourceMeshImporter.h" +#include "SourceMeshSerializer.h" #include "Volt/Asset/AssetManager.h" #include "Volt/Asset/Importers/MeshTypeImporter.h" namespace Volt { - bool SourceMeshImporter::Deserialize(const AssetMetadata& metadata, Ref destinationAsset) const + bool SourceMeshSerializer::Deserialize(const AssetMetadata& metadata, Ref destinationAsset) const { const auto filePath = AssetManager::GetFilesystemPath(metadata.filePath); diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshImporter.h b/Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshSerializer.h similarity index 85% rename from Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshImporter.h rename to Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshSerializer.h index abb9a9b5f..45448eedc 100644 --- a/Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshImporter.h +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/SourceMeshSerializer.h @@ -4,7 +4,7 @@ namespace Volt { - class SourceMeshImporter : public AssetSerializer + class SourceMeshSerializer : public AssetSerializer { public: void Serialize(const AssetMetadata& metadata, const Ref& asset) const override {} // Type is not serializable diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/SourceTextureSerializer.cpp b/Volt/Volt/src/Volt/Asset/ImportersNew/SourceTextureSerializer.cpp new file mode 100644 index 000000000..879197cda --- /dev/null +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/SourceTextureSerializer.cpp @@ -0,0 +1,29 @@ +#include "vtpch.h" +#include "SourceTextureSerializer.h" + +#include "Volt/Asset/AssetManager.h" +#include "Volt/Asset/Importers/TextureImporter.h" + +namespace Volt +{ + bool SourceTextureSerializer::Deserialize(const AssetMetadata& metadata, Ref destinationAsset) const + { + const auto filePath = AssetManager::GetFilesystemPath(metadata.filePath); + + if (!std::filesystem::exists(filePath)) + { + VT_CORE_ERROR("File {0} not found!", metadata.filePath); + destinationAsset->SetFlag(AssetFlag::Missing, true); + return false; + } + + Ref destinationTexture = std::reinterpret_pointer_cast(destinationAsset); + if (!TextureImporter::ImportTexture(filePath, *destinationTexture)) + { + destinationAsset->SetFlag(AssetFlag::Invalid, true); + return false; + } + + return true; + } +} diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/SourceTextureSerializer.h b/Volt/Volt/src/Volt/Asset/ImportersNew/SourceTextureSerializer.h new file mode 100644 index 000000000..05ca8a4a9 --- /dev/null +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/SourceTextureSerializer.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Volt/Asset/ImportersNew/AssetSerializer.h" + +namespace Volt +{ + class SourceTextureSerializer : public AssetSerializer + { + public: + void Serialize(const AssetMetadata& metadata, const Ref& asset) const override {} // Type is not serializable + bool Deserialize(const AssetMetadata& metadata, Ref destinationAsset) const override; + }; +} diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/TextureSerializer.cpp b/Volt/Volt/src/Volt/Asset/ImportersNew/TextureSerializer.cpp new file mode 100644 index 000000000..0db349a4f --- /dev/null +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/TextureSerializer.cpp @@ -0,0 +1,107 @@ +#include "vtpch.h" +#include "TextureSerializer.h" + +#include "Volt/Rendering/Texture/Texture2D.h" +#include "Volt/Rendering/Texture/Image2D.h" + +#include "Volt/Utility/ImageUtility.h" + +namespace Volt +{ + namespace Utility + { + inline static bool IsEncodedFormat(ImageFormat format) + { + switch (format) + { + case ImageFormat::BC1: + case ImageFormat::BC1SRGB: + case ImageFormat::BC2: + case ImageFormat::BC2SRGB: + case ImageFormat::BC3: + case ImageFormat::BC3SRGB: + case ImageFormat::BC4: + case ImageFormat::BC5: + case ImageFormat::BC7: + case ImageFormat::BC7SRGB: + case ImageFormat::BC6H_SF16: + case ImageFormat::BC6H_UF16: + return true; + } + return false; + } + } + + struct TextureMip + { + uint32_t width; + uint32_t height; + size_t dataSize; + }; + + struct TextureHeader + { + ImageFormat encoding; // Should be one of the BC formats + std::vector mips; + }; + + void TextureSerializer::Serialize(const AssetMetadata& metadata, const Ref& asset) const + { + Ref texture = std::reinterpret_pointer_cast(asset); + Ref image = texture->GetImage(); + + std::vector data; + + if (!Utility::IsEncodedFormat(texture->GetImage()->GetFormat())) + { + // do encoding + } + else + { + VkBuffer hostBuffer{}; + VmaAllocation hostAllocation{}; + + VulkanAllocator allocator{ "Texture - Serialize" }; + + // Create host buffer + { + VkBufferCreateInfo info{}; + info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + info.size = texture->GetImage()->GetAllocationSize(); + info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + hostAllocation = allocator.AllocateBuffer(info, VMA_MEMORY_USAGE_GPU_TO_CPU, hostBuffer); + } + + Utility::TransitionImageLayout(image->GetHandle(), image->GetLayout(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + size_t bufferOffset = 0; + + Utility::CopyImageToBuffer(hostBuffer, bufferOffset, image->GetHandle(), image->GetWidth(), image->GetHeight(), 0); + Utility::TransitionImageLayout(image->GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image->GetLayout()); + + auto* imageData = allocator.MapMemory(hostAllocation); + data.resize(image->GetAllocationSize()); + + memcpy_s(data.data(), data.size(), imageData, image->GetAllocationSize()); + allocator.UnmapMemory(hostAllocation); + + allocator.DestroyBuffer(hostBuffer, hostAllocation); + } + + TextureHeader header{}; + header.encoding = image->GetFormat(); + + { + auto& firstMip = header.mips.emplace_back(); + firstMip.width = image->GetWidth(); + firstMip.height = image->GetHeight(); + } + } + + bool TextureSerializer::Deserialize(const AssetMetadata& metadata, Ref destinationAsset) const + { + return false; + } +} diff --git a/Volt/Volt/src/Volt/Asset/ImportersNew/TextureSerializer.h b/Volt/Volt/src/Volt/Asset/ImportersNew/TextureSerializer.h new file mode 100644 index 000000000..756cea92f --- /dev/null +++ b/Volt/Volt/src/Volt/Asset/ImportersNew/TextureSerializer.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Volt/Asset/ImportersNew/AssetSerializer.h" + +namespace Volt +{ + class TextureSerializer : public AssetSerializer + { + public: + void Serialize(const AssetMetadata& metadata, const Ref& asset) const override; + bool Deserialize(const AssetMetadata& metadata, Ref destinationAsset) const override; + }; +} diff --git a/Volt/Volt/src/Volt/Asset/Serialization/AssetSerializationCommon.h b/Volt/Volt/src/Volt/Asset/Serialization/AssetSerializationCommon.h index 3a02fb84d..d87830f4b 100644 --- a/Volt/Volt/src/Volt/Asset/Serialization/AssetSerializationCommon.h +++ b/Volt/Volt/src/Volt/Asset/Serialization/AssetSerializationCommon.h @@ -16,9 +16,4 @@ namespace Volt static void Serialize(BinaryStreamWriter& streamWriter, const SerializedAssetMetadata& data); static void Deserialize(BinaryStreamReader& streamReader, SerializedAssetMetadata& outData); }; - - struct SerializedAssetMetadataHeader - { - size_t assetMetadataSize; - }; } diff --git a/Volt/Volt/src/Volt/Core/Buffer.h b/Volt/Volt/src/Volt/Core/Buffer.h index 5bfedb7fd..52a5a6cda 100644 --- a/Volt/Volt/src/Volt/Core/Buffer.h +++ b/Volt/Volt/src/Volt/Core/Buffer.h @@ -1,5 +1,6 @@ #pragma once +#include "Volt/Log/Log.h" #include "Volt/Core/Base.h" #include diff --git a/Volt/Volt/src/Volt/Core/Graphics/VulkanAllocator.cpp b/Volt/Volt/src/Volt/Core/Graphics/VulkanAllocator.cpp index 6a0e50d77..4e0999937 100644 --- a/Volt/Volt/src/Volt/Core/Graphics/VulkanAllocator.cpp +++ b/Volt/Volt/src/Volt/Core/Graphics/VulkanAllocator.cpp @@ -170,6 +170,13 @@ namespace Volt return allocation; } + const size_t VulkanAllocator::GetAllocationSize(VmaAllocation allocation) + { + VmaAllocationInfo allocInfo{}; + vmaGetAllocationInfo(s_allocatorData->allocator, allocation, &allocInfo); + return allocInfo.size; + } + void VulkanAllocator::Free(VmaAllocation allocation) { VT_CORE_ASSERT(allocation, "Unable to free null allocation!"); diff --git a/Volt/Volt/src/Volt/Core/Graphics/VulkanAllocator.h b/Volt/Volt/src/Volt/Core/Graphics/VulkanAllocator.h index 9fa84ae4b..acd9009ea 100644 --- a/Volt/Volt/src/Volt/Core/Graphics/VulkanAllocator.h +++ b/Volt/Volt/src/Volt/Core/Graphics/VulkanAllocator.h @@ -21,6 +21,8 @@ namespace Volt VmaAllocation AllocateImageInPool(VkImageCreateInfo bufferCreateInfo, VmaMemoryUsage memoryUsage, VkImage& outImage, VmaPool pool, std::string_view name = ""); + const size_t GetAllocationSize(VmaAllocation allocation); + void Free(VmaAllocation allocation); void DestroyBuffer(VkBuffer buffer, VmaAllocation allocation); void DestroyImage(VkImage image, VmaAllocation allocation); diff --git a/Volt/Volt/src/Volt/Project/ProjectManager.cpp b/Volt/Volt/src/Volt/Project/ProjectManager.cpp index 25867d8fa..db44dafb3 100644 --- a/Volt/Volt/src/Volt/Project/ProjectManager.cpp +++ b/Volt/Volt/src/Volt/Project/ProjectManager.cpp @@ -8,7 +8,7 @@ #include "Volt/Utility/SerializationMacros.h" #include "Volt/Utility/FileIO/YAMLStreamReader.h" -#include "Volt/Utility/FileIO/YAMLStreamWriter.h" +#include "Volt/Utility/FileIO/YAMLFileStreamWriter.h" namespace Volt { @@ -44,7 +44,7 @@ namespace Volt void ProjectManager::SerializeProject() { - YAMLStreamWriter streamWriter{ m_currentProject->projectFilePath }; + YAMLFileStreamWriter streamWriter{ m_currentProject->projectFilePath }; streamWriter.BeginMap(); streamWriter.BeginMapNamned("Project"); diff --git a/Volt/Volt/src/Volt/Rendering/Texture/Image2D.cpp b/Volt/Volt/src/Volt/Rendering/Texture/Image2D.cpp index 8fdd8112c..9e7905911 100644 --- a/Volt/Volt/src/Volt/Rendering/Texture/Image2D.cpp +++ b/Volt/Volt/src/Volt/Rendering/Texture/Image2D.cpp @@ -559,6 +559,12 @@ namespace Volt GraphicsContext::GetDevice()->FlushCommandBuffer(commandBuffer); } + const size_t Image2D::GetAllocationSize() const + { + VulkanAllocator allocator{}; + return allocator.GetAllocationSize(myAllocation); + } + Ref Image2D::Create(const ImageSpecification& specification, const void* data) { return CreateRef(specification, data); diff --git a/Volt/Volt/src/Volt/Rendering/Texture/Image2D.h b/Volt/Volt/src/Volt/Rendering/Texture/Image2D.h index 0d5f6d721..2b0acffbb 100644 --- a/Volt/Volt/src/Volt/Rendering/Texture/Image2D.h +++ b/Volt/Volt/src/Volt/Rendering/Texture/Image2D.h @@ -59,6 +59,8 @@ namespace Volt void Unmap(); + const size_t GetAllocationSize() const; + static Ref Create(const ImageSpecification& specification, const void* data = nullptr); static Ref Create(const ImageSpecification& specification, bool transitionTolayout); diff --git a/Volt/Volt/src/Volt/Rendering/Texture/ImageCommon.h b/Volt/Volt/src/Volt/Rendering/Texture/ImageCommon.h index 2a032f2ac..3279c50c7 100644 --- a/Volt/Volt/src/Volt/Rendering/Texture/ImageCommon.h +++ b/Volt/Volt/src/Volt/Rendering/Texture/ImageCommon.h @@ -42,6 +42,7 @@ namespace Volt BC7SRGB, BC6H_SF16, + BC6H_UF16, DEPTH32F, DEPTH16U, diff --git a/Volt/Volt/src/Volt/Scene/Scene.h b/Volt/Volt/src/Volt/Scene/Scene.h index eaa68f04e..6fedc3193 100644 --- a/Volt/Volt/src/Volt/Scene/Scene.h +++ b/Volt/Volt/src/Volt/Scene/Scene.h @@ -177,6 +177,7 @@ namespace Volt private: friend class Entity; friend class SceneImporter; + friend class SceneSerializer; void MoveToLayerRecursive(Entity entity, uint32_t targetLayer); diff --git a/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamReader.cpp b/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamReader.cpp index c96d0604d..b04f81cc3 100644 --- a/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamReader.cpp +++ b/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamReader.cpp @@ -35,6 +35,11 @@ namespace Volt m_streamValid = false; } } + else + { + // Decompress automatically removes compression encoding header + m_currentOffset += compressionEncodingHeaderSize; + } } void BinaryStreamReader::ReadData(void* outData, const TypeHeader& serializedTypeHeader, const TypeHeader& constructedTypeHeader) diff --git a/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamReader.h b/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamReader.h index 582fe3829..8ebb6a852 100644 --- a/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamReader.h +++ b/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamReader.h @@ -1,5 +1,6 @@ #pragma once +#include "Volt/Core/Buffer.h" #include "Volt/Utility/FileIO/StreamCommon.h" #include @@ -24,6 +25,9 @@ namespace Volt template<> void Read(std::string& data); + template<> + void Read(Buffer& data); + template void Read(std::vector& data); @@ -53,19 +57,21 @@ namespace Volt template inline void BinaryStreamReader::Read(T& outData) { + constexpr size_t typeSize = sizeof(T); + + TypeHeader typeHeader{}; + typeHeader.baseTypeSize = static_cast(typeSize); + typeHeader.totalTypeSize = static_cast(typeSize); + + TypeHeader serializedTypeHeader = ReadTypeHeader(); + if constexpr (std::is_trivial()) { - constexpr size_t typeSize = sizeof(T); - - TypeHeader typeHeader{}; - typeHeader.baseTypeSize = static_cast(typeSize); - typeHeader.totalTypeSize = static_cast(typeSize); - - TypeHeader serializedTypeHeader = ReadTypeHeader(); ReadData(&outData, serializedTypeHeader, typeHeader); } else { + VT_CORE_ASSERT(serializedTypeHeader.baseTypeSize == typeHeader.baseTypeSize, "Base Type sizes must match!"); T::Deserialize(*this, outData); } } @@ -81,6 +87,17 @@ namespace Volt ReadData(data.data(), serializedTypeHeader, typeHeader); } + template<> + inline void BinaryStreamReader::Read(Buffer& data) + { + TypeHeader typeHeader{}; + typeHeader.baseTypeSize = sizeof(Buffer); + TypeHeader serializedTypeHeader = ReadTypeHeader(); + + data.Resize(serializedTypeHeader.totalTypeSize); + ReadData(data.As(), serializedTypeHeader, typeHeader); + } + template inline void BinaryStreamReader::Read(std::vector& data) { @@ -88,16 +105,21 @@ namespace Volt typeHeader.baseTypeSize = sizeof(std::vector); TypeHeader serializedTypeHeader = ReadTypeHeader(); - data.resize(serializedTypeHeader.totalTypeSize / sizeof(F)); + data.resize(serializedTypeHeader.totalTypeSize); if constexpr (std::is_trivial()) { + // We must multiply type size to get correct byte size + serializedTypeHeader.totalTypeSize *= sizeof(F); ReadData(data.data(), serializedTypeHeader, typeHeader); } else { for (size_t i = 0; i < data.size(); i++) { + TypeHeader serializedObjectTypeHeader = ReadTypeHeader(); + VT_CORE_ASSERT(serializedObjectTypeHeader.baseTypeSize == sizeof(F), "Type sizes must match!"); + F::Deserialize(*this, data[i]); } } @@ -110,7 +132,8 @@ namespace Volt typeHeader.baseTypeSize = sizeof(std::vector); TypeHeader serializedTypeHeader = ReadTypeHeader(); - data.resize(serializedTypeHeader.totalTypeSize / sizeof(F)); + data.resize(serializedTypeHeader.totalTypeSize); + serializedTypeHeader.totalTypeSize *= sizeof(F); ReadData(data.data(), serializedTypeHeader, typeHeader); } @@ -123,12 +146,17 @@ namespace Volt if constexpr (std::is_trivial()) { + // We must multiply type size to get correct byte size + serializedTypeHeader.totalTypeSize *= sizeof(F); ReadData(data.data(), serializedTypeHeader, typeHeader); } else { for (size_t i = 0; i < data.size(); i++) { + TypeHeader serializedObjectTypeHeader = ReadTypeHeader(); + VT_CORE_ASSERT(serializedObjectTypeHeader.baseTypeSize == sizeof(F), "Type sizes must match!"); + F::Deserialize(*this, data[i]); } } @@ -141,7 +169,7 @@ namespace Volt typeHeader.baseTypeSize = sizeof(std::map); TypeHeader serializedTypeHeader = ReadTypeHeader(); - const size_t elementCount = serializedTypeHeader.totalTypeSize / (sizeof(Key) + sizeof(Value)); + const size_t elementCount = serializedTypeHeader.totalTypeSize; for (size_t i = 0; i < elementCount; i++) { @@ -186,7 +214,7 @@ namespace Volt typeHeader.baseTypeSize = sizeof(std::unordered_map); TypeHeader serializedTypeHeader = ReadTypeHeader(); - const size_t elementCount = serializedTypeHeader.totalTypeSize / (sizeof(Key) + sizeof(Value)); + const size_t elementCount = serializedTypeHeader.totalTypeSize; for (size_t i = 0; i < elementCount; i++) { diff --git a/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamWriter.cpp b/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamWriter.cpp index 8f63c7aa1..14e7e1160 100644 --- a/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamWriter.cpp +++ b/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamWriter.cpp @@ -42,6 +42,7 @@ namespace Volt emptyEncodingHeader.fill(0); m_data.insert(m_data.begin(), emptyEncodingHeader.begin(), emptyEncodingHeader.end()); + size = m_data.size(); } stream.write(reinterpret_cast(writePtr), size); @@ -100,24 +101,19 @@ namespace Volt return true; } - void BinaryStreamWriter::WriteData(const void* data, const size_t size, const TypeHeader& typeHeader) + void BinaryStreamWriter::WriteTypeHeader(const TypeHeader& typeHeader) { constexpr size_t typeHeaderSize = sizeof(TypeHeader); - const size_t writeSize = size + typeHeaderSize; - size_t currentOffset = m_data.size(); - m_data.resize(currentOffset + writeSize); - - memcpy_s(&m_data[currentOffset], writeSize, &typeHeader, typeHeaderSize); - currentOffset += typeHeaderSize; - - memcpy_s(&m_data[currentOffset], writeSize - typeHeaderSize, data, size); + const size_t offset = m_data.size(); + m_data.resize(m_data.size() + typeHeaderSize); + memcpy_s(&m_data[offset], typeHeaderSize, &typeHeader, typeHeaderSize); } void BinaryStreamWriter::WriteData(const void* data, const size_t size) { const size_t writeSize = size; - size_t currentOffset = m_data.size(); + const size_t currentOffset = m_data.size(); m_data.resize(currentOffset + writeSize); memcpy_s(&m_data[currentOffset], writeSize, data, size); diff --git a/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamWriter.h b/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamWriter.h index 20a2af32e..cceb3514d 100644 --- a/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamWriter.h +++ b/Volt/Volt/src/Volt/Utility/FileIO/BinaryStreamWriter.h @@ -1,5 +1,6 @@ #pragma once +#include "Volt/Core/Buffer.h" #include "Volt/Utility/FileIO/StreamCommon.h" #include @@ -26,30 +27,33 @@ namespace Volt template [[nodiscard]] const size_t GetBinarySizeOfType(const std::unordered_map& object) const; template - void Write(const T& data); + size_t Write(const T& data); template<> - void Write(const std::string& data); + size_t Write(const std::string& data); + + template<> + size_t Write(const Buffer& buffer); template - void Write(const std::vector& data); + size_t Write(const std::vector& data); template - void WriteRaw(const std::vector& data); + size_t WriteRaw(const std::vector& data); template - void Write(const std::array& data); + size_t Write(const std::array& data); template - void Write(const std::map& data); + size_t Write(const std::map& data); template - void Write(const std::unordered_map& data); + size_t Write(const std::unordered_map& data); private: bool GetCompressed(std::vector& result, size_t compressedDataOffset = 0); - void WriteData(const void* data, const size_t size, const TypeHeader& typeHeader); + void WriteTypeHeader(const TypeHeader& typeHeader); void WriteData(const void* data, const size_t size); std::vector m_data; @@ -107,40 +111,62 @@ namespace Volt } template - inline void BinaryStreamWriter::Write(const T& data) + inline size_t BinaryStreamWriter::Write(const T& data) { constexpr size_t typeSize = sizeof(T); + TypeHeader header{}; + header.baseTypeSize = typeSize; + header.totalTypeSize = typeSize; + + WriteTypeHeader(header); + if constexpr (std::is_trivial()) { - TypeHeader header{}; - header.baseTypeSize = typeSize; - header.totalTypeSize = typeSize; - - WriteData(&data, typeSize, header); + WriteData(&data, typeSize); } else { T::Serialize(*this, data); } + + return m_data.size(); } template<> - inline void BinaryStreamWriter::Write(const std::string& data) + inline size_t BinaryStreamWriter::Write(const std::string& data) { TypeHeader header{}; header.baseTypeSize = sizeof(std::string); header.totalTypeSize = static_cast(data.size()); - WriteData(data.data(), data.size(), header); + WriteTypeHeader(header); + WriteData(data.data(), data.size()); + + return m_data.size(); + } + + template<> + inline size_t BinaryStreamWriter::Write(const Buffer& buffer) + { + TypeHeader header{}; + header.baseTypeSize = sizeof(Buffer); + header.totalTypeSize = static_cast(buffer.GetSize()); + + WriteTypeHeader(header); + WriteData(buffer.As(), buffer.GetSize()); + + return m_data.size(); } template - inline void BinaryStreamWriter::Write(const std::vector& data) + inline size_t BinaryStreamWriter::Write(const std::vector& data) { TypeHeader header{}; header.baseTypeSize = sizeof(std::vector); - header.totalTypeSize = static_cast(data.size() * sizeof(F)); + header.totalTypeSize = static_cast(data.size()); + + WriteTypeHeader(header); if constexpr (std::is_trivial_v) { @@ -148,55 +174,70 @@ namespace Volt } else { - WriteData(&header, sizeof(header)); - for (const auto& obj : data) { + TypeHeader objectHeader{}; + objectHeader.baseTypeSize = sizeof(F); + objectHeader.totalTypeSize = sizeof(F); + + WriteTypeHeader(objectHeader); F::Serialize(*this, obj); } } + + return m_data.size(); } template - inline void BinaryStreamWriter::WriteRaw(const std::vector& data) + inline size_t BinaryStreamWriter::WriteRaw(const std::vector& data) { TypeHeader header{}; header.baseTypeSize = sizeof(std::vector); - header.totalTypeSize = static_cast(data.size() * sizeof(F)); + header.totalTypeSize = static_cast(data.size()); + + WriteTypeHeader(header); + WriteData(data.data(), data.size() * sizeof(F)); - WriteData(data.data(), data.size() * sizeof(F), header); + return m_data.size(); } template - inline void BinaryStreamWriter::Write(const std::array& data) + inline size_t BinaryStreamWriter::Write(const std::array& data) { TypeHeader header{}; header.baseTypeSize = sizeof(std::array); - header.totalTypeSize = COUNT * sizeof(F); + header.totalTypeSize = COUNT; + + WriteTypeHeader(header); if constexpr (std::is_trivial_v) { - WriteData(data.data(), COUNT * sizeof(F), header); + WriteData(data.data(), COUNT * sizeof(F)); } else { - WriteData(&header, sizeof(header)); - for (const auto& obj : data) { + TypeHeader objectHeader{}; + objectHeader.baseTypeSize = sizeof(F); + objectHeader.totalTypeSize = sizeof(F); + + WriteTypeHeader(objectHeader); F::Serialize(*this, obj); } } + + return m_data.size(); } template - inline void BinaryStreamWriter::Write(const std::map& data) + inline size_t BinaryStreamWriter::Write(const std::map& data) { TypeHeader header{}; header.baseTypeSize = sizeof(std::map& data); - header.totalTypeSize = data.size() * sizeof(Key) + data.size() * sizeof(Value); + header.totalTypeSize = data.size(); - WriteData(&header, sizeof(header)); + WriteTypeHeader(header); for (const auto& [key, value] : data) { @@ -218,14 +259,16 @@ namespace Volt Value::Serialize(*this, value); } } + + return m_data.size(); } template - inline void BinaryStreamWriter::Write(const std::unordered_map& data) + inline size_t BinaryStreamWriter::Write(const std::unordered_map& data) { TypeHeader header{}; header.baseTypeSize = sizeof(std::unordered_map&data); - header.totalTypeSize = data.size() * sizeof(Key) + data.size() * sizeof(Value); + header.totalTypeSize = data.size(); WriteData(&header, sizeof(header)); @@ -249,5 +292,7 @@ namespace Volt Value::Serialize(*this, value); } } + + return m_data.size(); } } diff --git a/Volt/Volt/src/Volt/Utility/FileIO/YAMLFileStreamWriter.cpp b/Volt/Volt/src/Volt/Utility/FileIO/YAMLFileStreamWriter.cpp new file mode 100644 index 000000000..cdf506ac5 --- /dev/null +++ b/Volt/Volt/src/Volt/Utility/FileIO/YAMLFileStreamWriter.cpp @@ -0,0 +1,23 @@ +#include "vtpch.h" +#include "YAMLFileStreamWriter.h" + +namespace Volt +{ + YAMLFileStreamWriter::YAMLFileStreamWriter(const std::filesystem::path& targetFilePath) + : m_targetFilePath(targetFilePath) + { + } + + const bool YAMLFileStreamWriter::WriteToDisk() + { + std::ofstream fout{ m_targetFilePath }; + if (!fout.is_open()) + { + return false; + } + + fout << m_emitter.c_str(); + + return true; + } +} diff --git a/Volt/Volt/src/Volt/Utility/FileIO/YAMLFileStreamWriter.h b/Volt/Volt/src/Volt/Utility/FileIO/YAMLFileStreamWriter.h new file mode 100644 index 000000000..add6bcefb --- /dev/null +++ b/Volt/Volt/src/Volt/Utility/FileIO/YAMLFileStreamWriter.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Volt/Utility/FileIO/YAMLStreamWriter.h" + +namespace Volt +{ + class YAMLFileStreamWriter : public YAMLStreamWriter + { + public: + YAMLFileStreamWriter(const std::filesystem::path& targetFilePath); + ~YAMLFileStreamWriter() override = default; + + const bool WriteToDisk(); + + private: + std::filesystem::path m_targetFilePath; + }; +} diff --git a/Volt/Volt/src/Volt/Utility/FileIO/YAMLMemoryStreamWriter.cpp b/Volt/Volt/src/Volt/Utility/FileIO/YAMLMemoryStreamWriter.cpp new file mode 100644 index 000000000..cddc2c184 --- /dev/null +++ b/Volt/Volt/src/Volt/Utility/FileIO/YAMLMemoryStreamWriter.cpp @@ -0,0 +1,12 @@ +#include "vtpch.h" +#include "Volt/Utility/FileIO/YAMLMemoryStreamWriter.h" + +namespace Volt +{ + Buffer YAMLMemoryStreamWriter::WriteAndGetBuffer() const + { + Buffer buffer{ m_emitter.size() }; + buffer.Copy(m_emitter.c_str(), m_emitter.size()); + return buffer; + } +} diff --git a/Volt/Volt/src/Volt/Utility/FileIO/YAMLMemoryStreamWriter.h b/Volt/Volt/src/Volt/Utility/FileIO/YAMLMemoryStreamWriter.h new file mode 100644 index 000000000..755b3e899 --- /dev/null +++ b/Volt/Volt/src/Volt/Utility/FileIO/YAMLMemoryStreamWriter.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Volt/Utility/FileIO/YAMLStreamWriter.h" +#include "Volt/Core/Buffer.h" + +namespace Volt +{ + class YAMLMemoryStreamWriter : public YAMLStreamWriter + { + public: + ~YAMLMemoryStreamWriter() = default; + + Buffer WriteAndGetBuffer() const; + }; +} diff --git a/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.cpp b/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.cpp index 5e8a5f77c..a8f5e3abb 100644 --- a/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.cpp +++ b/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.cpp @@ -1,14 +1,9 @@ #include "vtpch.h" #include "YAMLStreamWriter.h" +#include "YAMLFileStreamWriter.h" namespace Volt { - YAMLStreamWriter::YAMLStreamWriter(const std::filesystem::path& targetFilePath) - : m_targetFilePath(targetFilePath) - { - - } - void YAMLStreamWriter::BeginMap() { m_emitter << YAML::BeginMap; @@ -33,17 +28,4 @@ namespace Volt { m_emitter << YAML::Key << mapName << YAML::BeginMap; } - - const bool YAMLStreamWriter::WriteToDisk() - { - std::ofstream fout{ m_targetFilePath }; - if (!fout.is_open()) - { - return false; - } - - fout << m_emitter.c_str(); - - return true; - } } diff --git a/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.h b/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.h index d313ad344..b249ecbe0 100644 --- a/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.h +++ b/Volt/Volt/src/Volt/Utility/FileIO/YAMLStreamWriter.h @@ -11,7 +11,7 @@ namespace Volt class YAMLStreamWriter { public: - YAMLStreamWriter(const std::filesystem::path& targetFilePath); + virtual ~YAMLStreamWriter() = default; void BeginMap(); void EndMap(); @@ -24,10 +24,7 @@ namespace Volt template void SetKey(const K& key, const T& value); - const bool WriteToDisk(); - - private: - std::filesystem::path m_targetFilePath; + protected: YAML::Emitter m_emitter; }; diff --git a/Volt/Volt/src/Volt/Utility/ImageUtility.h b/Volt/Volt/src/Volt/Utility/ImageUtility.h index a2b66da2a..16d33deb2 100644 --- a/Volt/Volt/src/Volt/Utility/ImageUtility.h +++ b/Volt/Volt/src/Volt/Utility/ImageUtility.h @@ -429,6 +429,33 @@ namespace Volt device->FlushSingleUseCommandBuffer(cmdBuffer); } + inline void CopyImageToBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, size_t bufferOffset, VkImage image, uint32_t width, uint32_t height, uint32_t mipLevel) + { + VkBufferImageCopy region{}; + region.bufferOffset = bufferOffset; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = mipLevel; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + + region.imageOffset = { 0, 0, 0 }; + region.imageExtent = { width, height, 1 }; + + vkCmdCopyImageToBuffer(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1, ®ion); + } + + inline void CopyImageToBuffer(VkBuffer buffer, size_t bufferOffset, VkImage image, uint32_t width, uint32_t height, uint32_t mipLevel) + { + auto device = GraphicsContext::GetDevice(); + + VkCommandBuffer cmdBuffer = device->GetSingleUseCommandBuffer(true); + CopyImageToBuffer(cmdBuffer, buffer, bufferOffset, image, width, height, mipLevel); + device->FlushSingleUseCommandBuffer(cmdBuffer); + } + inline void GenerateMipMaps(VkImage image, uint32_t width, uint32_t height, uint32_t mipLevels) { auto device = GraphicsContext::GetDevice(); @@ -584,6 +611,7 @@ namespace Volt case Volt::ImageFormat::RG32F: case Volt::ImageFormat::SRGB: case Volt::ImageFormat::BC6H_SF16: + case Volt::ImageFormat::BC6H_UF16: return true; } @@ -627,6 +655,9 @@ namespace Volt case ImageFormat::BC7: return VK_FORMAT_BC7_UNORM_BLOCK; case ImageFormat::BC7SRGB: return VK_FORMAT_BC7_SRGB_BLOCK; + case ImageFormat::BC6H_SF16: return VK_FORMAT_BC6H_SFLOAT_BLOCK; + case ImageFormat::BC6H_UF16: return VK_FORMAT_BC6H_UFLOAT_BLOCK; + case ImageFormat::DEPTH32F: return VK_FORMAT_D32_SFLOAT; case ImageFormat::DEPTH16U: return VK_FORMAT_D16_UNORM; case ImageFormat::DEPTH24STENCIL8: return VK_FORMAT_D24_UNORM_S8_UINT; @@ -735,7 +766,24 @@ namespace Volt case ImageFormat::DEPTH32F: return 1 * 4; case ImageFormat::DEPTH24STENCIL8: return 4; - case ImageFormat::BC6H_SF16: return 3 * 2; + case ImageFormat::BC1: return 1; + case ImageFormat::BC1SRGB: return 1; + + case ImageFormat::BC2: return 1; + case ImageFormat::BC2SRGB: return 1; + + case ImageFormat::BC3: return 1; + case ImageFormat::BC3SRGB: return 1; + + case ImageFormat::BC4: return 1; + + case ImageFormat::BC5: return 1; + + case ImageFormat::BC6H_SF16: return 1; + case ImageFormat::BC6H_UF16: return 1; + + case ImageFormat::BC7: return 1; + case ImageFormat::BC7SRGB: return 1; } return 0;