Added Serialized Renderable #125

Merged
Pycorax merged 10 commits from SP3-1-SerialisedRenderable into main 2022-10-27 23:27:00 +08:00
22 changed files with 555 additions and 64 deletions

View File

@ -84,7 +84,7 @@ namespace Sandbox
auto& collider = *SHComponentManager::GetComponent_s<SHColliderComponent>(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<SHRenderable>(raccoonSpin);
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(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<SHRigidBodyComponent>(floor);
auto& floorCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(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<SHRenderable>(raccoonShowcase);
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(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);

View File

@ -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<SHMaterialInstance> 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<SHRenderable>(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();

View File

@ -680,7 +680,7 @@ namespace SHADE
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
for (auto& renderable : renderables)
{
if (!renderable.WasMaterialChanged())
if (!renderable.HasChanged())
continue;
// Remove from old material's SuperBatch
@ -768,5 +768,10 @@ namespace SHADE
}
Handle<SHRenderGraphNode> SHGraphicsSystem::GetPrimaryRenderpass() const noexcept
{
return worldRenderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data());
}
#pragma endregion MISC
}

View File

@ -135,7 +135,7 @@ namespace SHADE
void RemoveViewport(Handle<SHViewport> viewport);
/*-----------------------------------------------------------------------------*/
/* Material Creation Functions */
/* Material Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHMaterial> AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass);
void RemoveMaterial(Handle<SHMaterial> material);
@ -143,6 +143,7 @@ namespace SHADE
Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance(Handle<SHMaterial> material);
Handle<SHMaterialInstance> AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst);
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
Handle<SHMaterial> GetDefaultMaterial() { return defaultMaterial; }
/*-----------------------------------------------------------------------------*/
/* Mesh Registration Functions */
@ -286,12 +287,17 @@ namespace SHADE
#endif
Handle<SHMousePickSystem> GetMousePickSystem(void) const noexcept {return mousePickSystem;};
Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
Handle<SHRenderGraphNode> GetPrimaryRenderpass() const noexcept;
//SHRenderGraph const& GetRenderGraph(void) const noexcept;
//Handle<SHVkRenderpass> 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<SHViewport> editorViewport;
Handle<SHRenderer> editorRenderer;

View File

@ -23,7 +23,7 @@ namespace SHADE
}
// Allocate memory for properties
const Handle<SHShaderBlockInterface> SHADER_INFO = getShaderBlockInterface();
const Handle<SHShaderBlockInterface> 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<SHShaderBlockInterface> SHADER_INFO = getShaderBlockInterface();
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterial::getShaderBlockInterface() const noexcept
Handle<SHShaderBlockInterface> SHMaterial::GetShaderBlockInterface() const noexcept
{
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
(

View File

@ -50,13 +50,24 @@ namespace SHADE
template<typename T>
void SetProperty(const std::string& key, const T& value);
template<typename T>
void SetProperty(uint32_t memOffset, const T& value);
template<typename T>
T& GetProperty(const std::string& key);
template<typename T>
const T& GetProperty(const std::string& key) const;
template<typename T>
T& GetProperty(uint32_t memOffset);
template<typename T>
const T& GetProperty(uint32_t memOffset) const;
void ResetProperties();
void ExportProperties(void* dest) const noexcept;
Byte GetPropertiesMemorySize() const noexcept;
/*-----------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> GetShaderBlockInterface() const noexcept;
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
@ -64,11 +75,6 @@ namespace SHADE
Handle<SHVkPipeline> pipeline;
std::unique_ptr<char> propMemory;
Byte propMemorySize = 0;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> getShaderBlockInterface() const noexcept;
};
}

View File

@ -25,7 +25,7 @@ namespace SHADE
template<typename T>
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<typename T>
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<T*>(propMemory.get() + memOffset)) = value;
}
template<typename T>
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 T&>(const_cast<SHMaterial*>(this)->GetProperty(key));
}
template<typename T>
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<T*>(propMemory.get() + memOffset));
}
template<typename T>
T& SHMaterial::GetProperty(uint32_t memOffset)
{
return const_cast<const T&>(const_cast<SHMaterial*>(this)->GetProperty(memOffset));
}
}

View File

@ -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<SHMesh> 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_<SHRenderable>("Renderable Component");
}

View File

@ -11,9 +11,10 @@ of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// External Dependencies
#include <rttr/registration>
// 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<SHMaterialInstance> materialInstance);
Handle<SHMaterialInstance> GetMaterial() const;
Handle<SHMaterialInstance> GetModifiableMaterial();
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
bool HasMaterialChanged() const noexcept { return matChanged; }
/*-------------------------------------------------------------------------------*/
/* Getter Functions */
/* Mesh Functions */
/*-------------------------------------------------------------------------------*/
void SetMesh(Handle<SHMesh> newMesh);
Handle<SHMesh> GetMesh() const noexcept { return mesh; }
Handle<SHMesh> GetPrevMesh() const noexcept { return oldMesh; }
bool HasMeshChanged() const noexcept { return meshChanged; }
/*-------------------------------------------------------------------------------*/
/* Light Functions */
/*-------------------------------------------------------------------------------*/
bool WasMaterialChanged() const noexcept { return materialChanged; }
Handle<SHMaterialInstance> 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<SHMesh> Mesh;
private:
/*-------------------------------------------------------------------------------*/
/* Data Members */
/*-------------------------------------------------------------------------------*/
Handle<SHMesh> mesh;
Handle<SHMesh> oldMesh;
bool meshChanged = true;
Handle<SHMaterialInstance> sharedMaterial;
Handle<SHMaterialInstance> material;
bool materialChanged = true;
bool matChanged = true;
Handle<SHMaterialInstance> oldMaterial;
uint8_t lightLayer;
RTTR_ENABLE()
};
}

View File

@ -244,7 +244,15 @@ namespace SHADE
}
// Add subpass to container and create mapping for it
subpasses.emplace_back(graphStorage->resourceManager->Create<SHSubpass>(graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()), &resourceAttachmentMapping));
subpasses.emplace_back
(
graphStorage->resourceManager->Create<SHSubpass>
(
subpassName,
graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()),
&resourceAttachmentMapping
)
);
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
Handle<SHSubpass> subpass = subpasses.back();
subpass->Init(*graphStorage->resourceManager);

