From 9d8dfd334f5c58636f2bc98273a096bd35847711 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Sat, 22 Oct 2022 19:38:02 +0800 Subject: [PATCH] Added serialization interfaces for Material (missing Shader) --- .../MiddleEnd/Interface/SHMaterial.cpp | 6 +- .../Graphics/MiddleEnd/Interface/SHMaterial.h | 16 ++- .../MiddleEnd/Interface/SHMaterial.hpp | 31 ++++- .../Serialization/SHSerializationHelper.hpp | 116 +++++++++++++++++- .../Serialization/SHSerializationTools.cpp | 67 ++++++++++ .../src/Serialization/SHSerializationTools.h | 54 ++++++++ .../src/Serialisation/ReflectionUtilities.cxx | 4 - 7 files changed, 273 insertions(+), 21 deletions(-) create mode 100644 SHADE_Engine/src/Serialization/SHSerializationTools.cpp create mode 100644 SHADE_Engine/src/Serialization/SHSerializationTools.h 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/Serialization/SHSerializationHelper.hpp b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp index 48689298..048867a5 100644 --- a/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp +++ b/SHADE_Engine/src/Serialization/SHSerializationHelper.hpp @@ -11,10 +11,117 @@ #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 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; + } + + // Write Material + YAML::Node node; + + node[VERT_SHADER_YAML_TAG.data()] = 0; + node[FRAG_SHADER_YAML_TAG.data()] = 0; + node[PROPS_YAML_TAG.data()] = propertiesNode; + + return node; + } + static bool decode(YAML::Node const& node, SHMaterial& rhs) + { + if (node[VERT_SHADER_YAML_TAG.data()]) + { + // TODO + } + if (node[FRAG_SHADER_YAML_TAG.data()]) + { + // TODO + } + 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 { @@ -160,18 +267,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()) { 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) ||