diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 3f56e140..f80ec19e 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -84,7 +84,7 @@ namespace Sandbox auto& collider = *SHComponentManager::GetComponent_s(entity); //renderable.Mesh = handles.front(); - renderable.Mesh = CUBE_MESH; + renderable.SetMesh(CUBE_MESH); renderable.SetMaterial(customMat); if (y == 50) @@ -108,7 +108,7 @@ namespace Sandbox auto& renderable = *SHComponentManager::GetComponent_s(raccoonSpin); auto& transform = *SHComponentManager::GetComponent_s(raccoonSpin); - renderable.Mesh = handles.front(); + renderable.SetMesh(handles.front()); renderable.SetMaterial(customMat); renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); @@ -123,7 +123,7 @@ namespace Sandbox auto& floorRigidBody = *SHComponentManager::GetComponent_s(floor); auto& floorCollider = *SHComponentManager::GetComponent_s(floor); - floorRenderable.Mesh = CUBE_MESH; + floorRenderable.SetMesh(CUBE_MESH); floorRenderable.SetMaterial(customMat); floorRenderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f)); @@ -149,7 +149,7 @@ namespace Sandbox auto& renderableShowcase = *SHComponentManager::GetComponent_s(raccoonShowcase); auto& transformShowcase = *SHComponentManager::GetComponent_s(raccoonShowcase); - renderableShowcase.Mesh = handles.front(); + renderableShowcase.SetMesh(handles.front()); renderableShowcase.SetMaterial(customMat); renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 09fde60f..d07e0f06 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -45,16 +45,20 @@ namespace SHADE void SHBatch::Add(const SHRenderable* renderable) { + // Ignore if null + if (!renderable->GetMesh()) + return; + // Check if we have a SubBatch with the same mesh yet auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch) - { - return batch.Mesh == renderable->Mesh; - }); + { + return batch.Mesh == renderable->GetMesh(); + }); // Create one if not found if (subBatch == subBatches.end()) { - subBatches.emplace_back(renderable->Mesh); + subBatches.emplace_back(renderable->GetMesh()); subBatch = subBatches.end() - 1; } @@ -73,7 +77,7 @@ namespace SHADE // Check if we have a SubBatch with the same mesh yet auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch) { - return batch.Mesh == renderable->Mesh; + return batch.Mesh == renderable->GetMesh(); }); // Attempt to remove if it exists @@ -84,13 +88,18 @@ namespace SHADE // Check if other renderables in subBatches contain the same material instance bool matUnused = true; + + Handle matToCheck = renderable->HasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial(); + for (const auto& sb : subBatches) + { + // Check material usage for (const auto& rendId : sb.Renderables) { auto rend = SHComponentManager::GetComponent(rendId); if (rend) { - if (rend->GetMaterial() == renderable->GetMaterial()) + if (rend->GetMaterial() == matToCheck) { matUnused = false; break; @@ -101,10 +110,15 @@ namespace SHADE SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!"); } } + } // Material is no longer in this library, so we remove it if (matUnused) - referencedMatInstances.erase(renderable->WasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial()); + referencedMatInstances.erase(renderable->HasChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial()); + + // Mesh is no longer in this batch, so we remove the associated sub batch + if (subBatch->Renderables.empty()) + subBatches.erase(subBatch); // Mark all as dirty setAllDirtyFlags(); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 6fbf5a76..2b8e97bc 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -680,7 +680,7 @@ namespace SHADE auto& renderables = SHComponentManager::GetDense(); for (auto& renderable : renderables) { - if (!renderable.WasMaterialChanged()) + if (!renderable.HasChanged()) continue; // Remove from old material's SuperBatch @@ -768,5 +768,10 @@ namespace SHADE } + Handle SHGraphicsSystem::GetPrimaryRenderpass() const noexcept + { + return worldRenderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data()); + } + #pragma endregion MISC } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index 426f0abe..4e91ca8d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -135,7 +135,7 @@ namespace SHADE void RemoveViewport(Handle viewport); /*-----------------------------------------------------------------------------*/ - /* Material Creation Functions */ + /* Material Functions */ /*-----------------------------------------------------------------------------*/ Handle AddMaterial(Handle vertShader, Handle fragShader, Handle subpass); void RemoveMaterial(Handle material); @@ -143,6 +143,7 @@ namespace SHADE Handle AddOrGetBaseMaterialInstance(Handle material); Handle AddMaterialInstanceCopy(Handle materialInst); void RemoveMaterialInstance(Handle materialInstance); + Handle GetDefaultMaterial() { return defaultMaterial; } /*-----------------------------------------------------------------------------*/ /* Mesh Registration Functions */ @@ -286,12 +287,17 @@ namespace SHADE #endif Handle GetMousePickSystem(void) const noexcept {return mousePickSystem;}; Handle GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;}; + Handle GetPrimaryRenderpass() const noexcept; //SHRenderGraph const& GetRenderGraph(void) const noexcept; //Handle GetRenderPass() const { return renderPass; } private: + /*-----------------------------------------------------------------------------*/ + /* Constants */ + /*-----------------------------------------------------------------------------*/ + static constexpr std::string_view G_BUFFER_RENDER_GRAPH_NODE_NAME = "G-Buffer"; /*-----------------------------------------------------------------------------*/ /* Data Members */ @@ -318,7 +324,7 @@ namespace SHADE SHTextureLibrary texLibrary; SHSamplerCache samplerCache; SHMaterialInstanceCache materialInstanceCache; - // Viewports + // Viewports #ifdef SHEDITOR Handle editorViewport; Handle editorRenderer; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp index 36e30010..b6e1974f 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp @@ -23,7 +23,7 @@ namespace SHADE } // Allocate memory for properties - const Handle SHADER_INFO = getShaderBlockInterface(); + const Handle SHADER_INFO = GetShaderBlockInterface(); propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; if (propMemorySize <= 0) { @@ -59,14 +59,14 @@ namespace SHADE size_t SHMaterial::GetPropertiesMemorySize() const noexcept { - const Handle SHADER_INFO = getShaderBlockInterface(); + const Handle SHADER_INFO = GetShaderBlockInterface(); return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; } /*---------------------------------------------------------------------------------*/ /* Helper Functions */ /*---------------------------------------------------------------------------------*/ - Handle SHMaterial::getShaderBlockInterface() const noexcept + Handle SHMaterial::GetShaderBlockInterface() const noexcept { return pipeline->GetPipelineLayout()->GetShaderBlockInterface ( diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h index ec546fd5..ad7da4a6 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h @@ -50,13 +50,24 @@ namespace SHADE template void SetProperty(const std::string& key, const T& value); template + void SetProperty(uint32_t memOffset, const T& value); + template T& GetProperty(const std::string& key); template const T& GetProperty(const std::string& key) const; + template + T& GetProperty(uint32_t memOffset); + template + const T& GetProperty(uint32_t memOffset) const; void ResetProperties(); void ExportProperties(void* dest) const noexcept; Byte GetPropertiesMemorySize() const noexcept; + /*-----------------------------------------------------------------------------*/ + /* Query Functions */ + /*-----------------------------------------------------------------------------*/ + Handle GetShaderBlockInterface() const noexcept; + private: /*-----------------------------------------------------------------------------*/ /* Data Members */ @@ -64,11 +75,6 @@ namespace SHADE Handle pipeline; std::unique_ptr propMemory; Byte propMemorySize = 0; - - /*-----------------------------------------------------------------------------*/ - /* Helper Functions */ - /*-----------------------------------------------------------------------------*/ - Handle getShaderBlockInterface() const noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp index 49587921..3e56bfd5 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp @@ -25,7 +25,7 @@ namespace SHADE template void SHMaterial::SetProperty(const std::string& key, const T& value) { - const auto SHADER_INFO = getShaderBlockInterface(); + const auto SHADER_INFO = GetShaderBlockInterface(); const auto PROP_INFO = SHADER_INFO->GetVariable(key); if (PROP_INFO == nullptr) { @@ -36,14 +36,25 @@ namespace SHADE T* dataPtr = propMemory.get() + PROP_INFO->offset; *dataPtr = value; } + + template + void SHMaterial::SetProperty(uint32_t memOffset, const T& value) + { + // Check if out of bounds + if (memOffset + sizeof(T) > propMemorySize) + throw std::invalid_argument("Attempted to set an invalid property!"); + // Set + (*reinterpret_cast(propMemory.get() + memOffset)) = value; + } + template T& SHMaterial::GetProperty(const std::string& key) { - const auto SHADER_INFO = getShaderBlockInterface(); + const auto SHADER_INFO = GetShaderBlockInterface(); const auto PROP_INFO = SHADER_INFO->GetVariable(key); if (PROP_INFO == nullptr) { - throw std::invalid_argument("Attempted to set an invalid property!"); + throw std::invalid_argument("Attempted to retrieve an invalid property!"); } // Get offset and return the memory directly @@ -55,5 +66,19 @@ namespace SHADE { return const_cast(const_cast(this)->GetProperty(key)); } + + template + const T& SHMaterial::GetProperty(uint32_t memOffset) const + { + // Check if out of bounds + if (memOffset + sizeof(T) > propMemorySize) + throw std::invalid_argument("Attempted to retrieve an invalid property!"); + return *(reinterpret_cast(propMemory.get() + memOffset)); + } + template + T& SHMaterial::GetProperty(uint32_t memOffset) + { + return const_cast(const_cast(this)->GetProperty(memOffset)); + } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 7c4d0bb9..22de83b8 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -23,7 +23,7 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ void SHRenderable::OnCreate() { - materialChanged = true; + matChanged = true; sharedMaterial = {}; material = {}; oldMaterial = {}; @@ -55,7 +55,7 @@ namespace SHADE return; // Flag that material was changed - materialChanged = true; + matChanged = true; // Free copies of materials if any if (material) @@ -92,15 +92,41 @@ namespace SHADE return material; } - + + /*-----------------------------------------------------------------------------------*/ + /* Mesh Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHRenderable::SetMesh(Handle newMesh) + { + oldMesh = mesh; + mesh = newMesh; + meshChanged = true; + } + + /*-----------------------------------------------------------------------------------*/ + /* Light Functions */ + /*-----------------------------------------------------------------------------------*/ uint8_t SHRenderable::GetLightLayer(void) const noexcept { return lightLayer; } - + + /*-----------------------------------------------------------------------------------*/ + /* Batcher Dispatcher Functions */ + /*-----------------------------------------------------------------------------------*/ void SHRenderable::ResetChangedFlag() { - materialChanged = false; - oldMaterial = {}; + matChanged = false; + meshChanged = false; + oldMaterial = {}; + oldMesh = {}; } } + +RTTR_REGISTRATION +{ + using namespace SHADE; + using namespace rttr; + + registration::class_("Renderable Component"); +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h index 75e42d60..8893c43b 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h @@ -11,9 +11,10 @@ of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ #pragma once +// External Dependencies +#include // Project Includes #include "Resource/SHHandle.h" -//#include "SHTransform.h" #include "ECS_Base/Components/SHComponent.h" #include "Math/SHMatrix.h" #include "SH_API.h" @@ -50,33 +51,42 @@ namespace SHADE void SetMaterial(Handle materialInstance); Handle GetMaterial() const; Handle GetModifiableMaterial(); + Handle GetPrevMaterial() const noexcept { return oldMaterial; } + bool HasMaterialChanged() const noexcept { return matChanged; } /*-------------------------------------------------------------------------------*/ - /* Getter Functions */ + /* Mesh Functions */ + /*-------------------------------------------------------------------------------*/ + void SetMesh(Handle newMesh); + Handle GetMesh() const noexcept { return mesh; } + Handle GetPrevMesh() const noexcept { return oldMesh; } + bool HasMeshChanged() const noexcept { return meshChanged; } + + /*-------------------------------------------------------------------------------*/ + /* Light Functions */ /*-------------------------------------------------------------------------------*/ - bool WasMaterialChanged() const noexcept { return materialChanged; } - Handle GetPrevMaterial() const noexcept { return oldMaterial; } uint8_t GetLightLayer (void) const noexcept; /*-------------------------------------------------------------------------------*/ /* Batcher Dispatcher Functions */ /*-------------------------------------------------------------------------------*/ + bool HasChanged() const noexcept { return matChanged || meshChanged; } // Whether or not the mesh or material has changed void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this - /*-------------------------------------------------------------------------------*/ - /* Data Members */ - /*-------------------------------------------------------------------------------*/ - Handle Mesh; - private: /*-------------------------------------------------------------------------------*/ /* Data Members */ /*-------------------------------------------------------------------------------*/ + Handle mesh; + Handle oldMesh; + bool meshChanged = true; Handle sharedMaterial; Handle material; - bool materialChanged = true; + bool matChanged = true; Handle oldMaterial; uint8_t lightLayer; + + RTTR_ENABLE() }; } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index c315bffd..607c777a 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -244,7 +244,15 @@ namespace SHADE } // Add subpass to container and create mapping for it - subpasses.emplace_back(graphStorage->resourceManager->Create(graphStorage, GetHandle(), static_cast(subpasses.size()), &resourceAttachmentMapping)); + subpasses.emplace_back + ( + graphStorage->resourceManager->Create + ( + subpassName, + graphStorage, GetHandle(), static_cast(subpasses.size()), + &resourceAttachmentMapping + ) + ); subpassIndexing.try_emplace(subpassName, static_cast(subpasses.size()) - 1u); Handle subpass = subpasses.back(); subpass->Init(*graphStorage->resourceManager); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index af6f3089..d8f4f8c2 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -30,7 +30,7 @@ namespace SHADE */ /***************************************************************************/ - SHSubpass::SHSubpass(Handle renderGraphStorage, Handle const& parent, uint32_t index, std::unordered_map const* mapping) noexcept + SHSubpass::SHSubpass(const std::string& name, Handle renderGraphStorage, Handle const& parent, uint32_t index, std::unordered_map const* mapping) noexcept : resourceAttachmentMapping{ mapping } , parentNode{ parent } , subpassIndex{ index } @@ -38,6 +38,7 @@ namespace SHADE , colorReferences{} , depthReferences{} , inputReferences{} + , name { name } , graphStorage{ renderGraphStorage } , inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS} { @@ -411,4 +412,8 @@ namespace SHADE return parentNode->GetResource(attachmentReference)->GetResourceFormat(); } + const std::string& SHSubpass::GetName() const + { + return name; + } } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h index 166f0d76..c82ebdd0 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h @@ -77,13 +77,15 @@ namespace SHADE //! are always the last things drawn, so DO NOT USE THIS FUNCTIONALITY FOR ANYTHING //! COMPLEX. std::vector&)>> exteriorDrawCalls; + /// For identifying subpasses + std::string name; public: /*-----------------------------------------------------------------------*/ /* CTORS AND DTORS */ /*-----------------------------------------------------------------------*/ - SHSubpass(Handle renderGraphStorage, Handle const& parent, uint32_t index, std::unordered_map const* mapping) noexcept; + SHSubpass(const std::string& name, Handle renderGraphStorage, Handle const& parent, uint32_t index, std::unordered_map const* mapping) noexcept; SHSubpass(SHSubpass&& rhs) noexcept; SHSubpass& operator=(SHSubpass&& rhs) noexcept; @@ -117,6 +119,7 @@ namespace SHADE Handle GetSuperBatch(void) const noexcept; std::vector const& GetColorAttachmentReferences (void) const noexcept; vk::Format GetFormatFromAttachmentReference (uint32_t attachmentReference) const noexcept; + const std::string& GetName() const; friend class SHRenderGraphNode; friend class SHRenderGraph; diff --git a/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp b/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp index 75ede865..f214c094 100644 --- a/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp +++ b/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.cpp @@ -14,6 +14,7 @@ namespace SHADE return; } variables.emplace_back(std::move(newVariable)); + variableNames.emplace_back(name); variableIndexing.try_emplace(std::move(name), static_cast(variables.size() - 1)); } @@ -41,6 +42,19 @@ namespace SHADE return variableIndexing.at(variableName); } + const std::string& SHShaderBlockInterface::GetVariableName(uint32_t index) const noexcept + { + if (index < variableNames.size()) + return variableNames.at(index); + + return {}; + } + + size_t SHShaderBlockInterface::GetVariableCount() const noexcept + { + return variables.size(); + } + SHShaderBlockInterface::SHShaderBlockInterface(void) noexcept : bytesRequired{ 0 } {} diff --git a/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h b/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h index e546b452..ae75e2c8 100644 --- a/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h +++ b/SHADE_Engine/src/Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h @@ -12,13 +12,24 @@ namespace SHADE public: struct Variable { + enum class Type + { + OTHER, + FLOAT, + INT, + VECTOR2, + VECTOR3, + VECTOR4 + }; //! Offset of the variable in the block uint32_t offset; + Type type; }; private: //! containers of variable information std::vector variables; + std::vector variableNames; std::unordered_map variableIndexing; //! bytes required by the block (includes padding). This variable is required @@ -29,6 +40,8 @@ namespace SHADE Variable const* const GetVariable (std::string const& variableName) const noexcept; Variable const* const GetVariable(uint32_t index) const noexcept; uint32_t GetVariableIndex(std::string const& variableName) const; + const std::string& GetVariableName(uint32_t index) const noexcept; + size_t GetVariableCount() const noexcept; /*-----------------------------------------------------------------------*/ /* CTORS AND DTORS */ diff --git a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp index e635f763..f28561c5 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp +++ b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp @@ -97,17 +97,45 @@ namespace SHADE switch (member.type_description->op) { case SpvOp::SpvOpTypeFloat: - interfaceHdl->AddVariable(parentVarName + std::string(member.name), SHShaderBlockInterface::Variable(parentOffset + member.offset)); + interfaceHdl->AddVariable + ( + parentVarName + std::string(member.name), + SHShaderBlockInterface::Variable + ( + parentOffset + member.offset, + SHShaderBlockInterface::Variable::Type::FLOAT + ) + ); biggestAlignment = std::max (biggestAlignment, 4u); break; case SpvOp::SpvOpTypeVector: - interfaceHdl->AddVariable(parentVarName + std::string(member.name), SHShaderBlockInterface::Variable(parentOffset + member.offset)); + SHShaderBlockInterface::Variable::Type varType; + switch (dim) + { + case 2: varType = SHShaderBlockInterface::Variable::Type::VECTOR2; break; + case 3: varType = SHShaderBlockInterface::Variable::Type::VECTOR3; break; + case 4: varType = SHShaderBlockInterface::Variable::Type::VECTOR4; break; + default: varType = SHShaderBlockInterface::Variable::Type::OTHER; break; + } + interfaceHdl->AddVariable + ( + parentVarName + std::string(member.name), + SHShaderBlockInterface::Variable(parentOffset + member.offset, varType) + ); if (dim == 3) dim = 4; biggestAlignment = std::max (biggestAlignment, dim * member.type_description->traits.numeric.scalar.width / 8); break; case SpvOp::SpvOpTypeInt: - interfaceHdl->AddVariable(parentVarName + std::string(member.name), SHShaderBlockInterface::Variable(parentOffset + member.offset)); + interfaceHdl->AddVariable + ( + parentVarName + std::string(member.name), + SHShaderBlockInterface::Variable + ( + parentOffset + member.offset, + SHShaderBlockInterface::Variable::Type::INT + ) + ); biggestAlignment = std::max(biggestAlignment, 4u); break; case SpvOp::SpvOpTypeStruct: diff --git a/SHADE_Engine/src/Resource/SHHandle.hpp b/SHADE_Engine/src/Resource/SHHandle.hpp index 53061ac7..c5d14132 100644 --- a/SHADE_Engine/src/Resource/SHHandle.hpp +++ b/SHADE_Engine/src/Resource/SHHandle.hpp @@ -156,7 +156,6 @@ namespace std std::size_t hash, SHADE::Handle>>::operator()( std::pair, SHADE::Handle> const& pair) const { - return std::hash{}(pair.first.GetId().Raw) ^ std::hash{}(pair.second.GetId().Raw); } } diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index cff4e84b..072adaa2 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -136,11 +136,11 @@ namespace SHADE template std::optional SHResourceManager::GetAssetID(Handle handle) { - const Handle GENERIC_HANDLE = Handle(handle); + const Handle GENERIC_HANDLE = Handle(handle); auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap(); if (typedAssetIdMap.get().contains(GENERIC_HANDLE)) { - return typedAssetIdMap.GetId()[GENERIC_HANDLE]; + return typedAssetIdMap.get()[GENERIC_HANDLE]; } return {}; diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index 3804db95..79c8308f 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -1,8 +1,8 @@ #include "SHpch.h" -#include "SHSerializationHelper.hpp" -#include "SHSerialization.h" #include +#include "SHSerializationHelper.hpp" +#include "SHSerialization.h" #include "ECS_Base/Managers/SHEntityManager.h" #include "Scene/SHSceneManager.h" @@ -186,7 +186,7 @@ namespace SHADE } if (const auto renderable = SHComponentManager::GetComponent_s(eid)) { - components[rttr::type::get().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(renderable); + components[rttr::type::get().get_name().data()] = *renderable; } if (const auto rigidbody = SHComponentManager::GetComponent_s(eid)) { @@ -259,5 +259,6 @@ namespace SHADE if (!componentsNode) return; SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); + SHSerializationHelper::ConvertNodeToComponent(componentsNode, eid); } } diff --git a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp index da98c885..a8e46d88 100644 --- a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp +++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp @@ -1,7 +1,7 @@ #pragma once -#include "ECS_Base/Components/SHComponent.h" #include +#include "ECS_Base/Components/SHComponent.h" #include @@ -9,6 +9,207 @@ #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec4.h" +#include "Resource/SHResourceManager.h" +#include "Graphics/MiddleEnd/Interface/SHRenderable.h" +#include "Graphics/MiddleEnd/Interface/SHMaterial.h" +#include "SHSerializationTools.h" + +namespace YAML +{ + using namespace SHADE; + template<> + struct convert + { + static constexpr std::string_view VERT_SHADER_YAML_TAG = "VertexShader"; + static constexpr std::string_view FRAG_SHADER_YAML_TAG = "FragmentShader"; + static constexpr std::string_view SUBPASS_YAML_TAG = "SubPass"; + static constexpr std::string_view PROPS_YAML_TAG = "Properties"; + + static YAML::Node encode(SHMaterial const& rhs) + { + // Write Properties + YAML::Node propertiesNode; + Handle pipelineProperties = rhs.GetShaderBlockInterface(); + for (int i = 0; i < static_cast(pipelineProperties->GetVariableCount()); ++i) + { + const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i); + if (!VARIABLE) + break; + const std::string& VAR_NAME = pipelineProperties->GetVariableName(i); + YAML::Node propNode; + switch (VARIABLE->type) + { + case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT: + propNode = rhs.GetProperty(VARIABLE->offset); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::INT: + propNode = rhs.GetProperty(VARIABLE->offset); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2: + propNode = SHSerializationTools::ValToYAML(rhs.GetProperty(VARIABLE->offset)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3: + propNode = SHSerializationTools::ValToYAML(rhs.GetProperty(VARIABLE->offset)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4: + propNode = SHSerializationTools::ValToYAML(rhs.GetProperty(VARIABLE->offset)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::OTHER: + default: + continue; + break; + } + propertiesNode[VAR_NAME.data()] = propNode; + } + + // Get Shader Handles + const auto& SHADERS = rhs.GetPipeline()->GetPipelineLayout()->GetShaderModules(); + Handle vertexShader, fragShader; + for (const auto& shader : SHADERS) + { + const auto FLAG_BITS = shader->GetShaderStageFlagBits(); + if (FLAG_BITS & vk::ShaderStageFlagBits::eVertex) + vertexShader = shader; + else if (FLAG_BITS & vk::ShaderStageFlagBits::eFragment) + fragShader = shader; + } + + // Write Material + YAML::Node node; + + node[VERT_SHADER_YAML_TAG.data()] = 0; // SHResourceManager::GetAssetID(vertexShader).value_or(0); + node[FRAG_SHADER_YAML_TAG.data()] = 0; // SHResourceManager::GetAssetID(fragShader).value_or(0); + node[SUBPASS_YAML_TAG.data()] = rhs.GetPipeline()->GetPipelineState().GetSubpass()->GetName(); + node[PROPS_YAML_TAG.data()] = propertiesNode; + + return node; + } + static bool decode(YAML::Node const& node, SHMaterial& rhs) + { + /* + // Retrieve Shader Asset IDs + AssetID vertShaderId = 0; + AssetID fragShaderId = 0; + if (node[VERT_SHADER_YAML_TAG.data()]) + vertShaderId = node[VERT_SHADER_YAML_TAG.data()].as(); + if (node[FRAG_SHADER_YAML_TAG.data()]) + fragShaderId = node[FRAG_SHADER_YAML_TAG.data()].as(); + + // Ensure that both shaders are present + if (vertShaderId == 0 || fragShaderId == 0) + return false; // No pipeline + + // Get Shader Modules + Handle vertexShader, fragShader; + vertexShader = SHResourceManager::LoadOrGet(vertShaderId); + fragShader = SHResourceManager::LoadOrGet(fragShaderId); + + // Get Pipeline Library + if (node[SUBPASS_YAML_TAG.data()]) + { + auto gfxSystem = SHSystemManager::GetSystem(); + if (!gfxSystem) + return false; + + // Grab subpass from worldRenderer + auto renderPass = gfxSystem->GetPrimaryRenderpass(); + if (!renderPass) + return false; + auto subPass = renderPass->GetSubpass(node[SUBPASS_YAML_TAG.data()].as()); + if (!subPass) + return false; + + // Set Pipeline + rhs.SetPipeline(renderPass->GetOrCreatePipeline + ( + std::make_pair(vertexShader, fragShader), + subPass + )); + } + */ + + // TODO: Load Proper Material! + // Set default material + auto gfxSystem = SHSystemManager::GetSystem(); + if (!gfxSystem) + return false; + rhs.SetPipeline(gfxSystem->GetDefaultMaterial()->GetPipeline()); + + if (node[PROPS_YAML_TAG.data()]) + { + // Loop through all properties + Handle pipelineProperties = rhs.GetShaderBlockInterface(); + const YAML::Node& PROPS_NODE = node[PROPS_YAML_TAG.data()]; + for (int i = 0; i < static_cast(pipelineProperties->GetVariableCount()); ++i) + { + const std::string& PROP_NAME = pipelineProperties->GetVariableName(i); + const auto& PROP_NODE = PROPS_NODE[PROP_NAME.data()]; + if (PROP_NODE) + { + const std::string& VAR_NAME = pipelineProperties->GetVariableName(i); + const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i); + switch (VARIABLE->type) + { + case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT: + rhs.SetProperty(VARIABLE->offset, PROP_NODE.as()); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::INT: + rhs.SetProperty(VARIABLE->offset, PROP_NODE.as()); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2: + rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec2(PROP_NODE)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3: + rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec3(PROP_NODE)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4: + rhs.SetProperty(VARIABLE->offset, SHSerializationTools::YAMLToVec4(PROP_NODE)); + break; + case SHADE::SHShaderBlockInterface::Variable::Type::OTHER: + default: + continue; + break; + } + } + } + } + return true; + } + }; + + template<> + struct convert + { + static constexpr std::string_view MESH_YAML_TAG = "Mesh"; + static constexpr std::string_view MAT_YAML_TAG = "Material"; + + static YAML::Node encode(SHRenderable const& rhs) + { + YAML::Node node; + node[MESH_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetMesh()).value_or(0); + node[MAT_YAML_TAG.data()] = 0; // TODO: Asset ID + return node; + } + static bool decode(YAML::Node const& node, SHRenderable& rhs) + { + if (node[MESH_YAML_TAG.data()]) + { + rhs.SetMesh(SHResourceManager::LoadOrGet(node[MESH_YAML_TAG.data()].as())); + } + if (node[MAT_YAML_TAG.data()]) + { + // TODO: Convert Asset ID To Material HAndle + // Temporarily, use default material + auto gfxSystem = SHSystemManager::GetSystem(); + if (!gfxSystem) + return false; + rhs.SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(gfxSystem->GetDefaultMaterial())); + } + return true; + } + }; +} + namespace SHADE { @@ -126,18 +327,15 @@ namespace SHADE auto propType = prop.get_type(); if (propType == rttr::type::get()) { - SHVec4 vec{ propertyNode["X"].as(), propertyNode["Y"].as(), propertyNode["Z"].as(), propertyNode["W"].as() }; - prop.set_value(component, vec); + prop.set_value(component, SHSerializationTools::YAMLToVec4(propertyNode)); } else if (propType == rttr::type::get()) { - SHVec3 vec{ propertyNode["X"].as(), propertyNode["Y"].as(), propertyNode["Z"].as() }; - prop.set_value(component, vec); + prop.set_value(component, SHSerializationTools::YAMLToVec3(propertyNode)); } else if (propType == rttr::type::get()) { - SHVec2 vec{ propertyNode["X"].as(), propertyNode["Y"].as() }; - prop.set_value(component, vec); + prop.set_value(component, SHSerializationTools::YAMLToVec2(propertyNode)); } else if (propType.is_arithmetic()) { @@ -200,5 +398,18 @@ namespace SHADE } } + template , bool> = true> + static void ConvertNodeToComponent(YAML::Node const& componentsNode, EntityID const& eid) + { + auto component = SHComponentManager::GetComponent_s(eid); + if (componentsNode.IsNull() && !component) + return; + auto rttrType = rttr::type::get(); + auto componentNode = componentsNode[rttrType.get_name().data()]; + if (componentsNode.IsNull()) + return; + YAML::convert::decode(componentNode, *component); + } + }; } diff --git a/SHADE_Engine/src/Serialization/SHSerializationTools.cpp b/SHADE_Engine/src/Serialization/SHSerializationTools.cpp new file mode 100644 index 00000000..86a74613 --- /dev/null +++ b/SHADE_Engine/src/Serialization/SHSerializationTools.cpp @@ -0,0 +1,67 @@ +/************************************************************************************//*! +\file SHSerializationTools.cpp +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 22, 2022 +\brief Contains the definition of functions of the SHSerializationTools class. + + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#include "SHpch.h" +#include "SHSerializationTools.h" + +namespace SHADE +{ + /*-----------------------------------------------------------------------------------*/ + /* YAML Serialization Functions */ + /*-----------------------------------------------------------------------------------*/ + YAML::Node SHSerializationTools::ValToYAML(const SHVec2& vec) + { + YAML::Node node; + node.SetStyle(YAML::EmitterStyle::Flow); + node["X"] = vec.x; + node["Y"] = vec.y; + return node; + } + YAML::Node SHSerializationTools::ValToYAML(const SHVec3& vec) + { + YAML::Node node; + node.SetStyle(YAML::EmitterStyle::Flow); + node["X"] = vec.x; + node["Y"] = vec.y; + node["Z"] = vec.z; + return node; + } + YAML::Node SHSerializationTools::ValToYAML(const SHVec4& vec) + { + YAML::Node node; + node.SetStyle(YAML::EmitterStyle::Flow); + node["X"] = vec.x; + node["Y"] = vec.y; + node["Z"] = vec.z; + node["W"] = vec.w; + return node; + } + + /*-----------------------------------------------------------------------------------*/ + /* YAML Deserialization Functions */ + /*-----------------------------------------------------------------------------------*/ + SHVec2 SHSerializationTools::YAMLToVec2(const YAML::Node& node) + { + return SHVec2 { node["X"].as(), node["Y"].as() }; + } + + SHVec3 SHSerializationTools::YAMLToVec3(const YAML::Node& node) + { + return SHVec3 { node["X"].as(), node["Y"].as(), node["Z"].as() }; + } + + SHVec4 SHSerializationTools::YAMLToVec4(const YAML::Node& node) + { + return SHVec4 { node["X"].as(), node["Y"].as(), node["Z"].as(), node["W"].as() }; + } + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Serialization/SHSerializationTools.h b/SHADE_Engine/src/Serialization/SHSerializationTools.h new file mode 100644 index 00000000..3a3f6645 --- /dev/null +++ b/SHADE_Engine/src/Serialization/SHSerializationTools.h @@ -0,0 +1,54 @@ +/************************************************************************************//*! +\file SHSerializationTools.h +\author Tng Kah Wei, kahwei.tng, 390009620 +\par email: kahwei.tng\@digipen.edu +\date Oct 22, 2022 +\brief Contains the class definition of SHSerializationTools. + + +Copyright (C) 2022 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ +#pragma once + +// External Dependencies +#include +// Project Includes +#include "SH_API.h" +#include "Math/Vector/SHVec2.h" +#include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec4.h" + +namespace SHADE +{ + /*************************************************************************************/ + /*! + \brief + Static class that contains useful functions for converting values to YAML Nodes + and vice versa. + */ + /*************************************************************************************/ + class SH_API SHSerializationTools + { + public: + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + SHSerializationTools() = delete; + + /*---------------------------------------------------------------------------------*/ + /* YAML Serialization Functions */ + /*---------------------------------------------------------------------------------*/ + static YAML::Node ValToYAML(const SHVec2& vec); + static YAML::Node ValToYAML(const SHVec3& vec); + static YAML::Node ValToYAML(const SHVec4& vec); + + /*---------------------------------------------------------------------------------*/ + /* YAML Deserialization Functions */ + /*---------------------------------------------------------------------------------*/ + static SHVec2 YAMLToVec2(const YAML::Node& node); + static SHVec3 YAMLToVec3(const YAML::Node& node); + static SHVec4 YAMLToVec4(const YAML::Node& node); + }; +} \ No newline at end of file diff --git a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx index 3e963818..f114d01b 100644 --- a/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx +++ b/SHADE_Managed/src/Serialisation/ReflectionUtilities.cxx @@ -184,10 +184,6 @@ namespace SHADE void ReflectionUtilities::writeYamlIntoField(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node) { - if (fieldInfo->FieldType == System::Int16::typeid) - { - fieldInfo->SetValue(object, node.as()); - } if (fieldAssignYaml (fieldInfo, object, node) || fieldAssignYaml (fieldInfo, object, node) || fieldAssignYaml (fieldInfo, object, node) ||