View File

@ -30,7 +30,7 @@ namespace SHADE
*/
/***************************************************************************/
SHSubpass::SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept
SHSubpass::SHSubpass(const std::string& name, Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> 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;
}
}

View File

@ -77,13 +77,15 @@ namespace SHADE
//! are always the last things drawn, so DO NOT USE THIS FUNCTIONALITY FOR ANYTHING
//! COMPLEX.
std::vector<std::function<void(Handle<SHVkCommandBuffer>&)>> exteriorDrawCalls;
/// For identifying subpasses
std::string name;
public:
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHSubpass(Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept;
SHSubpass(const std::string& name, Handle<SHRenderGraphStorage> renderGraphStorage, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping) noexcept;
SHSubpass(SHSubpass&& rhs) noexcept;
SHSubpass& operator=(SHSubpass&& rhs) noexcept;
@ -117,6 +119,7 @@ namespace SHADE
Handle<SHSuperBatch> GetSuperBatch(void) const noexcept;
std::vector<vk::AttachmentReference> const& GetColorAttachmentReferences (void) const noexcept;
vk::Format GetFormatFromAttachmentReference (uint32_t attachmentReference) const noexcept;
const std::string& GetName() const;
friend class SHRenderGraphNode;
friend class SHRenderGraph;

View File

@ -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<uint32_t>(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 }
{}

View File

@ -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<Variable> variables;
std::vector<std::string> variableNames;
std::unordered_map<std::string, uint32_t> 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 */

View File

@ -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:

View File

@ -156,7 +156,6 @@ namespace std
std::size_t hash<pair<SHADE::Handle<T1>, SHADE::Handle<T2>>>::operator()(
std::pair<SHADE::Handle<T1>, SHADE::Handle<T2>> const& pair) const
{
return std::hash<uint64_t>{}(pair.first.GetId().Raw) ^ std::hash<uint64_t>{}(pair.second.GetId().Raw);
}
}

View File

@ -136,11 +136,11 @@ namespace SHADE
template<typename T>
std::optional<AssetID> SHResourceManager::GetAssetID(Handle<T> handle)
{
const Handle GENERIC_HANDLE = Handle(handle);
const Handle<void> GENERIC_HANDLE = Handle<void>(handle);
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<T>();
if (typedAssetIdMap.get().contains(GENERIC_HANDLE))
{
return typedAssetIdMap.GetId()[GENERIC_HANDLE];
return typedAssetIdMap.get()[GENERIC_HANDLE];
}
return {};

View File

@ -1,8 +1,8 @@
#include "SHpch.h"
#include "SHSerializationHelper.hpp"
#include "SHSerialization.h"
#include <yaml-cpp/yaml.h>
#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<SHRenderable>(eid))
{
components[rttr::type::get<SHRenderable>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(renderable);
components[rttr::type::get<SHRenderable>().get_name().data()] = *renderable;
}
if (const auto rigidbody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid))
{
@ -259,5 +259,6 @@ namespace SHADE
if (!componentsNode)
return;
SHSerializationHelper::InitializeComponentFromNode<SHTransformComponent>(componentsNode, eid);
SHSerializationHelper::ConvertNodeToComponent<SHRenderable>(componentsNode, eid);
}
}

View File

@ -1,7 +1,7 @@
#pragma once
#include "ECS_Base/Components/SHComponent.h"
#include <yaml-cpp/yaml.h>
#include "ECS_Base/Components/SHComponent.h"
#include <rttr/registration>
@ -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<SHMaterial>
{
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<SHShaderBlockInterface> pipelineProperties = rhs.GetShaderBlockInterface();
for (int i = 0; i < static_cast<int>(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<float>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
propNode = rhs.GetProperty<int>(VARIABLE->offset);
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
propNode = SHSerializationTools::ValToYAML(rhs.GetProperty<SHVec2>(VARIABLE->offset));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3:
propNode = SHSerializationTools::ValToYAML(rhs.GetProperty<SHVec3>(VARIABLE->offset));
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4:
propNode = SHSerializationTools::ValToYAML(rhs.GetProperty<SHVec4>(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<SHVkShaderModule> 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<SHVkShaderModule>(vertexShader).value_or(0);
node[FRAG_SHADER_YAML_TAG.data()] = 0; // SHResourceManager::GetAssetID<SHVkShaderModule>(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<AssetID>();
if (node[FRAG_SHADER_YAML_TAG.data()])
fragShaderId = node[FRAG_SHADER_YAML_TAG.data()].as<AssetID>();
// Ensure that both shaders are present
if (vertShaderId == 0 || fragShaderId == 0)
return false; // No pipeline
// Get Shader Modules
Handle<SHVkShaderModule> vertexShader, fragShader;
vertexShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(vertShaderId);
fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(fragShaderId);
// Get Pipeline Library
if (node[SUBPASS_YAML_TAG.data()])
{
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
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<std::string>());
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<SHGraphicsSystem>();
if (!gfxSystem)
return false;
rhs.SetPipeline(gfxSystem->GetDefaultMaterial()->GetPipeline());
if (node[PROPS_YAML_TAG.data()])
{
// Loop through all properties
Handle<SHShaderBlockInterface> pipelineProperties = rhs.GetShaderBlockInterface();
const YAML::Node& PROPS_NODE = node[PROPS_YAML_TAG.data()];
for (int i = 0; i < static_cast<int>(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<float>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
rhs.SetProperty(VARIABLE->offset, PROP_NODE.as<int>());
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<SHRenderable>
{
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<SHMesh>(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<SHMesh>(node[MESH_YAML_TAG.data()].as<AssetID>()));
}
if (node[MAT_YAML_TAG.data()])
{
// TODO: Convert Asset ID To Material HAndle
// Temporarily, use default material
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
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>())
{
SHVec4 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>(), propertyNode["Z"].as<float>(), propertyNode["W"].as<float>() };
prop.set_value(component, vec);
prop.set_value(component, SHSerializationTools::YAMLToVec4(propertyNode));
}
else if (propType == rttr::type::get<SHVec3>())
{
SHVec3 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>(), propertyNode["Z"].as<float>() };
prop.set_value(component, vec);
prop.set_value(component, SHSerializationTools::YAMLToVec3(propertyNode));
}
else if (propType == rttr::type::get<SHVec2>())
{
SHVec2 vec{ propertyNode["X"].as<float>(), propertyNode["Y"].as<float>() };
prop.set_value(component, vec);
prop.set_value(component, SHSerializationTools::YAMLToVec2(propertyNode));
}
else if (propType.is_arithmetic())
{
@ -200,5 +398,18 @@ namespace SHADE
}
}
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
static void ConvertNodeToComponent(YAML::Node const& componentsNode, EntityID const& eid)
{
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
if (componentsNode.IsNull() && !component)
return;
auto rttrType = rttr::type::get<ComponentType>();
auto componentNode = componentsNode[rttrType.get_name().data()];
if (componentsNode.IsNull())
return;
YAML::convert<ComponentType>::decode(componentNode, *component);
}
};
}

View File

@ -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<float>(), node["Y"].as<float>() };
}
SHVec3 SHSerializationTools::YAMLToVec3(const YAML::Node& node)
{
return SHVec3 { node["X"].as<float>(), node["Y"].as<float>(), node["Z"].as<float>() };
}
SHVec4 SHSerializationTools::YAMLToVec4(const YAML::Node& node)
{
return SHVec4 { node["X"].as<float>(), node["Y"].as<float>(), node["Z"].as<float>(), node["W"].as<float>() };
}
}

View File

@ -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 <yaml-cpp/yaml.h>
// 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);
};
}

View File

@ -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<int>());
}
if (fieldAssignYaml<System::Int16> (fieldInfo, object, node) ||
fieldAssignYaml<System::Int32> (fieldInfo, object, node) ||
fieldAssignYaml<System::Int64> (fieldInfo, object, node) ||