diff --git a/SHADE_Application/premake5.lua b/SHADE_Application/premake5.lua index 9aa1707b..50bd41b2 100644 --- a/SHADE_Application/premake5.lua +++ b/SHADE_Application/premake5.lua @@ -22,13 +22,22 @@ project "SHADE_Application" includedirs { - "%{IncludeDir.spdlog}/include", "../SHADE_Engine/src", "src", "%{IncludeDir.dotnet}/include", "%{IncludeDir.SDL}/include", } + + externalincludedirs + { + "%{IncludeDir.spdlog}/include", + "%{IncludeDir.VULKAN}/include", + "%{IncludeDir.VMA}/include", + "%{IncludeDir.VULKAN}/Source/SPIRV-Reflect" + } + externalwarnings "Off" + flags { "MultiProcessorCompile" @@ -47,6 +56,11 @@ project "SHADE_Application" "%{IncludeDir.spdlog}/lib", "%{IncludeDir.SDL}/lib", } + + defines + { + "NOMINMAX" + } disablewarnings { diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index cbf3e5d9..fb6fd803 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -1,9 +1,11 @@ #include "SBpch.h" #include "SBApplication.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#define SHEDITOR #ifdef SHEDITOR -#include "Editor/SHEditor.h" -#include "Scenes/SBEditorScene.h" +//#include "Editor/SHEditor.h" +//#include "Scenes/SBEditorScene.h" #endif // SHEDITOR #include "Tools/SHLogger.h" @@ -32,9 +34,17 @@ namespace Sandbox SDL_Init(SDL_INIT_VIDEO); window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); + SHADE::SHSystemManager::CreateSystem(); + SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); + SHADE::SHSystemManager::RegisterRoutine(1); + + + graphicsSystem->SetWindow(&window); SDL_CreateWindowFrom(window.GetHWND()); + SHADE::SHSystemManager::Init(); #ifdef SHEDITOR + //SHADE::SHEditor::Initialize(window.GetHWND()); #else #endif @@ -44,21 +54,30 @@ namespace Sandbox void SBApplication::Update(void) { + SHADE::SHGraphicsSystem* graphicsSystem = static_cast(SHADE::SHSystemManager::GetSystem()); + //TODO: Change true to window is open while (!window.WindowShouldClose()) { - #ifdef SHEDITOR - #else - #endif - } + //#ifdef SHEDITOR + //SHADE::SHEditor::PreRender(); + //#endif + graphicsSystem->BeginRender(); + graphicsSystem->Run(1.0f); + //#ifdef SHEDITOR + //SHADE::SHEditor::PreRender(); + //SHADE::SHEditor::Update(); + //SHADE::SHEditor::Render(); + //#endif + graphicsSystem->EndRender(); + } } void SBApplication::Exit(void) { - // Shutdown scripting SHADE::SHScriptEngine::Exit(); - + SHADE::SHSystemManager::Exit(); SDL_DestroyWindow(sdlWindow); SDL_Quit(); #ifdef SHEDITOR diff --git a/SHADE_Application/src/Application/SBApplication.h b/SHADE_Application/src/Application/SBApplication.h index 9a6e4153..63626907 100644 --- a/SHADE_Application/src/Application/SBApplication.h +++ b/SHADE_Application/src/Application/SBApplication.h @@ -1,7 +1,8 @@ #ifndef SB_APPLICATION_H #define SB_APPLICATION_H +#include +#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h" #include -#include "Graphics/Windowing/SHWindow.h" //using namespace SHADE; namespace Sandbox diff --git a/SHADE_Engine/premake5.lua b/SHADE_Engine/premake5.lua index d56d78cf..74f19f96 100644 --- a/SHADE_Engine/premake5.lua +++ b/SHADE_Engine/premake5.lua @@ -15,14 +15,17 @@ project "SHADE_Engine" "%{prj.location}/src/**.hpp", "%{prj.location}/src/**.c", "%{prj.location}/src/**.cpp", - "%{prj.location}/src/**.glsl", - "%{wks.location}/Dependencies/stb_image/**.cpp" + "%{prj.location}/src/**.glsl" } includedirs { "%{prj.location}/src", - "%{IncludeDir.assimp}/include", + } + + externalincludedirs + { + "%{IncludeDir.assimp}/include", "%{IncludeDir.imgui}", "%{IncludeDir.imguizmo}", "%{IncludeDir.imnodes}", @@ -40,6 +43,8 @@ project "SHADE_Engine" "%{IncludeDir.dotnet}/include", } + externalwarnings "Off" + libdirs { "%{prj.location}/libs", diff --git a/SHADE_Engine/src/ECS_Base/Components/SHComponent.h b/SHADE_Engine/src/ECS_Base/Components/SHComponent.h index edd8436c..aba3ba51 100644 --- a/SHADE_Engine/src/ECS_Base/Components/SHComponent.h +++ b/SHADE_Engine/src/ECS_Base/Components/SHComponent.h @@ -9,8 +9,7 @@ *********************************************************************/ -#ifndef SH_COMPONENT_H -#define SH_COMPONENT_H +#pragma once #include "SHpch.h" #include "../SHECSMacros.h" @@ -119,4 +118,3 @@ namespace SHADE }; } -#endif diff --git a/SHADE_Engine/src/ECS_Base/Components/SHComponentGroup.cpp b/SHADE_Engine/src/ECS_Base/Components/SHComponentGroup.cpp index 3ccb7778..2627d9fb 100644 --- a/SHADE_Engine/src/ECS_Base/Components/SHComponentGroup.cpp +++ b/SHADE_Engine/src/ECS_Base/Components/SHComponentGroup.cpp @@ -14,7 +14,7 @@ #include "SHpch.h" #include "SHComponentGroup.h" -#include "../System/SHComponentManager.h" +#include "../Managers/SHComponentManager.h" namespace SHADE diff --git a/SHADE_Engine/src/ECS_Base/Components/SHComponentGroup.h b/SHADE_Engine/src/ECS_Base/Components/SHComponentGroup.h index 3f67aff0..2b20ec13 100644 --- a/SHADE_Engine/src/ECS_Base/Components/SHComponentGroup.h +++ b/SHADE_Engine/src/ECS_Base/Components/SHComponentGroup.h @@ -12,9 +12,7 @@ consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ - -#ifndef SH_COMPONENT_GROUP -#define SH_COMPONENT_GROUP +#pragma once #include "../SHECSMacros.h" #include "../General/SHFamily.h" @@ -180,6 +178,3 @@ namespace SHADE }; } - - -#endif diff --git a/SHADE_Engine/src/ECS_Base/Entity/SHEntity.cpp b/SHADE_Engine/src/ECS_Base/Entity/SHEntity.cpp index edf29ec7..2683a6e9 100644 --- a/SHADE_Engine/src/ECS_Base/Entity/SHEntity.cpp +++ b/SHADE_Engine/src/ECS_Base/Entity/SHEntity.cpp @@ -9,9 +9,9 @@ *********************************************************************/ #include "SHpch.h" #include "SHEntity.h" -#include "../System/SHEntityManager.h" +#include "../Managers/SHEntityManager.h" //#include "Scene/SHSceneGraph.h" -#include "../System/SHComponentManager.h" +#include "../Managers/SHComponentManager.h" namespace SHADE { @@ -39,6 +39,10 @@ namespace SHADE SHComponentManager::SetActive(entityID, active); } + bool SHEntity::GetActive(void) const noexcept + { + return isActive; + } void SHEntity::SetParent(SHEntity* newParent) noexcept @@ -53,20 +57,20 @@ namespace SHADE //TODO } - SHEntity* SHEntity::GetParent() noexcept + SHEntity* SHEntity::GetParent()const noexcept { //TODO return nullptr; } - std::vectorconst& SHEntity::GetChildren() noexcept + std::vectorconst& SHEntity::GetChildren()const noexcept { //TODO return std::vector{}; } - std::vectorconst& SHEntity::GetChildrenID() noexcept + std::vectorconst& SHEntity::GetChildrenID()const noexcept { return std::vector{}; } diff --git a/SHADE_Engine/src/ECS_Base/Entity/SHEntity.h b/SHADE_Engine/src/ECS_Base/Entity/SHEntity.h index 9077b0b9..e499e260 100644 --- a/SHADE_Engine/src/ECS_Base/Entity/SHEntity.h +++ b/SHADE_Engine/src/ECS_Base/Entity/SHEntity.h @@ -8,12 +8,11 @@ consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ -#ifndef SH_ENTITY_H -#define SH_ENTITY_H +#pragma once #include "../SHECSMacros.h" #include "../Components/SHComponent.h" -#include "../System/SHComponentManager.h" +#include "../Managers/SHComponentManager.h" //#include "../../Scene/SHSceneNode.h" #include "SH_API.h" @@ -64,7 +63,7 @@ namespace SHADE * Returns nullptr if the entity does not have such Component. ***************************************************************************/ template - std::enable_if_t, T*> GetComponent() noexcept + std::enable_if_t, T*> GetComponent()const noexcept { return SHComponentManager::GetComponent_s(entityID); @@ -92,6 +91,7 @@ namespace SHADE ***************************************************************************/ virtual void SetActive(bool active) noexcept; + bool GetActive(void)const noexcept; /************************************************************************** @@ -125,7 +125,7 @@ namespace SHADE * Returns a pointer to the parent entity. * Returns a nullptr if the parent node is the root node. ***************************************************************************/ - SHEntity* GetParent() noexcept; + SHEntity* GetParent()const noexcept; /************************************************************************** @@ -134,7 +134,7 @@ namespace SHADE * \return * Return a vector of SHEntity pointers of the children belonging to this entity. ***************************************************************************/ - std::vectorconst& GetChildren() noexcept; + std::vectorconst& GetChildren()const noexcept; /************************************************************************** * \brief @@ -142,11 +142,13 @@ namespace SHADE * \return * return a vector of EntityID of the children belonging to this entity. ***************************************************************************/ - std::vectorconst& GetChildrenID() noexcept; - + std::vectorconst& GetChildrenID()const noexcept; + //Name of the entity. This name is non-unique and only used for the editor. std::string name; - bool isActive; + + + private: @@ -157,8 +159,10 @@ namespace SHADE EntityID entityID; + //Entity active state. This should only be set using the SetActive function which will + //set the active state of all components of this entity. + bool isActive; + + }; } - - -#endif diff --git a/SHADE_Engine/src/ECS_Base/General/SHFamily.h b/SHADE_Engine/src/ECS_Base/General/SHFamily.h index f97bbe0e..5815703f 100644 --- a/SHADE_Engine/src/ECS_Base/General/SHFamily.h +++ b/SHADE_Engine/src/ECS_Base/General/SHFamily.h @@ -11,8 +11,7 @@ consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ -#ifndef SH_FAMILY_H -#define SH_FAMILY_H +#pragma once #include "../SHECSMacros.h" @@ -81,8 +80,4 @@ namespace SHADE template ComponentTypeID SHFamilyID::currentID = 0; -} - - - -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/General/SHHandleGenerator.h b/SHADE_Engine/src/ECS_Base/General/SHHandleGenerator.h index 48ae2132..7c68f66d 100644 --- a/SHADE_Engine/src/ECS_Base/General/SHHandleGenerator.h +++ b/SHADE_Engine/src/ECS_Base/General/SHHandleGenerator.h @@ -11,8 +11,7 @@ or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ -#ifndef SH_HANDLE_GENERATOR_H -#define SH_HANDLE_GENERATOR_H +#pragma once #include #include @@ -299,7 +298,4 @@ namespace SHADE typedef SHHandleGenerator EntityHandleGenerator; -} - - -#endif +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/General/SHSparseBase.h b/SHADE_Engine/src/ECS_Base/General/SHSparseBase.h index 2deebe74..913fca5a 100644 --- a/SHADE_Engine/src/ECS_Base/General/SHSparseBase.h +++ b/SHADE_Engine/src/ECS_Base/General/SHSparseBase.h @@ -10,8 +10,7 @@ consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ -#ifndef SH_SPARSE_BASE_H -#define SH_SPARSE_BASE_H +#pragma once #include "../SHECSMacros.h" @@ -44,7 +43,4 @@ namespace SHADE }; -} - - -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/General/SHSparseSet.h b/SHADE_Engine/src/ECS_Base/General/SHSparseSet.h index 3473eb37..8e096a37 100644 --- a/SHADE_Engine/src/ECS_Base/General/SHSparseSet.h +++ b/SHADE_Engine/src/ECS_Base/General/SHSparseSet.h @@ -9,8 +9,7 @@ or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ -#ifndef SH_SPARSE_SET_H -#define SH_SPARSE_SET_H +#pragma once #include "../SHECSMacros.h" #include "../General/SHSparseBase.h" @@ -351,6 +350,4 @@ namespace SHADE } }; -} - -#endif +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/General/SHSparseSetContainer.h b/SHADE_Engine/src/ECS_Base/General/SHSparseSetContainer.h index 8698d1f5..8f8814f6 100644 --- a/SHADE_Engine/src/ECS_Base/General/SHSparseSetContainer.h +++ b/SHADE_Engine/src/ECS_Base/General/SHSparseSetContainer.h @@ -10,8 +10,7 @@ consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ -#ifndef SH_SPARSE_SET_CONTAINER_H -#define SH_SPARSE_SET_CONTAINER_H +#pragma once #include "SHSparseSet.h" #include "SHFamily.h" @@ -243,6 +242,3 @@ namespace SHADE }; } - - -#endif diff --git a/SHADE_Engine/src/ECS_Base/System/SHComponentManager.cpp b/SHADE_Engine/src/ECS_Base/Managers/SHComponentManager.cpp similarity index 100% rename from SHADE_Engine/src/ECS_Base/System/SHComponentManager.cpp rename to SHADE_Engine/src/ECS_Base/Managers/SHComponentManager.cpp diff --git a/SHADE_Engine/src/ECS_Base/System/SHComponentManager.h b/SHADE_Engine/src/ECS_Base/Managers/SHComponentManager.h similarity index 95% rename from SHADE_Engine/src/ECS_Base/System/SHComponentManager.h rename to SHADE_Engine/src/ECS_Base/Managers/SHComponentManager.h index 75db35d5..20720760 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHComponentManager.h +++ b/SHADE_Engine/src/ECS_Base/Managers/SHComponentManager.h @@ -12,8 +12,7 @@ consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ -#ifndef SH_ENGINE_H -#define SH_ENGINE_H +#pragma once #include "../General/SHSparseSetContainer.h" #include "../Components/SHComponent.h" @@ -26,6 +25,8 @@ namespace SHADE { + typedef SHFamilyID ComponentFamily; + class SH_API SHComponentManager { private: @@ -37,6 +38,8 @@ namespace SHADE friend struct SHSceneNode; + + /************************************************************************** @@ -226,7 +229,7 @@ namespace SHADE * \return * none ***************************************************************************/ - static void AddComponent(EntityID entityID, uint32_t componentTypeID) noexcept + static void AddComponent(EntityID entityID, ComponentTypeID componentTypeID) noexcept { componentSet.GetSparseSet_ID(componentTypeID)->Add(EntityHandleGenerator::GetIndex(entityID)); @@ -278,7 +281,7 @@ namespace SHADE * \return bool * True if the entity has a component of specified type. ***************************************************************************/ - static bool HasComponent_ID(EntityID entityID, uint32_t componentTypeID) noexcept; + static bool HasComponent_ID(EntityID entityID, ComponentTypeID componentTypeID) noexcept; /*!************************************************************************* @@ -363,7 +366,7 @@ namespace SHADE * \return * ***************************************************************************/ - static void SwapInDenseByIndexHash_ID(EntityIndex index, EntityID hash, uint32_t componentTypeID) noexcept; + static void SwapInDenseByIndexHash_ID(EntityIndex index, EntityID hash, ComponentTypeID componentTypeID) noexcept; @@ -386,7 +389,7 @@ namespace SHADE * \return * The number of components in the component sparse set. ***************************************************************************/ - static EntityIndex ComponentCount_ID(uint32_t componentTypeID) + static EntityIndex ComponentCount_ID(ComponentTypeID componentTypeID) { return componentSet.GetSparseSet_ID(componentTypeID)->Count(); } @@ -403,9 +406,9 @@ namespace SHADE static void SetActive(EntityID entityID, bool active) noexcept; template - static std::enable_if_t<(... && std::is_base_of_v), uint32_t> CreateComponentGroup(uint32_t numOwningComponents) + static std::enable_if_t<(... && std::is_base_of_v), uint32_t> CreateComponentGroup(ComponentTypeID numOwningComponents) { - std::vector templateIDs{ (SHFamilyID::GetID())... }; + std::vector templateIDs{ (ComponentFamily::GetID())... }; for (auto& g : componentGroups) { @@ -422,11 +425,11 @@ namespace SHADE } SHComponentGroup grp; - for (uint32_t i = 0; i < numOwningComponents; ++i) + for (ComponentTypeID i = 0; i < numOwningComponents; ++i) { grp.ownedComponentTypes.push_back(templateIDs[i]); } - for (uint32_t i = 0; i < templateIDs.size(); ++i) + for (ComponentTypeID i = 0; i < templateIDs.size(); ++i) { grp.componentTypeIDs.push_back(templateIDs[i]); } @@ -472,7 +475,4 @@ namespace SHADE -} - - -#endif +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/System/SHEntityManager.cpp b/SHADE_Engine/src/ECS_Base/Managers/SHEntityManager.cpp similarity index 77% rename from SHADE_Engine/src/ECS_Base/System/SHEntityManager.cpp rename to SHADE_Engine/src/ECS_Base/Managers/SHEntityManager.cpp index 4aa38112..240c0b32 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHEntityManager.cpp +++ b/SHADE_Engine/src/ECS_Base/Managers/SHEntityManager.cpp @@ -52,63 +52,20 @@ namespace SHADE return entityHandle.GetIndex(entityID); } - EntityID SHEntityManager::CreateEntity(std::vectorconst& componentTypeIDs, std::string const& name,EntityID parentEID) - { - EntityID eID = entityHandle.GetNewHandle(); - EntityIndex eIndex = entityHandle.GetIndex(eID); - if (eIndex > entityVec.size()) - { - assert("FATAL ERROR: EntityIndex out of range in Entity Creation"); - } - else if (eIndex == entityVec.size()) - { - entityVec.emplace_back(std::make_unique()); - } - else - { - if (!entityVec[eIndex]) - { - //There is still an entity stored there.Something went wrong - assert("FATAL ERROR: Entity Creation error. Entity Index Conflict"); - } - - //Reset it to a newly constructed entity - entityVec[eIndex].reset(new SHEntity()); - } - - - entityVec[eIndex]->entityID = eID; - entityVec[eIndex]->name = name; - for (auto& id : componentTypeIDs) - { - SHComponentManager::AddComponent(eID, id); - } - - //(SHComponentManager::AddComponent(eID), ...); - /*if (entityHandle.IsValid(parentEID) == false) - { - entityVec[eIndex]->sceneNode.ConnectToRoot(); - } - else - { - entityVec[eIndex]->SetParent(parentEID); - }*/ - - - //TODO Link to Scene graph. - - return eID; - - } - EntityID SHEntityManager::CreateEntity(std::vectorconst& componentTypeIDs, EntityID desiredEID, std::string const& name, EntityID parentEID) { - EntityID eID ; - - if (entityHandle.ClaimHandle(desiredEID) == true) - eID = desiredEID; - else + EntityID eID; + if (desiredEID == MAX_EID) + { eID = entityHandle.GetNewHandle(); + } + else + { + if (entityHandle.ClaimHandle(desiredEID) == true) + eID = desiredEID; + else + eID = entityHandle.GetNewHandle(); + } EntityIndex eIndex = entityHandle.GetIndex(eID); diff --git a/SHADE_Engine/src/ECS_Base/System/SHEntityManager.h b/SHADE_Engine/src/ECS_Base/Managers/SHEntityManager.h similarity index 72% rename from SHADE_Engine/src/ECS_Base/System/SHEntityManager.h rename to SHADE_Engine/src/ECS_Base/Managers/SHEntityManager.h index 802ef75d..2d8a3ce5 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHEntityManager.h +++ b/SHADE_Engine/src/ECS_Base/Managers/SHEntityManager.h @@ -12,9 +12,7 @@ or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ - -#ifndef SH_ENTITY_MANAGER_H -#define SH_ENTITY_MANAGER_H +#pragma once #include #include @@ -82,55 +80,21 @@ namespace SHADE * EntityID of the new Entity ***************************************************************************/ template - static std::enable_if_t<(... && std::is_base_of_v), EntityID> CreateEntity(std::string const& name = "Default", EntityID parentEID = MAX_EID) - { - EntityID eID = entityHandle.GetNewHandle(); - EntityIndex eIndex = entityHandle.GetIndex(eID); - if (eIndex > entityVec.size()) - { - assert("FATAL ERROR: EntityIndex out of range in Entity Creation"); - } - else if (eIndex == entityVec.size()) - { - entityVec.emplace_back(std::make_unique()); - } - else - { - if (!entityVec[eIndex]) - { - //There is still an entity stored there.Something went wrong - assert("FATAL ERROR: Entity Creation error. Entity Index Conflict"); - } - - //Reset it to a newly constructed entity - entityVec[eIndex].reset(new SHEntity()); - } - entityVec[eIndex]->entityID = eID; - entityVec[eIndex]->name = name; - (SHComponentManager::AddComponent(eID),...); - - /*if (entityHandle.IsValid(parentEID) == false) - { - entityVec[eIndex]->sceneNode.ConnectToRoot(); - } - else - { - entityVec[eIndex]->SetParent(parentEID); - }*/ - - //TODO Link up with Scene graph - - return eID; - } - - template - static std::enable_if_t<(... && std::is_base_of_v), EntityID> CreateEntity(EntityID desiredEID, std::string const& name = "Default", EntityID parentEID = MAX_EID) + static std::enable_if_t<(... && std::is_base_of_v), EntityID> CreateEntity(EntityID desiredEID = MAX_EID, std::string const& name = "Default", EntityID parentEID = MAX_EID) { EntityID eID; - if (entityHandle.ClaimHandle(desiredEID) == true) - eID = desiredEID; - else + if (desiredEID == MAX_EID) + { eID = entityHandle.GetNewHandle(); + } + else + { + if (entityHandle.ClaimHandle(desiredEID) == true) + eID = desiredEID; + else + eID = entityHandle.GetNewHandle(); + } + EntityIndex eIndex = entityHandle.GetIndex(eID); if (eIndex > entityVec.size()) { @@ -180,21 +144,6 @@ namespace SHADE - /************************************************************************** - * \brief - * Create Entity using a vector of ComponentTypeIDs. - * \param componentTypeIDs - * Vector of ComponentTypeIDs. This assumes that CreateSparseSet is called - * for these ComponentTypes. - * \param name - * Name of the Entity (this is not unique) - * \param parentEID - * The entity ID of the parent. This does not call UpdateHierarchy hence - * the parent of the entity is not updated until UpdateHierarchy is called. - * \return - * EntityID of the new Entity - ***************************************************************************/ - static EntityID CreateEntity(std::vectorconst& componentTypeIDs,std::string const& name = "Default", EntityID parentEID = MAX_EID); /************************************************************************** * \brief @@ -210,7 +159,7 @@ namespace SHADE * \return * EntityID of the new Entity ***************************************************************************/ - static EntityID CreateEntity(std::vectorconst& componentTypeIDs, EntityID desiredEID, std::string const& name = "Default", EntityID parentEID = MAX_EID); + static EntityID CreateEntity(std::vectorconst& componentTypeIDs, EntityID desiredEID = MAX_EID, std::string const& name = "Default", EntityID parentEID = MAX_EID); /************************************************************************** * \brief @@ -248,7 +197,3 @@ namespace SHADE } - - - -#endif diff --git a/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.cpp b/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.cpp new file mode 100644 index 00000000..551233db --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.cpp @@ -0,0 +1,77 @@ +/********************************************************************* + * \file SHSystemManager.cpp + * \author Daniel Chua Yee Chen + * \brief Implementation for the SHSystemManager class. + * SHSystemManager is the interface class where users of the engine create + * the systems that gives the components their functionality. This also + * ensures that the Init and Exit functions are ran at the appropriate time + * + * \copyright Copyright (c) 2021 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 "SHSystemManager.h" +#include + +#include +#include +#include + +namespace SHADE +{ + SHSystemManager::SystemContainer SHSystemManager::systemContainer; + SHSystemManager::SystemRoutineContainer SHSystemManager::systemRoutineContainer; + + void SHSystemManager::Init() noexcept + { + for (auto& system : systemContainer) + { + system.second->Init(); +#ifdef _DEBUG + std::cout << system.first << " Init" << std::endl; +#endif + } + } + + void SHSystemManager::RunRoutines(bool editorPause, double deltaTime) noexcept + { + for (auto& routine : systemRoutineContainer) + { + if (editorPause == true) + { + if (routine.get()->IsRunInEditorPause) + { + std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); + routine.get()->Execute(deltaTime); + std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); + routine.get()->stats.executionTime = std::chrono::duration(end - start).count(); + } + } + else + { + std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); + routine.get()->Execute(deltaTime); + std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); + routine.get()->stats.executionTime = std::chrono::duration(end - start).count(); + } + } + } + + + void SHSystemManager::Exit() noexcept + { + systemRoutineContainer.clear(); + + for (SystemContainer::reverse_iterator it = systemContainer.rbegin(); it != systemContainer.rend(); ++it) + { + (*it).second->Exit(); + //delete system.second; + } + + systemContainer.clear(); + + } + + +} diff --git a/SHADE_Engine/src/ECS_Base/System/SHSystemManager.h b/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.h similarity index 55% rename from SHADE_Engine/src/ECS_Base/System/SHSystemManager.h rename to SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.h index d5a4866d..f92f6635 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHSystemManager.h +++ b/SHADE_Engine/src/ECS_Base/Managers/SHSystemManager.h @@ -10,29 +10,33 @@ consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ - -#ifndef SH_SYSTEM_MANAGER_H -#define SH_SYSTEM_MANAGER_H +#pragma once -#include +#include #include #include #include +#include #include "../System/SHSystem.h" - +#include "../General/SHFamily.h" +#include "../System/SHSystemRoutine.h" +#include "SH_API.h" namespace SHADE { - class SHSystemManager + + typedef SHFamilyID SystemFamily; + + class SH_API SHSystemManager { //type definition for the container we use to store our system - using SystemContainer = std::unordered_map>; - + using SystemContainer = std::map>; + using SystemRoutineContainer = std::vector>; private: static SystemContainer systemContainer; - + static SystemRoutineContainer systemRoutineContainer; public: /*!************************************************************************* @@ -43,45 +47,79 @@ namespace SHADE ~SHSystemManager() = delete; /************************************************************************** - * \brief + * \brief * Create a system of type T and map it to a name. * throws an error if a system with the same name already exists. * \param name * name of the system - * \return + * \return * none ***************************************************************************/ template - static std::enable_if_t, void> CreateSystem(std::string const& name) + static std::enable_if_t, SystemID> CreateSystem() { - if (systemContainer.find(name) != systemContainer.end()) + SystemTypeID typeID = SystemFamily::GetID(); + + SystemVersionID version = 0; + SystemID id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID; + while (systemContainer.find(id) != systemContainer.end()) { - assert("System Creation Error: System with the same name already exist."); + ++version; + id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID; } + systemContainer.emplace(id, std::make_unique()); + systemContainer[id].get()->systemID = id; - systemContainer.emplace(name, std::make_unique()); - + return id; } /************************************************************************** - * \brief + * \brief * Get a pointer to the System with a specified name. * \param name * Name of the system in the map - * \return + * \return * Base System pointer. ***************************************************************************/ - static SHSystem* GetSystem(std::string name); + template + static std::enable_if_t, T*> GetSystem(SystemVersionID version = 0) + { + SystemTypeID typeID = SystemFamily::GetID(); + + SystemID id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID; + + if (systemContainer.find(id) == systemContainer.end()) + { + std::cout << "System Manager error: System Version " << version << " does not exit." << std::endl; + return nullptr; + } + + return (T*)systemContainer.find(id)->second.get(); + } /************************************************************************** - * \brief + * \brief * Call the Init function of all systems. - * \return + * \return * none ***************************************************************************/ static void Init() noexcept; + static void RunRoutines(bool editorPause, double deltaTime) noexcept; + + template + static void RegisterRoutine(SystemVersionID version = 0) noexcept + { + SHSystem* system = GetSystem(version); + if (system == nullptr) + return; + systemRoutineContainer.emplace_back(std::make_unique()); + systemRoutineContainer.back().get()->system = system; + + } + + /************************************************************************** * \brief * Call the Exit function of all systems. @@ -95,8 +133,4 @@ namespace SHADE }; -} - - - -#endif +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/SHECSMacros.h b/SHADE_Engine/src/ECS_Base/SHECSMacros.h index 5243e20f..02615ca4 100644 --- a/SHADE_Engine/src/ECS_Base/SHECSMacros.h +++ b/SHADE_Engine/src/ECS_Base/SHECSMacros.h @@ -9,6 +9,10 @@ typedef uint32_t EntityID; typedef uint16_t EntityIndex; typedef uint32_t ComponentTypeID; +typedef uint32_t SystemTypeID; +typedef uint32_t SystemVersionID; +typedef uint64_t SystemID; + const EntityIndex MAX_EID = 51000; diff --git a/SHADE_Engine/src/ECS_Base/System/SHFixedSystemRoutine.cpp b/SHADE_Engine/src/ECS_Base/System/SHFixedSystemRoutine.cpp new file mode 100644 index 00000000..fa34a5cf --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/System/SHFixedSystemRoutine.cpp @@ -0,0 +1,21 @@ +#include "SHpch.h" +#include "SHFixedSystemRoutine.h" +#include "../SHECSMacros.h" + +namespace SHADE +{ + + void SHFixedSystemRoutine::Execute(double dt) noexcept + { + accumulatedTime += dt; + int counter = 0; + while (accumulatedTime >= fixedTimeStep) + { + ++counter; + accumulatedTime -= fixedTimeStep; + FixedExecute(fixedTimeStep); + } + stats.numSteps = counter; + } + +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/System/SHFixedSystemRoutine.h b/SHADE_Engine/src/ECS_Base/System/SHFixedSystemRoutine.h new file mode 100644 index 00000000..d9a2b510 --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/System/SHFixedSystemRoutine.h @@ -0,0 +1,31 @@ +#pragma once + + +#include "SHSystemRoutine.h" +#define DEFAULT_FIXED_STEP 1.0/60.0 + +namespace SHADE +{ + class SHFixedSystemRoutine: public SHSystemRoutine + { + private: + double accumulatedTime; + double fixedTimeStep; + + protected: + SHFixedSystemRoutine(double timeStep = DEFAULT_FIXED_STEP, std::string routineName = "Default Fixed Routine Name", bool editorPause = false) + :SHSystemRoutine(routineName, editorPause), accumulatedTime(0.0), fixedTimeStep(timeStep){} + + + + public: + ~SHFixedSystemRoutine() = default; + + virtual void Execute(double dt) noexcept; + + virtual void FixedExecute(double dt) noexcept {}; + + }; + + +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/System/SHRoutineStats.h b/SHADE_Engine/src/ECS_Base/System/SHRoutineStats.h new file mode 100644 index 00000000..513358ee --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/System/SHRoutineStats.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +namespace SHADE +{ + struct SHRoutineStats + { + SHRoutineStats(std::string name) + :name(name) + { + } + std::string name; + double executionTime; + int numSteps{1}; + + //friend std::ostream& operator<<(std::ostream& os, const SHRoutineStats& stats); + }; + + //std::ostream& operator<<(std::ostream& os, const SHRoutineStats& stats) + //{ + // os << stats.name << ": Execution Time: " << stats.executionTime << " Number of steps: " << stats.numSteps << std::endl; + // return os; + //} + + +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/System/SHSystem.h b/SHADE_Engine/src/ECS_Base/System/SHSystem.h index 1a304605..19b16f72 100644 --- a/SHADE_Engine/src/ECS_Base/System/SHSystem.h +++ b/SHADE_Engine/src/ECS_Base/System/SHSystem.h @@ -8,19 +8,29 @@ consent of DigiPen Institute of Technology is prohibited. *********************************************************************/ -#ifndef SH_SYSTEM_H -#define SH_SYSTEM_H +#pragma once + +#include "../SHECSMacros.h" namespace SHADE { + + class SHSystemManager; + class SHSystem { + private: + SystemID systemID; + protected: /*!************************************************************************* * \brief * Protected default constructor for SHSytem class ***************************************************************************/ SHSystem()= default; + + + public: /*!************************************************************************* @@ -35,13 +45,13 @@ namespace SHADE ***************************************************************************/ virtual void Init() = 0; - /*!************************************************************************* - * \brief - * Pure virtual Run function. Derived class must implement this - * \param dt - * Delta time - ***************************************************************************/ - virtual void Run(float dt) = 0; + ///*!************************************************************************* + // * \brief + // * Pure virtual Run function. Derived class must implement this + // * \param dt + // * Delta time + //***************************************************************************/ + //virtual void Run(float dt) = 0; /*!************************************************************************* * \brief @@ -49,7 +59,14 @@ namespace SHADE ***************************************************************************/ virtual void Exit() = 0; - }; -} + friend class SHSystemManager; -#endif \ No newline at end of file + inline SystemID GetSystemID(void) const noexcept { return systemID; } + inline SystemVersionID GetSystemVersion(void) const noexcept { return static_cast(systemID >> sizeof(SystemVersionID) * CHAR_BIT); } + + + }; + + + +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/System/SHSystemManager.cpp b/SHADE_Engine/src/ECS_Base/System/SHSystemManager.cpp deleted file mode 100644 index 67d6f781..00000000 --- a/SHADE_Engine/src/ECS_Base/System/SHSystemManager.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/********************************************************************* - * \file SHSystemManager.cpp - * \author Daniel Chua Yee Chen - * \brief Implementation for the SHSystemManager class. - * SHSystemManager is the interface class where users of the engine create - * the systems that gives the components their functionality. This also - * ensures that the Init and Exit functions are ran at the appropriate time - * - * \copyright Copyright (c) 2021 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 "SHSystemManager.h" -#include - -namespace SHADE -{ - SHSystemManager::SystemContainer SHSystemManager::systemContainer; - - - SHSystem* SHSystemManager::GetSystem(std::string name) - { - if (systemContainer.find(name) == systemContainer.end()) - { - assert("Get System Error: No system with such name exist."); - return nullptr; - } - - return systemContainer.find(name)->second.get(); - } - - void SHSystemManager::Init() noexcept - { - for (auto& system : systemContainer) - { - system.second->Init(); -#ifdef _DEBUG - std::cout << system.first << " Init" << std::endl; -#endif - } - } - - void SHSystemManager::Exit() noexcept - { - for (auto& system : systemContainer) - { - system.second->Exit(); - //delete system.second; - } - - systemContainer.clear(); - - } - - -} diff --git a/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.cpp b/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.cpp new file mode 100644 index 00000000..73157e8b --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.cpp @@ -0,0 +1,23 @@ +#include "SHpch.h" +#include "SHSystemRoutine.h" + + +namespace SHADE +{ + + SHSystem* SHSystemRoutine::GetSystem() const noexcept + { + return system; + } + + std::string const SHSystemRoutine::GetName()const noexcept + { + return name; + } + + SHRoutineStats const& SHSystemRoutine::GetStats()const noexcept + { + return stats; + } + +} diff --git a/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.h b/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.h new file mode 100644 index 00000000..cdb62438 --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/System/SHSystemRoutine.h @@ -0,0 +1,53 @@ + + + +#pragma once + +#include "../SHECSMacros.h" +#include "SHRoutineStats.h" +#include "SHSystem.h" +#include + + +namespace SHADE +{ + + class SHSystemManager; + + + class SHSystemRoutine + { + friend class SHSystemManager; + protected: + + SHSystemRoutine(std::string routineName = "Default Routine Name", bool editorPause = false) + :system(nullptr), name(routineName), stats(routineName),IsRunInEditorPause(editorPause){}; + + + SHSystem* system; + std::string name; + SHRoutineStats stats; + + //Whether or not this routine should run when the editor is still in pause + bool IsRunInEditorPause; + + + public: + ~SHSystemRoutine() = default; + + + SHSystem* GetSystem()const noexcept; + std::string const GetName() const noexcept; + SHRoutineStats const& GetStats()const noexcept; + + virtual void Execute(double dt) noexcept {}; + }; + + + + +} + + + + diff --git a/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.cpp b/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.cpp new file mode 100644 index 00000000..c9d8477b --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.cpp @@ -0,0 +1,181 @@ +#include "SHpch.h" +#include "SHECSUnitTest.h" +#include "../Managers/SHComponentManager.h" +#include "../Managers/SHEntityManager.h" +#include "../Managers/SHSystemManager.h" +#include "SHTestComponents.h" +#include "SHTestSystems.h" +#include "Tools/SHLogger.h" + + + +namespace SHADE +{ + void SHECSUnitTest::TestAll(void) noexcept + { + TestBasicEntityCreate(); + TestEntityCreateTemplate(); + TestEntityDestroy(); + TestSystemRoutine(); + } + + + void SHECSUnitTest::TestBasicEntityCreate(void) noexcept + { + + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + + SHLOG_INFO("Test for add and remove component") + + EntityID id1 = SHEntityManager::CreateEntity(); + EntityID id2 = SHEntityManager::CreateEntity(); + EntityID id3 = SHEntityManager::CreateEntity(); + + + SHComponentManager::AddComponent(id1); + } + + + void SHECSUnitTest::TestEntityCreateTemplate(void) noexcept + { + std::cout << "\nTest2" << std::endl; + //Test entity Creation. + + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + + + + for (size_t i = 0; i < 10000; ++i) + { + switch (i % 3) + { + case 0: + { + SHEntityManager::CreateEntity(); + }break; + case 1: + { + SHEntityManager::CreateEntity(); + }break; + + case 2: + { + SHEntityManager::CreateEntity(); + }break; + default: + break; + } + + + } + + + auto& denseA = SHComponentManager::GetDense(); + auto& denseB = SHComponentManager::GetDense(); + auto& denseC = SHComponentManager::GetDense(); + + std::cout << "Test Entity Creation" << std::endl; + std::cout << "dense A size: " << denseA.size() << ((denseA.size() == 10000) ? " Success" : " Failure") << std::endl; + std::cout << "dense B size: " << denseB.size() << ((denseB.size() == 3334) ? " Success" : " Failure") << std::endl; + std::cout << "dense C size: " << denseC.size() << ((denseC.size() == 3333) ? " Success" : " Failure") << std::endl; + std::cout << "Number of entities: " << SHEntityManager::GetEntityCount() << (SHEntityManager::GetEntityCount() == 10000 ? " Success" : " Failure") << std::endl; + + SHEntityManager::DestroyAllEntity(); + std::cout << std::endl << "Test Destroy All Entity" << std::endl; + std::cout << "dense A size: " << denseA.size() << ((denseA.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "dense B size: " << denseB.size() << ((denseB.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "dense C size: " << denseC.size() << ((denseC.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "Number of entities: " << SHEntityManager::GetEntityCount() << (SHEntityManager::GetEntityCount() == 0 ? " Success" : " Failure") << std::endl; + + + } + + + void SHECSUnitTest::TestEntityDestroy(void) noexcept + { + std::cout << "\nTest3" << std::endl; + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + SHComponentManager::CreateComponentSparseSet(); + + + + for (size_t i = 0; i < 10000; ++i) + { + switch (i % 3) + { + case 0: + { + SHEntityManager::CreateEntity(); + }break; + case 1: + { + SHEntityManager::CreateEntity(); + }break; + + case 2: + { + SHEntityManager::CreateEntity(); + }break; + default: + break; + } + + + } + + SHEntityManager::DestroyEntity(5000); + SHEntityManager::DestroyEntity(5001); + + + + + auto& denseA = SHComponentManager::GetDense(); + auto& denseB = SHComponentManager::GetDense(); + auto& denseC = SHComponentManager::GetDense(); + + + std::cout << "Test Entity Deletion" << std::endl; + std::cout << "dense A size: " << denseA.size() << ((denseA.size() == 9998) ? " Success" : " Failure") << std::endl; + std::cout << "dense B size: " << denseB.size() << ((denseB.size() == 3333) ? " Success" : " Failure") << std::endl; + std::cout << "dense C size: " << denseC.size() << ((denseC.size() == 3333) ? " Success" : " Failure") << std::endl; + std::cout << "Number of entities: " << SHEntityManager::GetEntityCount() << (SHEntityManager::GetEntityCount() == 9998 ? " Success" : " Failure") << std::endl; + + + std::cout << std::endl << "Test Entity Recreation" << std::endl; + EntityID id = SHEntityManager::CreateEntity(); + std::cout << "dense A size: " << denseA.size() << ((denseA.size() == 9998) ? " Success" : " Failure") << std::endl; + std::cout << "dense B size: " << denseB.size() << ((denseB.size() == 3333) ? " Success" : " Failure") << std::endl; + std::cout << "dense C size: " << denseC.size() << ((denseC.size() == 3334) ? " Success" : " Failure") << std::endl; + std::cout << "Entity ID: " << id << " EntityIndex: " << EntityHandleGenerator::GetIndex(id) << (EntityHandleGenerator::GetIndex(id) == 5001 ? " Success" : " Failure") << std::endl; + std::cout << "Number of entities: " << SHEntityManager::GetEntityCount() << (SHEntityManager::GetEntityCount() == 9999 ? " Success" : " Failure") << std::endl; + + + SHEntityManager::DestroyAllEntity(); + std::cout << std::endl << "Check Destroy All Entity" << std::endl; + std::cout << "dense A size: " << denseA.size() << ((denseA.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "dense B size: " << denseB.size() << ((denseB.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "dense C size: " << denseC.size() << ((denseC.size() == 0) ? " Success" : " Failure") << std::endl; + std::cout << "Number of entities: " << SHEntityManager::GetEntityCount() << (SHEntityManager::GetEntityCount() == 0 ? " Success" : " Failure") << std::endl; + + } + + void SHECSUnitTest::TestSystemRoutine(void) noexcept + { + SHSystemManager::CreateSystem(); + SHSystemManager::CreateSystem(); + + + SHSystemManager::RegisterRoutine(1); + + SHSystemManager::RunRoutines(false, 1.0 / 120.0); + + SHSystemManager::Exit(); + } + + +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.h b/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.h new file mode 100644 index 00000000..938ba865 --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/UnitTesting/SHECSUnitTest.h @@ -0,0 +1,22 @@ +#pragma once + +namespace SHADE +{ + class SHECSUnitTest + { + public: + SHECSUnitTest() = delete; + ~SHECSUnitTest() = delete; + + static void TestBasicEntityCreate(void) noexcept; + static void TestEntityCreateTemplate(void) noexcept; + static void TestEntityDestroy(void) noexcept; + static void TestSystemRoutine(void) noexcept; + + static void TestAll(void) noexcept; + + + + + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestComponents.h b/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestComponents.h new file mode 100644 index 00000000..e2e53d6b --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestComponents.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../Components/SHComponent.h" + +namespace SHADE +{ + + class SHComponent_A :public SHComponent + { + public: + int value{}; + + }; + + + class SHComponent_B :public SHComponent + { + public: + float x{}; + float y{}; + float z{}; + }; + + class SHComponent_C :public SHComponent + { + public: + std::string value{}; + }; + +} \ No newline at end of file diff --git a/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestSystems.h b/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestSystems.h new file mode 100644 index 00000000..7231b323 --- /dev/null +++ b/SHADE_Engine/src/ECS_Base/UnitTesting/SHTestSystems.h @@ -0,0 +1,40 @@ +#pragma once + + +#include +#include "../System/SHSystem.h" +#include "../System/SHSystemRoutine.h" + +namespace SHADE +{ + + class SHTestSystem : public SHSystem + { + public: + SHTestSystem() {}; + ~SHTestSystem() {}; + + + + std::string test{ "Test system" }; + + void Init() {}; + void Exit() {}; + + class SHTestRoutine : public SHSystemRoutine + { + public: + SHTestRoutine() + :SHSystemRoutine("Test System Routine", false) {} + + + virtual void Execute(double dt) noexcept + { + + std::cout << GetName() << " System Version: " << GetSystem()->GetSystemVersion() << std::endl; + } + }; + + + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp index 4158d3c3..7913574c 100644 --- a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.cpp @@ -33,6 +33,8 @@ namespace SHADE }; cmdBufferHdl->GetVkCommandBuffer().copyBuffer(stagingBuffer, vkBuffer, 1, ©Region); } + + // TODO: Need to destroy staging buffer. Obviously not here but after the command has finished executing. } vk::Buffer SHVkBuffer::GetVkBuffer(void) const noexcept diff --git a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h index 2ad3e4e9..9df1a1d0 100644 --- a/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h +++ b/SHADE_Engine/src/Graphics/Buffers/SHVkBuffer.h @@ -48,7 +48,6 @@ namespace SHADE vk::BufferUsageFlags bufferUsageFlags; //! Reference to the allocator - //VmaAllocator const& vmaAllocator; std::reference_wrapper vmaAllocator; /*-----------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp index 6a307230..f83087dd 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.cpp @@ -76,7 +76,10 @@ namespace SHADE // Check if command buffer is ready to record. if (cmdBufferState != SH_CMD_BUFFER_STATE::INITIAL) { - SHLOG_ERROR("Command buffer not in initial state, cannot begin recording. "); + SHLOG_ERROR("Command buffer not in initial state, cannot begin recording. Command buffer could be: \n" + "- corrupted and in invalid state\n" + "- in executable state\n" + "- in pending state\n"); return; } @@ -182,7 +185,9 @@ namespace SHADE // Check if render area is optimal if (!IsRenderAreaOptimal(renderpassHdl, framebufferExtent, renderPassInfo.renderArea)) + { SHLOG_ERROR("Render area in renderpass begin info is not optimal. See Vulkan vkGetRenderAreaGranularity for details."); + } // Begin the render pass vkCommandBuffer.beginRenderPass (&renderPassInfo, vk::SubpassContents::eInline); @@ -202,6 +207,11 @@ namespace SHADE vkCommandBuffer.endRenderPass(); } + void SHVkCommandBuffer::NextSubpass(void) noexcept + { + vkCommandBuffer.nextSubpass(commandBufferType == SH_CMD_BUFFER_TYPE::PRIMARY ? vk::SubpassContents::eInline : vk::SubpassContents::eSecondaryCommandBuffers); + } + /***************************************************************************/ /*! @@ -406,6 +416,41 @@ namespace SHADE } + + void SHVkCommandBuffer::PipelineBarrier ( + vk::PipelineStageFlags srcStage, + vk::PipelineStageFlags dstStage, + vk::DependencyFlags deps, + std::vector const& memoryBarriers, + std::vector const& bufferMemoryBarriers, + std::vector const& imageMemoryBarriers + ) const noexcept + { + vkCommandBuffer.pipelineBarrier ( + srcStage, + dstStage, + deps, + memoryBarriers, + bufferMemoryBarriers, + imageMemoryBarriers + ); + } + + bool SHVkCommandBuffer::IsReadyToSubmit(void) const noexcept + { + return cmdBufferState == SH_CMD_BUFFER_STATE::EXECUTABLE; + } + + void SHVkCommandBuffer::HandlePostSubmit(void) noexcept + { + SetState(SH_CMD_BUFFER_STATE::PENDING); + } + + //void SHVkCommandBuffer::PipelineBarrier(vk::PipelineStageFlags ) const noexcept + //{ + // //vkCommandBuffer.pipelineBarrier() + //} + /***************************************************************************/ /*! @@ -463,9 +508,7 @@ namespace SHADE { vk::Extent2D granularity = parentPool->GetLogicalDevice()->GetVkLogicalDevice().getRenderAreaGranularity(renderpassHdl->GetVkRenderpass()); - return (renderArea.offset.x % granularity.width == 0 && renderArea.offset.y % granularity.height == 0 && - (renderArea.extent.width % granularity.width || renderArea.offset.x + renderArea.extent.width == framebufferExtent.width) && - (renderArea.extent.height % granularity.height || renderArea.offset.y + renderArea.extent.height == framebufferExtent.height)); + return (renderArea.offset.x % granularity.width == 0 && renderArea.offset.y % granularity.height == 0 && (renderArea.extent.width % granularity.width || renderArea.offset.x + renderArea.extent.width == framebufferExtent.width) && (renderArea.extent.height % granularity.height || renderArea.offset.y + renderArea.extent.height == framebufferExtent.height)); } /***************************************************************************/ @@ -529,6 +572,7 @@ namespace SHADE , usageFlags{} , commandBufferCount{ 0 } , parentPool{commandPool} + , pushConstantData{} { vk::CommandBufferAllocateInfo allocateInfo{}; diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h index 08fc45f7..948092bf 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandBuffer.h @@ -96,11 +96,12 @@ namespace SHADE /*-----------------------------------------------------------------------*/ void Reset(void); - // Begins and Ends + // Begins, Ends and Nexts void BeginRecording (void) noexcept; void EndRecording (void) noexcept; void BeginRenderpass (Handle const& renderpassHdl, Handle const& framebufferHdl, vk::Offset2D offset = {0, 0}, vk::Extent2D extent = {0, 0}) noexcept; void EndRenderpass (void) noexcept; + void NextSubpass (void) noexcept; // Dynamic State void SetviewportScissor (float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX = 0.0f, float vpY = 0.0f, int32_t sX = 0.0f, int32_t sY = 0.0f, float vpMinDepth = 0.0f, float vpMaxDepth = 1.0f) noexcept; @@ -114,6 +115,19 @@ namespace SHADE void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept; void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept; + // memory barriers + void PipelineBarrier ( + vk::PipelineStageFlags srcStage, + vk::PipelineStageFlags dstStage, + vk::DependencyFlags deps, + std::vector const& memoryBarriers, + std::vector const& bufferMemoryBarriers, + std::vector const& imageMemoryBarriers + ) const noexcept; + + bool IsReadyToSubmit (void) const noexcept; + void HandlePostSubmit (void) noexcept; + // Push Constant variable setting template void SetPushConstantVariable(std::string variableName, T const& data) noexcept diff --git a/SHADE_Engine/src/Graphics/Commands/SHVkCommandPool.cpp b/SHADE_Engine/src/Graphics/Commands/SHVkCommandPool.cpp index 5cf4bea4..881ee998 100644 --- a/SHADE_Engine/src/Graphics/Commands/SHVkCommandPool.cpp +++ b/SHADE_Engine/src/Graphics/Commands/SHVkCommandPool.cpp @@ -150,20 +150,19 @@ namespace SHADE logicalDeviceHdl->GetVkLogicalDevice().resetCommandPool(vkCommandPool, vk::CommandPoolResetFlagBits::eReleaseResources); for (auto& primary : primaries) { - if (primary->GetState() != SH_CMD_BUFFER_STATE::PENDING) - primary->SetState(SH_CMD_BUFFER_STATE::INITIAL); - else - SHLOG_ERROR("Primary command buffer in pending state, could not reset. "); + // #NoteToSelf: Since there is no way to set the state of a command buffer back to initial, we just hard set it to initial. Ditto for secondaries. + //if (primary->GetState() != SH_CMD_BUFFER_STATE::PENDING) + primary->SetState(SH_CMD_BUFFER_STATE::INITIAL); + + // From the spec: Any primary command buffer allocated from another VkCommandPool that is in the recording or // executable state and has a secondary command buffer allocated from commandPool recorded into it, // becomes invalid. TODO: Might want to check and throw exception for these conditions after making sure this actually happens using validation layers. } for (auto& secondary : secondaries) { - if (secondary->GetState() != SH_CMD_BUFFER_STATE::PENDING) - secondary->SetState(SH_CMD_BUFFER_STATE::INITIAL); - else - SHLOG_ERROR("Secondary command buffer in pending state, could not reset. "); + //if (secondary->GetState() != SH_CMD_BUFFER_STATE::PENDING) + secondary->SetState(SH_CMD_BUFFER_STATE::INITIAL); // TODO: Ditto from TODO in primary check } diff --git a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp index d63a65f7..0152e6c9 100644 --- a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp +++ b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.cpp @@ -59,7 +59,7 @@ namespace SHADE */ /***************************************************************************/ - void SHVulkanDebugUtil::ReportVkWarning(vk::Result vkResult, std::string_view message, std::source_location const& location /*= std::source_location::current()*/) noexcept + void SHVulkanDebugUtil::ReportVkWarning(vk::Result vkResult, std::string_view message) noexcept { //std::cout << location.file_name() << ": " << location.function_name() << "|" << location.line() << "|" << // location.column() << "|: Warning: " << SHDebugUtil::VkResultToString(vkResult) << " | " << message << std::endl; @@ -88,7 +88,7 @@ namespace SHADE */ /***************************************************************************/ - void SHVulkanDebugUtil::ReportVkError(vk::Result vkResult, std::string_view message, std::source_location const& location /*= std::source_location::current()*/) noexcept + void SHVulkanDebugUtil::ReportVkError(vk::Result vkResult, std::string_view message) noexcept { std::string toLogger = "Vulkan Warning: " + std::string(SHVulkanDebugUtil::VkResultToString(vkResult)) + " | " + std::string(message); @@ -96,7 +96,7 @@ namespace SHADE } - void SHVulkanDebugUtil::ReportVkSuccess(std::string_view message, std::source_location const& location /*= std::source_location::current()*/) noexcept + void SHVulkanDebugUtil::ReportVkSuccess(std::string_view message) noexcept { SHLOGV_INFO(message); } diff --git a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.h b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.h index 7bf583bb..af4ca3ef 100644 --- a/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.h +++ b/SHADE_Engine/src/Graphics/Debugging/SHVulkanDebugUtil.h @@ -15,9 +15,9 @@ namespace SHADE public: static VKAPI_ATTR VkBool32 VKAPI_CALL GenericDebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageSeverityFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData); - static void ReportVkWarning(vk::Result vkResult, std::string_view message, std::source_location const& location = std::source_location::current()) noexcept; - static void ReportVkError(vk::Result vkResult, std::string_view message, std::source_location const& location = std::source_location::current()) noexcept; - static void ReportVkSuccess(std::string_view message, std::source_location const& location = std::source_location::current()) noexcept; + static void ReportVkWarning(vk::Result vkResult, std::string_view message) noexcept; + static void ReportVkError(vk::Result vkResult, std::string_view message) noexcept; + static void ReportVkSuccess(std::string_view message) noexcept; }; diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp new file mode 100644 index 00000000..a1b1cbc2 --- /dev/null +++ b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.cpp @@ -0,0 +1,84 @@ +#include "SHpch.h" +#include "SHDescriptorSetUpdater.h" + +namespace SHADE +{ + + SHDescriptorWriteInfo::SHDescriptorWriteInfo(SHDescriptorWriteInfo&& rhs) noexcept + : descImageInfos{ std::move(rhs.descImageInfos) } + , descBufferInfos{ std::move(rhs.descBufferInfos) } + , descTexelBufferInfos{std::move (rhs.descTexelBufferInfos)} + { + + } + + SHDescriptorWriteInfo::SHDescriptorWriteInfo(void) noexcept + : descImageInfos{} + , descBufferInfos{} + , descTexelBufferInfos{} + { + + } + + /***************************************************************************/ + /*! + + \brief + Links the write infos to the vulkan write descriptor sets. + + */ + /***************************************************************************/ + void SHDescriptorSetUpdater::LinkInfoToWriteDescSet(void) noexcept + { + for (uint32_t i = 0; i < writeInfos.size(); ++i) + { + writeDescSets[i].pImageInfo = writeInfos[i].descImageInfos.data(); + writeDescSets[i].pBufferInfo = writeInfos[i].descBufferInfos.data(); + writeDescSets[i].pTexelBufferView = writeInfos[i].descTexelBufferInfos.data(); + } + } + + SHDescriptorWriteInfo& SHDescriptorWriteInfo::operator=(SHDescriptorWriteInfo&& rhs) noexcept + { + if (&rhs == this) + return *this; + + descImageInfos = std::move(rhs.descImageInfos); + descBufferInfos = std::move(rhs.descBufferInfos); + descTexelBufferInfos = std::move(rhs.descTexelBufferInfos); + + return *this; + } + + + SHDescriptorSetUpdater::SHDescriptorSetUpdater(SHDescriptorSetUpdater&& rhs) noexcept + : writeInfos{ std::move(rhs.writeInfos) } + , writeHashMap {std::move (rhs.writeHashMap)} + { + + } + + SHDescriptorSetUpdater::SHDescriptorSetUpdater(void) noexcept + : writeInfos{} + , writeHashMap{} + { + + } + + std::vector const& SHDescriptorSetUpdater::GetWriteDescriptorSets(void) const noexcept + { + return writeDescSets; + } + + SHDescriptorSetUpdater& SHDescriptorSetUpdater::operator=(SHDescriptorSetUpdater&& rhs) noexcept + { + if (&rhs == this) + return *this; + + writeInfos = std::move (rhs.writeInfos); + writeHashMap = std::move (rhs.writeHashMap); + + return *this; + } + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h new file mode 100644 index 00000000..7a5ae967 --- /dev/null +++ b/SHADE_Engine/src/Graphics/Descriptors/SHDescriptorSetUpdater.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include "Graphics/SHVulkanIncludes.h" +#include "Graphics/Shaders/SHShaderReflected.h" + +namespace SHADE +{ + // Vulkan doesn't use all of the information when looking at a writeDescriptorSet. It all + // depends on the descriptor type. This struct plays it safe by having members that would + // accommodate all types of descriptors. + class SHDescriptorWriteInfo + { + //! When we want to update a descriptor that is an image, it goes in here + std::vector descImageInfos; + + //! When we want to update a descriptor that is a buffer, it goes in here + std::vector descBufferInfos; + + //! When we want to update a descriptor that is an texel buffer, it goes in here + std::vector descTexelBufferInfos; + + public: + SHDescriptorWriteInfo (void) noexcept; + SHDescriptorWriteInfo (SHDescriptorWriteInfo&& rhs) noexcept; + SHDescriptorWriteInfo& operator= (SHDescriptorWriteInfo&& rhs) noexcept; + + friend class SHVkDescriptorSetGroup; + friend class SHDescriptorSetUpdater; + }; + + class SHDescriptorSetUpdater + { + private: + //! When we want to update descriptor sets, this will get passed into vkUpdateDescriptorSets. + //! Each write will correspond to a binding from a set. If the binding is a variable + //! sized binding, pImageInfo (e.g.) will point to an array of vk::DescriptorImageInfo. + std::vector writeInfos; + + //! When we want to update a write, we need to use this to identify the index of the write. + std::unordered_map writeHashMap; + + //! We keep this here because we want this to be immediately passable to vkUpdateDescriptorSets + std::vector writeDescSets; + + void LinkInfoToWriteDescSet(void) noexcept; + + public: + SHDescriptorSetUpdater (void) noexcept; + SHDescriptorSetUpdater(SHDescriptorSetUpdater&& rhs) noexcept; + SHDescriptorSetUpdater& operator= (SHDescriptorSetUpdater&& rhs) noexcept; + + public: + std::vector const& GetWriteDescriptorSets (void) const noexcept; + + friend class SHVkDescriptorSetGroup; + }; +} + diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp index 87d43255..77663ab8 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.cpp @@ -7,32 +7,52 @@ namespace SHADE { - /*---------------------------------------------------------------------------------*/ - /* Constructor/Destructor */ - /*---------------------------------------------------------------------------------*/ - SHVkDescriptorPool::SHVkDescriptorPool(Handle device, const Config& config) - : device { device } + /*---------------------------------------------------------------------------------*/ + /* Constructor/Destructor */ + /*---------------------------------------------------------------------------------*/ + SHVkDescriptorPool::SHVkDescriptorPool(Handle device, const Config& config) + : device{ device } + { + // Create the Pool + const vk::DescriptorPoolCreateInfo POOL_CREATE_INFO { - // Create the Pool - const vk::DescriptorPoolCreateInfo POOL_CREATE_INFO - { - .flags = config.Flags, - .maxSets = config.MaxSets, - .poolSizeCount = static_cast(config.Limits.size()), - .pPoolSizes = config.Limits.data() - }; - pool = device->GetVkLogicalDevice().createDescriptorPool(POOL_CREATE_INFO); - } + .flags = config.Flags, + .maxSets = config.MaxSets, + .poolSizeCount = static_cast(config.Limits.size()), + .pPoolSizes = config.Limits.data() + }; + pool = device->GetVkLogicalDevice().createDescriptorPool(POOL_CREATE_INFO); + } - SHVkDescriptorPool::~SHVkDescriptorPool() noexcept - { - if (pool) - device->GetVkLogicalDevice().destroyDescriptorPool(pool); - } + SHVkDescriptorPool::SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept + : device{ rhs.device } + , pool{ rhs.pool } + { + rhs.pool = VK_NULL_HANDLE; + } - std::vector> SHVkDescriptorPool::Allocate(const std::vector>& layouts, std::vector const& variableDescCounts) - { - SHVkInstance::GetResourceManager().Create(device, GetHandle(), layouts, variableDescCounts); - return {}; - } + SHVkDescriptorPool::~SHVkDescriptorPool() noexcept + { + if (pool) + device->GetVkLogicalDevice().destroyDescriptorPool(pool); + } + + SHVkDescriptorPool& SHVkDescriptorPool::operator=(SHVkDescriptorPool&& rhs) noexcept + { + if (&rhs == this) + return *this; + + device = rhs.device; + pool = rhs.pool; + + rhs.pool = VK_NULL_HANDLE; + + return *this; + } + + std::vector> SHVkDescriptorPool::Allocate(const std::vector>& layouts, std::vector const& variableDescCounts) + { + SHVkInstance::GetResourceManager().Create(device, GetHandle(), layouts, variableDescCounts); + return {}; + } } diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h index c3059b8b..9314d940 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h @@ -65,7 +65,7 @@ namespace SHADE /// SHVkDescriptorPool(Handle device, const Config& config = {}); SHVkDescriptorPool(const SHVkDescriptorPool&) = delete; - SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept = default; + SHVkDescriptorPool(SHVkDescriptorPool&& rhs) noexcept; /// /// Destructor which will unload and deallocate all resources for this Pool. /// @@ -75,7 +75,7 @@ namespace SHADE /* Overloaded Operators */ /*-----------------------------------------------------------------------------*/ SHVkDescriptorPool& operator=(const SHVkDescriptorPool&) = delete; - SHVkDescriptorPool& operator=(SHVkDescriptorPool&& rhs) noexcept = default; + SHVkDescriptorPool& operator=(SHVkDescriptorPool&& rhs) noexcept; /*-----------------------------------------------------------------------------*/ /* Getter Functions */ diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp index 6bdc5601..16143aa5 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.cpp @@ -42,9 +42,11 @@ namespace SHADE { // Create the layout for each concurrent frame std::vector vkLayouts{ layouts.size() }; - for (auto& layout : layouts) + + //for (auto& layout : layouts) + for (uint32_t i = 0; i < layouts.size(); ++i) { - vkLayouts.push_back(layout->GetVkHandle()); + vkLayouts.push_back(layouts[i]->GetVkHandle()); } // Check for variable descriptor count @@ -67,6 +69,66 @@ namespace SHADE // allocate descriptor sets descSets = device->GetVkLogicalDevice().allocateDescriptorSets(DESC_SET_LAYOUT_CREATE_INFO); + + + + // Now we want to prepare the write descriptor sets for writing later. + for (uint32_t i = 0; i < layouts.size(); ++i) + { + auto const& bindings = layouts[i]->GetBindings(); + for (auto& binding : bindings) + { + BindingAndSetHash writeHash = binding.BindPoint; + writeHash |= static_cast(i) << 32; + + // new write for the binding + updater.writeInfos.emplace_back(); + updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1); + auto& writeInfo = updater.writeInfos.back(); + + updater.writeDescSets.emplace_back(); + auto& writeDescSet = updater.writeDescSets.back(); + + // Initialize info for write + writeDescSet.descriptorType = binding.Type; + writeDescSet.dstArrayElement = 0; + writeDescSet.dstSet = descSets[i]; + writeDescSet.dstBinding = binding.BindPoint; + + // Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in + uint32_t descriptorCount = (binding.flags & vk::DescriptorBindingFlagBits::eVariableDescriptorCount) ? variableDescCounts[i] : 1; + writeDescSet.descriptorCount = descriptorCount; + + switch (binding.Type) + { + //case vk::DescriptorType::eSampler: + //case vk::DescriptorType::eSampledImage: + case vk::DescriptorType::eCombinedImageSampler: + writeInfo.descImageInfos.resize(descriptorCount); + break; + //case vk::DescriptorType::eStorageImage: + // break; + case vk::DescriptorType::eUniformTexelBuffer: + case vk::DescriptorType::eStorageTexelBuffer: + case vk::DescriptorType::eUniformBuffer: + case vk::DescriptorType::eStorageBuffer: + writeInfo.descImageInfos.resize (descriptorCount); + break; + //case vk::DescriptorType::eUniformBufferDynamic: + // break; + //case vk::DescriptorType::eStorageBufferDynamic: + // break; + //case vk::DescriptorType::eInputAttachment: + // break; + //case vk::DescriptorType::eInlineUniformBlock: + // break; + default: + break; + } + } + } + // Link all the writeDescSet data for vkUpdateDescriptorSets to write to the linked descriptors + updater.LinkInfoToWriteDescSet(); } /***************************************************************************/ @@ -82,4 +144,45 @@ namespace SHADE if (!descSets.empty()) device->GetVkLogicalDevice().freeDescriptorSets(descPool->GetVkHandle(), descSets); } + + /***************************************************************************/ + /*! + + \brief + Modifies a descriptor write info. #NoteToSelf: This function does NOT + need to modify the writeDescSets. Those are already linked before. + + \param imageViewsAndSamplers + Image and view samplers + + */ + /***************************************************************************/ + void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::vector> const& imageViewsAndSamplers) noexcept + { + // Find the target writeDescSet + BindingAndSetHash writeHash = binding; + writeHash |= static_cast(set) << 32; + auto& writeInfo = updater.writeInfos[updater.writeHashMap.at(writeHash)]; + + if (imageViewsAndSamplers.size() > writeInfo.descImageInfos.size()) + { + SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. "); + } + + for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i) + { + // write sampler and image view + auto& ivs = imageViewsAndSamplers[i]; + writeInfo.descImageInfos[i].imageView = ivs.first; + writeInfo.descImageInfos[i].sampler = ivs.second; + } + } + + + void SHVkDescriptorSetGroup::UpdateDescriptorSet(void) noexcept + { + device->UpdateDescriptorSets(updater.GetWriteDescriptorSets()); + } + + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h index b95859bb..9e311e9a 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetGroup.h @@ -1,71 +1,89 @@ - #pragma once +#pragma once // Project Includes #include "Graphics/SHVulkanIncludes.h" #include "Resource/Handle.h" +#include "Graphics/Shaders/SHShaderReflected.h" +#include "SHDescriptorSetUpdater.h" namespace SHADE { - /*---------------------------------------------------------------------------------*/ - /* Forward Declarations */ - /*---------------------------------------------------------------------------------*/ - class SHVkLogicalDevice; - class SHVkDescriptorPool; - class SHVkDescriptorSetLayout; + /*---------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*---------------------------------------------------------------------------------*/ + class SHVkLogicalDevice; + class SHVkDescriptorPool; + class SHVkDescriptorSetLayout; - /*---------------------------------------------------------------------------------*/ - /* Type Definitions */ - /*---------------------------------------------------------------------------------*/ + + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*---------------------------------------------------------------------------------*/ + /// + /// + /// + class SHVkDescriptorSetGroup + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constructor/Destructors */ + /*-----------------------------------------------------------------------------*/ /// - /// + /// Constructs a Descriptor Set with the specified layout using the specified + /// pool meant for use with the specified surface. This Set will be created with + /// multiple Vulkan Descriptor Set objects based on the max number of concurrent + /// frames for the specified surface. /// - class SHVkDescriptorSetGroup - { - public: - /*-----------------------------------------------------------------------------*/ - /* Constructor/Destructors */ - /*-----------------------------------------------------------------------------*/ - /// - /// Constructs a Descriptor Set with the specified layout using the specified - /// pool meant for use with the specified surface. This Set will be created with - /// multiple Vulkan Descriptor Set objects based on the max number of concurrent - /// frames for the specified surface. - /// - /// Vulkan logical device used to create the Set. - /// Descriptor Pool used to create the Set. - /// Descriptor Set Layout to create the Set with. - SHVkDescriptorSetGroup(Handle deviceHdl, Handle pool, - std::vector> const& layouts, - std::vector const& variableDescCounts); - SHVkDescriptorSetGroup(const SHVkDescriptorSetGroup&) = delete; - SHVkDescriptorSetGroup(SHVkDescriptorSetGroup&& rhs) noexcept = default; - /// - /// Destructor which will unload and deallocate all resources for this Descriptor Set. - /// - ~SHVkDescriptorSetGroup() noexcept; + /// Vulkan logical device used to create the Set. + /// Descriptor Pool used to create the Set. + /// Descriptor Set Layout to create the Set with. + SHVkDescriptorSetGroup(Handle deviceHdl, Handle pool, + std::vector> const& layouts, + std::vector const& variableDescCounts); + SHVkDescriptorSetGroup(const SHVkDescriptorSetGroup&) = delete; + SHVkDescriptorSetGroup(SHVkDescriptorSetGroup&& rhs) noexcept = default; + /// + /// Destructor which will unload and deallocate all resources for this Descriptor Set. + /// + ~SHVkDescriptorSetGroup() noexcept; - /*-----------------------------------------------------------------------------*/ - /* Overloaded Operators */ - /*-----------------------------------------------------------------------------*/ - SHVkDescriptorSetGroup& operator=(const SHVkDescriptorSetGroup&) = delete; - SHVkDescriptorSetGroup& operator=(SHVkDescriptorSetGroup&& rhs) noexcept = default; + /*-----------------------------------------------------------------------------*/ + /* Overloaded Operators */ + /*-----------------------------------------------------------------------------*/ + SHVkDescriptorSetGroup& operator=(const SHVkDescriptorSetGroup&) = delete; + SHVkDescriptorSetGroup& operator=(SHVkDescriptorSetGroup&& rhs) noexcept = default; - /*-----------------------------------------------------------------------------*/ - /* Getter Functions */ - /*-----------------------------------------------------------------------------*/ - /// - /// Retrieves the handle to the Vulkan Descriptor Set handle. - /// - /// Handle to the Vulkan Descriptor Set. - [[nodiscard]] - inline const std::vector& GetVkHandle() { return descSets; } + /*-----------------------------------------------------------------------------*/ + /* Descriptor set writing */ + /*-----------------------------------------------------------------------------*/ + void ModifyWriteDescImage (uint32_t set, uint32_t binding, std::vector> const& imageViewsAndSamplers) noexcept; + void UpdateDescriptorSet (void) noexcept; - private: - /*-----------------------------------------------------------------------------*/ - /* Data Members */ - /*-----------------------------------------------------------------------------*/ - Handle device; - Handle descPool; - std::vector descSets; - }; + /*-----------------------------------------------------------------------------*/ + /* Getter Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Retrieves the handle to the Vulkan Descriptor Set handle. + /// + /// Handle to the Vulkan Descriptor Set. + [[nodiscard]] + inline const std::vector& GetVkHandle() { return descSets; } + private: + /*-----------------------------------------------------------------------------*/ + /* Data Members */ + /*-----------------------------------------------------------------------------*/ + //! Device required to allocate descriptor sets + Handle device; + + //! Descriptor pool to allocate descriptor sets + Handle descPool; + + //! Descriptor sets + std::vector descSets; + + //! for updating descriptor sets. We want to cache this so that we don't create the + //! write structs at runtime. + SHDescriptorSetUpdater updater; + + }; } diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp index 36eaa8e8..da1a3645 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.cpp @@ -85,6 +85,11 @@ namespace SHADE device->GetVkLogicalDevice().destroyDescriptorSetLayout(setLayout); } + std::vector const& SHVkDescriptorSetLayout::GetBindings(void) const noexcept + { + return layoutDesc; + } + SHVkDescriptorSetLayout& SHVkDescriptorSetLayout::operator=(SHVkDescriptorSetLayout&& rhs) noexcept { if (&rhs == this) diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h index 590fd787..1acba189 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorSetLayout.h @@ -96,6 +96,7 @@ namespace SHADE /// /// Handle to the Vulkan Descriptor Set Layout handle. inline const vk::DescriptorSetLayout& GetVkHandle() const { return setLayout; } + std::vector const& GetBindings (void) const noexcept; private: /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp index aa442805..da4947f2 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp +++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.cpp @@ -418,7 +418,12 @@ namespace SHADE /***************************************************************************/ Handle SHVkLogicalDevice::CreateImage(uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) const noexcept { - return SHVkInstance::GetResourceManager().Create(std::cref(vmaAllocator), w, h, levels, format, usage, create); + return SHVkInstance::GetResourceManager().Create(&vmaAllocator, w, h, levels, format, usage, create); + } + + Handle SHVkLogicalDevice::CreateImage(SHImageCreateParams const& imageDetails, unsigned char* data, uint32_t dataSize, std::span inMipOffsets, VmaMemoryUsage memUsage, VmaAllocationCreateFlags allocFlags) noexcept + { + return SHVkInstance::GetResourceManager().Create(&vmaAllocator, imageDetails, data, dataSize, inMipOffsets, memUsage, allocFlags); } /***************************************************************************/ @@ -509,6 +514,12 @@ namespace SHADE } + Handle SHVkLogicalDevice::CreateDescriptorPools(const SHVkDescriptorPool::Config& config /*= {}*/) noexcept + { + return SHVkInstance::GetResourceManager().Create (GetHandle(), config); + + } + /***************************************************************************/ /*! @@ -541,6 +552,22 @@ namespace SHADE return SHVkInstance::GetResourceManager().Create(GetHandle()); } + /***************************************************************************/ + /*! + + \brief + Writes to descriptor sets. + + \param writeDescSets + Descriptor sets to write to. + + */ + /***************************************************************************/ + void SHVkLogicalDevice::UpdateDescriptorSets(std::vector const& writeDescSets) noexcept + { + vkLogicalDevice.updateDescriptorSets(writeDescSets, {}); + } + /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h index b8eec993..c359d1d3 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h +++ b/SHADE_Engine/src/Graphics/Devices/SHVkLogicalDevice.h @@ -17,8 +17,9 @@ #include "Graphics/Pipeline/SHPipelineState.h" #include "Graphics/Pipeline/SHPipelineType.h" #include "vk_mem_alloc.h" -//#include "Graphics/DescriptorSets/SHDescriptorPool.h" +#include "Graphics/Descriptors/SHVkDescriptorPool.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" +#include "Graphics/Images/SHVkImage.h" namespace SHADE { @@ -29,7 +30,6 @@ namespace SHADE class SHVkSurface; class SHVkSwapchain; class SHVkBuffer; - class SHVkImage; class SHVkFence; class SHVkSemaphore; class SHVkShaderModule; @@ -38,6 +38,7 @@ namespace SHADE class SHVkFramebuffer; class SHVkImageView; class SHShaderBlockInterface; + class SHVkDescriptorSetGroup; /***************************************************************************/ /*! @@ -138,14 +139,23 @@ namespace SHADE ) const noexcept; Handle CreateImage ( - uint32_t w, - uint32_t h, - uint8_t levels, - vk::Format format, - vk::ImageUsageFlags usage, - vk::ImageCreateFlags create + uint32_t w, + uint32_t h, + uint8_t levels, + vk::Format format, + vk::ImageUsageFlags usage, + vk::ImageCreateFlags create ) const noexcept; - + + Handle CreateImage ( + SHImageCreateParams const& imageDetails, + unsigned char* data, + uint32_t dataSize, + std::span inMipOffsets, + VmaMemoryUsage memUsage, + VmaAllocationCreateFlags allocFlags + ) noexcept; + Handle CreateShaderModule ( std::vector const& binaryData, std::string entryPoint, @@ -165,10 +175,13 @@ namespace SHADE Handle CreateRenderpass (std::span const vkDescriptions, std::span const spDescs, std::span const spDeps) noexcept; Handle CreateFramebuffer (Handle const& renderpassHdl, std::vector> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept; Handle CreateDescriptorSetLayout (std::vector const& bindings) noexcept; + Handle CreateDescriptorPools (const SHVkDescriptorPool::Config& config = {}) noexcept; Handle CreatePipelineLayout (SHPipelineLayoutParams& pipelineLayoutParams) noexcept; Handle CreateFence (void) const noexcept; Handle CreateSemaphore (void) const noexcept; + void UpdateDescriptorSets (std::vector const& writeDescSets) noexcept; + /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ /*-----------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDeviceLibrary.cpp b/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDeviceLibrary.cpp index 511af8fc..d815fb7e 100644 --- a/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDeviceLibrary.cpp +++ b/SHADE_Engine/src/Graphics/Devices/SHVkPhysicalDeviceLibrary.cpp @@ -180,10 +180,10 @@ namespace SHADE return; } - SHLOG_ERROR("Successfully queried Physical Devices:"); + SHLOG_TRACE("Successfully queried Physical Devices:"); for (auto const& device : physicalDevices) { - SHLOG_ERROR(std::string_view (std::string("\t-") + GetDeviceTypeName(device.getProperties().deviceType) + device.getProperties().deviceName.operator std::string())); + SHLOG_TRACE(std::string_view (std::string("\t-") + GetDeviceTypeName(device.getProperties().deviceType) + device.getProperties().deviceName.operator std::string())); } } } diff --git a/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp b/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp index 11fbe5dd..f3d5a7b5 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp +++ b/SHADE_Engine/src/Graphics/Images/SHVkImage.cpp @@ -5,14 +5,88 @@ #include "Tools/SHLogger.h" #include "SHVkImageView.h" #include "Graphics/Instance/SHVkInstance.h" +#include "Graphics/Buffers/SHVkBuffer.h" namespace SHADE { + /***************************************************************************/ + /*! + + \brief + If an image is a GPU only resource, we need to prep a staging buffer + to use for transferring data to the GPU. #NoteToSelf: I don't really + like this because its duplicate code. Should try to find a way to utilize + the logical device for this. + + \param data + Data to transfer. + + \param srcSize + Size in bytes of the data. + + */ + /***************************************************************************/ + void SHVkImage::PrepStagingBuffer(void* data, uint32_t srcSize) noexcept + { + // For creation of buffer + vk::BufferCreateInfo bufferInfo{}; + + // size stored same as GPU buffer + bufferInfo.size = srcSize; + + // We just want to set the transfer bit + bufferInfo.usage = vk::BufferUsageFlagBits::eTransferSrc; + + // sharing mode exclusive + bufferInfo.sharingMode = vk::SharingMode::eExclusive; + + // Set to auto detect bits + VmaAllocationCreateInfo allocCreateInfo{}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; + + // We want to just write all at once. Using random access bit could make this slow + allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; + + // parameters of a vmaAllocation retrieved via vmaGetAllocationInfo + VmaAllocationInfo allocInfo; + + // results of allocation + VmaAllocation stagingAlloc; + + // To get around VMA's usage for C version of vulkan, create a temp first..., + VkBuffer tempBuffer{}; + + // Create the buffer... + vmaCreateBuffer(*vmaAllocator, + &bufferInfo.operator VkBufferCreateInfo & (), // TODO: Verify if this works (can use renderdoc to check buffer variables?) + &allocCreateInfo, + &tempBuffer, &stagingAlloc, &allocInfo); + + // then assign it to the hpp version + stagingBuffer = tempBuffer; + + // Just map, copy then unmap + void* stagingBufferMappedPtr = nullptr; + vmaMapMemory(*vmaAllocator, stagingAlloc, &stagingBufferMappedPtr); + + if (stagingBufferMappedPtr) + std::memcpy(static_cast(stagingBufferMappedPtr), static_cast(data), srcSize); + + const VkDeviceSize offsets = 0; + const VkDeviceSize sizes = srcSize; + vmaFlushAllocations(*vmaAllocator, 1, &stagingAlloc, &offsets, &sizes); + + vmaUnmapMemory(*vmaAllocator, stagingAlloc); + } + SHVkImage::SHVkImage( - VmaAllocator const& vmaAllocator, - SHImageCreateParams const& imageDetails, - VmaMemoryUsage memUsage, - VmaAllocationCreateFlags allocFlags + VmaAllocator const* allocator, + SHImageCreateParams const& imageDetails, + unsigned char* data, + uint32_t dataSize, + std::span inMipOffsets, + VmaMemoryUsage memUsage, + VmaAllocationCreateFlags allocFlags ) noexcept : imageType { imageDetails.imageType } , width{ imageDetails.width } @@ -23,12 +97,14 @@ namespace SHADE , imageFormat{ imageDetails.imageFormat } , usageFlags{} , createFlags{} + , vmaAllocator{allocator} + , mipOffsets { inMipOffsets } + , boundToCoherent{false} + , randomAccessOptimized {false} + , mappedPtr{nullptr} { - for (auto& bit : imageDetails.usageBits) - usageFlags |= bit; - - for (auto& bit : imageDetails.createBits) - createFlags |= bit; + usageFlags = imageDetails.usageFlags; + createFlags = imageDetails.createFlags; // If marked as 2D array compatible, image type MUST be 3D if (createFlags & vk::ImageCreateFlagBits::e2DArrayCompatible) @@ -64,58 +140,52 @@ namespace SHADE VmaAllocationInfo allocInfo{}; VkImage tempImage; - vmaCreateImage(vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo&(), &allocCreateInfo, &tempImage, &alloc, &allocInfo); + auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo&(), &allocCreateInfo, &tempImage, &alloc, &allocInfo); + + if (result != VK_SUCCESS) + SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. "); + else + SHVulkanDebugUtil::ReportVkSuccess("Successfully created image. "); + vkImage = tempImage; - //if (allocFlags & ) + // At this point the image and device memory have been created. + + if (allocFlags & VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT) + randomAccessOptimized = true; + + // TODO: This constructor can only create a GPU only resource for now. Due to time constraint, I was trying to create a ctor + // fast to finish up the ImGUI backend. In the future, there definitely needs to be more versatility to the constructor. + + // Get the memory property flags + VkMemoryPropertyFlags memPropFlags; + vmaGetAllocationMemoryProperties(*vmaAllocator, alloc, &memPropFlags); + + // mainly host visible. Can be cached (need to flush/invalidate), uncached (always coherent) and coherent (virtual). + //if (memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + //{ + // // If memory is marked to be coherent between CPU and GPU (no need flush/invalidate) (TODO: Verify if VMA_ALLOCATION_CREATE_MAPPED_BIT is used when VMA_MEMORY_USAGE_AUTO is set) + // // TODO: also verify that coherent bit = pointer is already mapped + // if (memPropFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + // { + // boundToCoherent = true; + // mappedPtr = allocInfo.pMappedData; + // } + // else + // mappedPtr = nullptr; + + // if (data) + // MapWriteUnmap(data, srcSize, 0, 0); + //} + //else + //{ + // We can prep first so that we can do transfers later via 1 cmd buffer recording + PrepStagingBuffer(data, dataSize); + + //} } - /***************************************************************************/ - /*! - - \brief - This is mainly used for images that aren't created internally because - they cannot be created in the traditional way (e.g. swapchain images). - - \param inVkImage - Image already created outside - - \param width - Width of the image - - \param height - Height of the image - - \param depth - Depth of the image - - \param levels - Number of levels in the image - - \param arrayLayers - if the image is an array, this value will be > 1. - - \param imageFormat - Format of the image - - */ - /***************************************************************************/ - SHVkImage::SHVkImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t arrayLayers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept - : vkImage (inVkImage) - , width{ inWidth } - , height{ inHeight } - , depth{ inDepth } - , mipLevelCount{ levels } - , layerCount{ arrayLayers } - , imageFormat{ format } - , usageFlags{flags} - , alloc{} - , imageType{type} - , createFlags{} - { - } - - SHVkImage::SHVkImage(VmaAllocator const& vmaAllocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept + SHVkImage::SHVkImage(VmaAllocator const* allocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept : width {w} , height{h} , depth {1} @@ -124,6 +194,7 @@ namespace SHADE , imageFormat{format} , usageFlags{usage} , createFlags {create} + , vmaAllocator {allocator} { vk::ImageCreateInfo imageCreateInfo{}; imageCreateInfo.imageType = vk::ImageType::e2D; @@ -149,7 +220,7 @@ namespace SHADE VmaAllocationInfo allocInfo{}; VkImage tempImage; - auto result = vmaCreateImage(vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo); + auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo); vkImage = tempImage; if (result != VK_SUCCESS) @@ -163,6 +234,86 @@ namespace SHADE return SHVkInstance::GetResourceManager().Create(inLogicalDeviceHdl, parent, createParams); } + void SHVkImage::TransferToDeviceResource(Handle const& cmdBufferHdl) noexcept + { + // prepare copy regions + std::vector copyRegions{mipOffsets.size()}; + + for (uint32_t i = 0; i < mipOffsets.size(); ++i) + { + copyRegions[i].bufferOffset = mipOffsets[i]; + copyRegions[i].bufferRowLength = 0; // for padding + copyRegions[i].bufferImageHeight = 0; // for padding + copyRegions[i].imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor; // TODO: Need to change this to base it off image format. + copyRegions[i].imageSubresource.mipLevel = i; + copyRegions[i].imageSubresource.baseArrayLayer = 0; // TODO: Array textures not supported yet + copyRegions[i].imageSubresource.layerCount = layerCount; + copyRegions[i].imageOffset = vk::Offset3D{ 0,0,0 }; + copyRegions[i].imageExtent = vk::Extent3D{ width >> i, height >> i, 1 }; + } + + } + + /***************************************************************************/ + /*! + + \brief + Does not perform any image transitions but prepares a barrier for image + transitioning. Pipeline barrier will be issued outside this call after + this preparation function, or at least, it should be. + + \param oldLayout + Old layout of the image. + + \param newLayout + new layout of the image to transition to. + + \param barrier + Barrier to modify to prepare the image for transitioning. + + */ + /***************************************************************************/ + void SHVkImage::PrepareImageTransition(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept + { + barrier.oldLayout = oldLayout; + barrier.newLayout = newLayout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = vkImage; + barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; // TODO: Need to change this to base it off image format. + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = mipLevelCount; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = layerCount; + + vk::PipelineStageFlagBits srcStage = vk::PipelineStageFlagBits::eTopOfPipe; + vk::PipelineStageFlagBits dstStage = vk::PipelineStageFlagBits::eTopOfPipe; + + if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal) + { + srcStage = vk::PipelineStageFlagBits::eTopOfPipe; + dstStage = vk::PipelineStageFlagBits::eTransfer; + + barrier.srcAccessMask = vk::AccessFlagBits::eNone; + barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite; + } + else if (oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal) + { + srcStage = vk::PipelineStageFlagBits::eTransfer; + + // TODO, what if we want to access in compute shader + dstStage = vk::PipelineStageFlagBits::eFragmentShader; + + barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite; + barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead; + } + else + { + SHLOG_ERROR("Image layouts are invalid. "); + } + + } + void SHVkImage::LinkWithExteriorImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t layers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept { vkImage = inVkImage; diff --git a/SHADE_Engine/src/Graphics/Images/SHVkImage.h b/SHADE_Engine/src/Graphics/Images/SHVkImage.h index 53066075..a30b90e6 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkImage.h +++ b/SHADE_Engine/src/Graphics/Images/SHVkImage.h @@ -10,6 +10,7 @@ namespace SHADE { class SHVkLogicalDevice; class SHVkImageView; + class SHVkCommandBuffer; struct SHImageCreateParams { @@ -35,10 +36,10 @@ namespace SHADE vk::Format imageFormat; //! Image usage bits - std::span usageBits; + vk::ImageUsageFlags usageFlags; //! Image create flags - std::span createBits; + vk::ImageCreateFlags createFlags; }; class SHVkImage @@ -47,6 +48,12 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ /*-----------------------------------------------------------------------*/ + //! Pointer to the vma allocator. #NoteToSelf: Not super proud of this being a pointer. + //! The only reason why this is a pointer is because a reference_wrapper cannot be default constructed. + //! And the reason why we want a default constructor is because sometimes we don't want to create images + //! but merely link them from outside (swapchain images) + VmaAllocator const* vmaAllocator; + //! 1D, 2D or 3D vk::ImageType imageType = vk::ImageType::e2D; @@ -80,22 +87,46 @@ namespace SHADE //! allocation object containing details of an allocation VmaAllocation alloc{}; + //! Whether or not this image is HOST_VISIBLE and random access optimized + bool randomAccessOptimized; + + //! Whether or not the memory the image is bound to is memory coherent (updates on CPU can be seen on GPU without flushing cache) + bool boundToCoherent; + + //! Persistently mapped pointer if applicable (will be void if image is + //! not created with the correct flags). Note that this is only used for + //! persistent mapping. One time updates do not use this pointer. + void* mappedPtr; + + //! Staging buffer for images purely in the GPU + vk::Buffer stagingBuffer; + + //! Mipmap offsets for initializing the vk::BufferImageCopy during transfer to GPU resource + std::span mipOffsets; + + /*-----------------------------------------------------------------------*/ + /* PRIVATE MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + void PrepStagingBuffer(void* data, uint32_t srcSize) noexcept; + + public: /*-----------------------------------------------------------------------*/ /* CTOR AND DTOR */ /*-----------------------------------------------------------------------*/ SHVkImage(void) noexcept = default; - // TODO: Might need to add flags to parameters SHVkImage( - VmaAllocator const& vmaAllocator, - SHImageCreateParams const& imageDetails, - VmaMemoryUsage memUsage, - VmaAllocationCreateFlags allocFlags + VmaAllocator const* allocator, + SHImageCreateParams const& imageDetails, + unsigned char* data, + uint32_t dataSize, + std::span inMipOffsets, + VmaMemoryUsage memUsage, + VmaAllocationCreateFlags allocFlags ) noexcept; - SHVkImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t arrayLayers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept; - SHVkImage(VmaAllocator const& vmaAllocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept; + SHVkImage(VmaAllocator const* allocator, uint32_t w, uint32_t h, uint8_t levels, vk::Format format, vk::ImageUsageFlags usage, vk::ImageCreateFlags create) noexcept; SHVkImage(SHVkImage&& rhs) noexcept = default; SHVkImage& operator=(SHVkImage && rhs) noexcept = default; @@ -103,7 +134,9 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ - Handle CreateImageView(Handle const& inLogicalDeviceHdl, Handle const& parent, SHImageViewDetails const& createParams) const noexcept; + Handle CreateImageView (Handle const& inLogicalDeviceHdl, Handle const& parent, SHImageViewDetails const& createParams) const noexcept; + void TransferToDeviceResource (Handle const& cmdBufferHdl) noexcept; + void PrepareImageTransition (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept; /*-----------------------------------------------------------------------*/ /* GETTERS AND SETTERS */ diff --git a/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp new file mode 100644 index 00000000..e7a97126 --- /dev/null +++ b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp @@ -0,0 +1,7 @@ +#include "SHpch.h" +#include "SHVkSampler.h" + +namespace SHADE +{ + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Images/SHVkSampler.h b/SHADE_Engine/src/Graphics/Images/SHVkSampler.h new file mode 100644 index 00000000..d58edb8f --- /dev/null +++ b/SHADE_Engine/src/Graphics/Images/SHVkSampler.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Graphics/SHVulkanIncludes.h" + +namespace SHADE +{ + struct SHVkSamplerParams + { + vk::Filter minFilter; + vk::Filter maxFilter; + //vk::Filter maxFilter; + }; + + class SHVkSampler + { + private: + //! The vulkan sampler handler + vk::Sampler vkSampler; + + public: + SHVkSampler () noexcept; + SHVkSampler (SHVkSampler&& rhs) noexcept; + SHVkSampler&& operator=(SHVkSampler&& rhs) noexcept; + + }; +} + diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index ad70a18f..573e1905 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -22,14 +22,12 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { - /*---------------------------------------------------------------------------------*/ + + /*---------------------------------------------------------------------------------*/ /* Constructor/Destructors */ /*---------------------------------------------------------------------------------*/ - SHGraphicsSystem::SHGraphicsSystem(SHWindow& window) + void SHGraphicsSystem::Init(void) { - // Save the SHWindow - this->window = &window; - // Set Up Instance SHVkInstance::Init(true, true, true); @@ -39,10 +37,10 @@ namespace SHADE device = SHVkInstance::CreateLogicalDevice({ SHQueueParams(SH_Q_FAM::GRAPHICS, SH_QUEUE_SELECT::DEDICATED), SHQueueParams(SH_Q_FAM::TRANSFER, SH_QUEUE_SELECT::DEDICATED) }, physicalDevice); // Construct surface - surface = device->CreateSurface(window.GetHWND()); + surface = device->CreateSurface(window->GetHWND()); // Construct Swapchain - auto windowDims = window.GetWindowSize(); + auto windowDims = window->GetWindowSize(); swapchain = device->CreateSwapchain(surface, windowDims.first, windowDims.second, SHSwapchainParams { .surfaceImageFormats {vk::Format::eB8G8R8A8Unorm, vk::Format::eR8G8B8A8Unorm, vk::Format::eB8G8R8Unorm, vk::Format::eR8G8B8Unorm}, @@ -51,13 +49,13 @@ namespace SHADE .vsyncOn = false, // TODO: Set to true when shipping game }); - window.RegisterWindowSizeCallback([&]([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height) + window->RegisterWindowSizeCallback([&]([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height) { renderContext.SetIsResized(true); }); // Create graphics queue - queue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0); + graphicsQueue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0); // Create Render Context @@ -87,7 +85,7 @@ namespace SHADE //commandBuffers[i] = commandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); // works } - + descPool = device->CreateDescriptorPools(); @@ -101,12 +99,12 @@ namespace SHADE renderGraph.AddResource("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); renderGraph.AddResource("Downscale", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); renderGraph.AddResource("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second); - auto node = renderGraph.AddNode("G-Buffer", { "Position", "Normals", "Composite" }, {}); // no predecessors + auto node = renderGraph.AddNode("G-Buffer", { "Composite", "Position", "Normals", "Present" }, {}); // no predecessors // First subpass to write to G-Buffer - auto writeSubpass = node->AddSubpass("G-Buffer Write"); + auto writeSubpass = node->AddSubpass("G-Buffer Write"); writeSubpass->AddColorOutput("Position"); - writeSubpass->AddColorOutput("Normals"); + writeSubpass->AddColorOutput("Present"); // Second subpass to read from G-Buffer auto compositeSubpass = node->AddSubpass("G-Buffer Composite"); @@ -114,11 +112,11 @@ namespace SHADE compositeSubpass->AddInput("Normals"); compositeSubpass->AddInput("Position"); - auto compositeNode = renderGraph.AddNode("Bloom", { "Composite", "Downscale", "Present"}, {"G-Buffer"}); - auto bloomSubpass = compositeNode->AddSubpass("Downsample"); - bloomSubpass->AddInput("Composite"); - bloomSubpass->AddColorOutput("Downscale"); - bloomSubpass->AddColorOutput("Present"); + //auto compositeNode = renderGraph.AddNode("Bloom", { "Composite", "Downscale", "Present" }, { "G-Buffer" }); + //auto bloomSubpass = compositeNode->AddSubpass("Downsample"); + //bloomSubpass->AddInput("Composite"); + //bloomSubpass->AddColorOutput("Downscale"); + //bloomSubpass->AddColorOutput("Present"); renderGraph.Generate(); @@ -127,11 +125,25 @@ namespace SHADE /* RENDERGRAPH END TESTING */ /*-----------------------------------------------------------------------*/ } - SHGraphicsSystem::~SHGraphicsSystem() + + void SHGraphicsSystem::Run(float dt) noexcept + { + auto const& frameData = renderContext.GetCurrentFrameData(); + + renderGraph.Execute(renderContext.GetCurrentFrame()); + + graphicsQueue->SubmitCommandBuffer({ renderGraph.GetCommandBuffer(renderContext.GetCurrentFrame()) }, + { frameData.semRenderFinishHdl }, + { frameData.semImgAvailableHdl }, + vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests); + + } + + void SHGraphicsSystem::Exit(void) { //renderPass.Free(); renderContext.Destroy(); - queue.Free(); + graphicsQueue.Free(); swapchain.Free(); surface.Free(); device.Free(); @@ -205,7 +217,7 @@ namespace SHADE presentInfo.pImageIndices = &CURR_FRAME_IDX; // #BackEndTest: queues an image for presentation - if (auto result = device->GetQueue(SH_Q_FAM::GRAPHICS, 0)->GetVkQueue().presentKHR(&presentInfo); result != vk::Result::eSuccess) + if (auto result = graphicsQueue->Present(swapchain, {currFrameData.semRenderFinishHdl}, CURR_FRAME_IDX); result != vk::Result::eSuccess) { // If swapchain is incompatible/outdated if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR) @@ -235,4 +247,19 @@ namespace SHADE void SHGraphicsSystem::RemoveSegment(Handle segment) { } + + void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept + { + window = wind; + } + + SHRenderGraph const& SHGraphicsSystem::GetRenderGraph(void) const noexcept + { + return renderGraph; + } + + void SHGraphicsSystem::SHGraphicsSystemRoutine::Execute(double dt) noexcept + { + } + } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index e1dff379..d5d71450 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -21,9 +21,14 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/SHVulkanIncludes.h" #include "Graphics/MiddleEnd/PerFrame/SHRenderContext.h" #include "Graphics/RenderGraph/SHRenderGraph.h" +#include "ECS_Base/System/SHSystem.h" +#include "ECS_Base/System/SHSystemRoutine.h" +#include "Graphics/Descriptors/SHVkDescriptorPool.h" namespace SHADE { + + /*---------------------------------------------------------------------------------*/ /* Forward Declarations */ /*---------------------------------------------------------------------------------*/ @@ -61,8 +66,15 @@ namespace SHADE portions of the screen. */ /***********************************************************************************/ - class SHGraphicsSystem + class SH_API SHGraphicsSystem : public SHSystem { + public: + class SH_API SHGraphicsSystemRoutine : public SHSystemRoutine + { + public: + virtual void Execute(double dt) noexcept override; + }; + public: /*-----------------------------------------------------------------------------*/ /* Constants */ @@ -72,8 +84,15 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Constructor/Destructors */ /*-----------------------------------------------------------------------------*/ - SHGraphicsSystem(SHWindow& window); - ~SHGraphicsSystem(); + SHGraphicsSystem (void) = default; + ~SHGraphicsSystem(void) noexcept = default; + + /*-----------------------------------------------------------------------------*/ + /* SHSystem overrides */ + /*-----------------------------------------------------------------------------*/ + virtual void Init(void) override; + void Run (float dt) noexcept; + virtual void Exit(void) override; /*-----------------------------------------------------------------------------*/ /* Lifecycle Functions */ @@ -93,12 +112,22 @@ namespace SHADE Handle AddSegment(const VkViewport& viewport, Handle imageToUse); void RemoveSegment(Handle segment); + /*-----------------------------------------------------------------------------*/ + /* Setters */ + /*-----------------------------------------------------------------------------*/ + void SetWindow (SHWindow* wind) noexcept; + /*-----------------------------------------------------------------------------*/ /* Getters (Temporary) */ /*-----------------------------------------------------------------------------*/ Handle GetDevice() const { return device; } Handle GetSwapchain() const { return swapchain; } Handle GetSurface() const { return surface; } + Handle GetPhysicalDevice() const {return physicalDevice;} + Handle GetQueue() const { return graphicsQueue; } + Handle GetDescriptorPool() const { return descPool; } + SHRenderGraph const& GetRenderGraph (void) const noexcept; + //Handle GetRenderPass() const { return renderPass; } @@ -111,7 +140,8 @@ namespace SHADE Handle device; Handle surface; Handle swapchain; - Handle queue; + Handle graphicsQueue; + Handle descPool; //Handle renderPass; // Potentially bring out? std::vector screenSegments; SHRenderContext renderContext; @@ -125,5 +155,6 @@ namespace SHADE //std::vector renderers; SHRenderGraph renderGraph; + friend SHGraphicsSystemRoutine; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.h b/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.h index 7ed8cb82..04cea4e4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/PerFrame/SHRenderContext.h @@ -3,6 +3,7 @@ #include #include "SHPerFrameData.h" +#include "SH_API.h" namespace SHADE { @@ -16,7 +17,7 @@ namespace SHADE //! render context in SHADE engine has is that it requires users to call these explicitly in the middle end. While there //! is little reason the flow of the render context should deviate from its intended usage, we want to leave it up to //! users to explicitly call functions from here so we don't risk losing opportunities for different usage. - class SHRenderContext + class SH_API SHRenderContext { private: //! container of frame data. Note that the manager owns the data, but the frame data themselves do not own anything. diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp index 8179444f..6094958e 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHPipelineState.cpp @@ -117,7 +117,7 @@ namespace SHADE dirty = isDirty; } - std::tuple SHVertexInputState::GetInfoFromAttribFormat(SHAttribFormat attribFormat) const noexcept + std::tuple SHVertexInputState::GetInfoFromAttribFormat(SHAttribFormat attribFormat) const noexcept { switch (attribFormat) { @@ -138,6 +138,9 @@ namespace SHADE case SHAttribFormat::MAT_4D: return std::make_tuple(4, 16, vk::Format::eR32G32B32A32Sfloat); break; + + case SHAttribFormat::UINT32_1D: + return std::make_tuple(1, 4, vk::Format::eR32Uint); } return std::make_tuple(0, 0, vk::Format::eR32Sfloat); } diff --git a/SHADE_Engine/src/Graphics/Queues/SHVkQueue.cpp b/SHADE_Engine/src/Graphics/Queues/SHVkQueue.cpp index 9f8c529c..6ed6def6 100644 --- a/SHADE_Engine/src/Graphics/Queues/SHVkQueue.cpp +++ b/SHADE_Engine/src/Graphics/Queues/SHVkQueue.cpp @@ -5,6 +5,7 @@ #include "Graphics/Synchronization/SHVkSemaphore.h" #include "Graphics/Synchronization/SHVkFence.h" #include "Graphics/Commands/SHVkCommandBuffer.h" +#include "Graphics/Swapchain/SHVkSwapchain.h" namespace SHADE @@ -31,14 +32,10 @@ namespace SHADE } - vk::Queue SHVkQueue::GetVkQueue(void) const noexcept + void SHVkQueue::SubmitCommandBuffer(std::initializer_list> cmdBuffers, std::initializer_list> signalSems /*= {}*/, std::initializer_list> waitSems /*= {}*/, vk::PipelineStageFlags waitDstStageMask /*= {}*/, Handle const& optionalFence /*= {}*/) noexcept { - return vkQueue; - } - - void SHVkQueue::SubmitCommandBuffer(std::initializer_list> cmdBuffers, std::initializer_list> signalSems /*= {}*/, std::initializer_list> waitSems /*= {}*/, vk::PipelineStageFlagBits waitDstStageMask /*= {}*/, Handle const& optionalFence /*= {}*/) noexcept - { - std::vector vkWaitSems{ waitSems.size() }; + // prepare wait sems + std::array vkWaitSems{ }; uint32_t i = 0; for (auto& sem : waitSems) { @@ -46,7 +43,8 @@ namespace SHADE ++i; } - std::vector vkSignalSems{ signalSems.size() }; + // prepare signal sems + std::array vkSignalSems{ }; i = 0; for (auto& sem : signalSems) { @@ -54,33 +52,76 @@ namespace SHADE ++i; } - std::vector vkCmdBuffers{ cmdBuffers.size() }; + // prepare cmd buffers + std::array vkCmdBuffers{ }; i = 0; for (auto& cmdBuffer : cmdBuffers) { + // Check if command buffer is in executable state + if (!cmdBuffer->IsReadyToSubmit()) + { + SHLOG_ERROR("Command buffer is not in executable state. Cannot submit command buffer. "); + return; + } + vkCmdBuffers[i] = cmdBuffer->GetVkCommandBuffer(); ++i; } - vk::PipelineStageFlags mask = waitDstStageMask; - + // Prepare submit info vk::SubmitInfo submitInfo { - .waitSemaphoreCount = static_cast(vkWaitSems.size()), + .waitSemaphoreCount = static_cast(waitSems.size()), .pWaitSemaphores = vkWaitSems.data(), - .pWaitDstStageMask = &mask, - .commandBufferCount = static_cast(vkCmdBuffers.size()), + .pWaitDstStageMask = &waitDstStageMask, + .commandBufferCount = static_cast(cmdBuffers.size()), .pCommandBuffers = vkCmdBuffers.data(), - .signalSemaphoreCount = static_cast(vkSignalSems.size()), + .signalSemaphoreCount = static_cast(signalSems.size()), .pSignalSemaphores = vkSignalSems.data(), }; - // #BackEndTest: Submit the queue + // Submit the queue if (auto result = vkQueue.submit(1, &submitInfo, (optionalFence) ? optionalFence->GetVkFence() : nullptr); result != vk::Result::eSuccess) { SHVulkanDebugUtil::ReportVkError(result, "Failed to submit command buffer. "); } + else // if success + { + // Change all command buffers to pending state + for (Handle cmdBuffer : cmdBuffers) + { + cmdBuffer->HandlePostSubmit(); + } + } + } + vk::Result SHVkQueue::Present(Handle const& swapchain, std::initializer_list> waitSems, uint32_t frameIndex) noexcept + { + vk::PresentInfoKHR presentInfo{}; + + // prepare wait sems + std::array vkWaitSems{ }; + uint32_t i = 0; + for (auto& sem : waitSems) + { + vkWaitSems[i] = sem->GetVkSem(); + ++i; + } + + // prepare presentation information + presentInfo.waitSemaphoreCount = static_cast(waitSems.size()); + presentInfo.pWaitSemaphores = vkWaitSems.data(); + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapchain->GetVkSwapchain(); + presentInfo.pImageIndices = &frameIndex; + + // Present swapchain image. + auto result = vkQueue.presentKHR(&presentInfo); + if (result != vk::Result::eSuccess) + { + SHLOGV_ERROR ("Failed to present swapchain image. "); + } + return result; } } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Queues/SHVkQueue.h b/SHADE_Engine/src/Graphics/Queues/SHVkQueue.h index 203ae59e..042bc4bb 100644 --- a/SHADE_Engine/src/Graphics/Queues/SHVkQueue.h +++ b/SHADE_Engine/src/Graphics/Queues/SHVkQueue.h @@ -11,6 +11,7 @@ namespace SHADE class SHVkCommandBuffer; class SHVkFence; class SHVkSemaphore; + class SHVkSwapchain; enum class SH_QUEUE_FAMILY_ARRAY_INDEX : std::size_t { @@ -45,9 +46,9 @@ namespace SHADE public: SHVkQueue(vk::Queue inVkQueue, SHQueueFamilyIndex parent, Handle const& inLogicalDeviceHdl) noexcept; - vk::Queue GetVkQueue(void) const noexcept; - void SubmitCommandBuffer(std::initializer_list> cmdBuffers, std::initializer_list> signalSems = {}, std::initializer_list> waitSems = {}, vk::PipelineStageFlagBits waitDstStageMask = {}, Handle const& fence = {}) noexcept; + void SubmitCommandBuffer (std::initializer_list> cmdBuffers, std::initializer_list> signalSems = {}, std::initializer_list> waitSems = {}, vk::PipelineStageFlags waitDstStageMask = {}, Handle const& fence = {}) noexcept; + vk::Result Present (Handle const& swapchain, std::initializer_list> waitSems, uint32_t frameIndex) noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index a86913e4..a2647b74 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -182,12 +182,12 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Destructor for resource. - - */ + + */ /***************************************************************************/ SHRenderGraphResource::~SHRenderGraphResource(void) noexcept { @@ -195,37 +195,38 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Subpass non-default constructor. Simply initializes variables. - + \param mapping Mapping from a resource handle to an attachment reference referencing the resource. \param resources A mapping from string to render graph resource. - - */ + + */ /***************************************************************************/ - SHRenderGraphNode::SHSubpass::SHSubpass(std::unordered_map const* mapping, std::unordered_map> const* resources) noexcept + SHRenderGraphNode::SHSubpass::SHSubpass(Handle const& parent, std::unordered_map const* mapping, std::unordered_map> const* resources) noexcept : resourceAttachmentMapping{ mapping } , ptrToResources{ resources } + , parentNode{ parent } { } /***************************************************************************/ - /*! - + /*! + \brief Move constructor for subpass. - + \param rhs The subpass the move from. - - */ + + */ /***************************************************************************/ SHRenderGraphNode::SHSubpass::SHSubpass(SHSubpass&& rhs) noexcept : colorReferences{ std::move(rhs.colorReferences) } @@ -238,15 +239,15 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Move assignment operator for subpass. - + \param rhs subpass to move from. - - */ + + */ /***************************************************************************/ SHRenderGraphNode::SHSubpass& SHRenderGraphNode::SHSubpass::operator=(SHSubpass&& rhs) noexcept { @@ -263,16 +264,16 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief - Adds a color output to a subpass. Takes in a string and finds the + Adds a color output to a subpass. Takes in a string and finds the attachment index to create the vk::SubpassReference. - + \param resourceToReference Resource name to find resource to attach. - - */ + + */ /***************************************************************************/ void SHRenderGraphNode::SHSubpass::AddColorOutput(std::string resourceToReference) noexcept { @@ -280,8 +281,8 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Adds a depth output to a subpass. Takes in a string and finds the attachment index to create the vk::SubpassReference. @@ -292,8 +293,8 @@ namespace SHADE \param attachmentDescriptionType Depending on the type of the resource, initialize the image layout appropriately. - - */ + + */ /***************************************************************************/ void SHRenderGraphNode::SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType) noexcept { @@ -317,8 +318,8 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Adds a input output to a subpass. Takes in a string and finds the attachment index to create the vk::SubpassReference. @@ -326,21 +327,53 @@ namespace SHADE \param resourceToReference Resource name to find resource to attach. - */ + */ /***************************************************************************/ void SHRenderGraphNode::SHSubpass::AddInput(std::string resourceToReference) noexcept { inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal }); } + void SHRenderGraphNode::SHSubpass::Execute(Handle& commandBuffer) noexcept + { + // Draw all the batches + + // Draw all the exterior draw calls + for (auto& drawCall : exteriorDrawCalls) + { + drawCall(commandBuffer); + } + } + + void SHRenderGraphNode::SHSubpass::AddExteriorDrawCalls(std::function&)> const& newDrawCall) noexcept + { + exteriorDrawCalls.push_back(newDrawCall); + } + /***************************************************************************/ - /*! - + /*! + \brief - Creates a renderpass for the node. Uses subpass and attachment + Getter for parent renderpass. + + \return + Returns the parent renderpass the subpass belongs to. + + */ + /***************************************************************************/ + Handle const& SHRenderGraphNode::SHSubpass::GetParentNode(void) const noexcept + { + return parentNode; + } + + /***************************************************************************/ + /*! + + \brief + Creates a renderpass for the node. Uses subpass and attachment descriptions already configured beforehand in the render graph. - - */ + + */ /***************************************************************************/ void SHRenderGraphNode::CreateRenderpass(void) noexcept { @@ -348,12 +381,12 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Creates a framebuffer from the images used in the renderpass. - - */ + + */ /***************************************************************************/ void SHRenderGraphNode::CreateFramebuffer(void) noexcept { @@ -426,10 +459,10 @@ namespace SHADE // We set this to clear first. If later we find out that some predecessor is writing to the same attachment, // we set the pred's storeOp to eStore and "this" loadOp to eLoad. newDesc.loadOp = vk::AttachmentLoadOp::eClear; - newDesc.storeOp = vk::AttachmentStoreOp::eDontCare; + newDesc.storeOp = vk::AttachmentStoreOp::eStore; newDesc.stencilLoadOp = vk::AttachmentLoadOp::eClear; - newDesc.stencilStoreOp = vk::AttachmentStoreOp::eDontCare; + newDesc.stencilStoreOp = vk::AttachmentStoreOp::eStore; newDesc.format = attResources[i]->resourceFormat; @@ -489,18 +522,18 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Add subpasses to the renderpass and returns a reference to it. - + \param subpassName Name of the subpass. - + \return Handle to the new subpass. - - */ + + */ /***************************************************************************/ Handle SHRenderGraphNode::AddSubpass(std::string subpassName) noexcept { @@ -512,11 +545,44 @@ namespace SHADE } // Add subpass to container and create mapping for it - subpasses.emplace_back(resourceManager.Create(&resourceAttachmentMapping, ptrToResources)); - subpassIndexing.try_emplace(subpassName, subpasses.size() - 1); + subpasses.emplace_back(resourceManager.Create(GetHandle(), &resourceAttachmentMapping, ptrToResources)); + subpassIndexing.try_emplace(subpassName, static_cast(subpasses.size()) - 1u); return subpasses.at(subpassIndexing[subpassName]); } + void SHRenderGraphNode::Execute(Handle& commandBuffer, uint32_t frameIndex) noexcept + { + frameIndex = (framebuffers.size() > 1) ? frameIndex : 0; + commandBuffer->BeginRenderpass(renderpass, framebuffers[frameIndex]); + + for (uint32_t i = 0; i < subpasses.size(); ++i) + { + subpasses[i]->Execute(commandBuffer); + + // Go to next subpass if not last subpass + if (i != subpasses.size() - 1) + commandBuffer->NextSubpass(); + } + + commandBuffer->EndRenderpass(); + } + + /***************************************************************************/ + /*! + + \brief + Get the renderpass from the node. + + \return + Handle to the renderpass. + + */ + /***************************************************************************/ + Handle SHRenderGraphNode::GetRenderpass(void) const noexcept + { + return renderpass; + } + /***************************************************************************/ /*! @@ -544,7 +610,7 @@ namespace SHADE */ /***************************************************************************/ - void SHRenderGraph::AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w /*= static_cast(-1)*/, uint32_t h /*= static_cast(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint32_t levels /*= 1*/, vk::ImageCreateFlagBits createFlags /*= {}*/) + void SHRenderGraph::AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w /*= static_cast(-1)*/, uint32_t h /*= static_cast(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageCreateFlagBits createFlags /*= {}*/) { // If we set to if (w == static_cast(-1) && h == static_cast(-1)) @@ -647,16 +713,16 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Configures the supasses; mainly the subpass descriptions and the subpass dependencies involved between subpasses. - - - \return - - */ + + + \return + + */ /***************************************************************************/ void SHRenderGraph::ConfigureSubpasses(void) noexcept { @@ -785,12 +851,12 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Simply loops through all nodes and create renderpasses. - - */ + + */ /***************************************************************************/ void SHRenderGraph::ConfigureRenderpasses(void) noexcept { @@ -801,12 +867,12 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Simply loops through all nodes and create framebuffers. - - */ + + */ /***************************************************************************/ void SHRenderGraph::ConfigureFramebuffers(void) noexcept { @@ -820,7 +886,25 @@ namespace SHADE /*! \brief - Init function. Doesn't do much except initialize device and swapchain + Configures command pools and command buffers. + + */ + /***************************************************************************/ + void SHRenderGraph::ConfigureCommands(void) noexcept + { + commandPool = logicalDeviceHdl->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true); + commandBuffers.resize(static_cast(swapchainHdl->GetNumImages())); + for (auto& cmdBuffer : commandBuffers) + { + cmdBuffer = commandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); + } + } + + /***************************************************************************/ + /*! + + \brief + Init function. Doesn't do much except initialize device and swapchain handle. Graph should start out empty. \param swapchain @@ -838,15 +922,15 @@ namespace SHADE } /***************************************************************************/ - /*! - + /*! + \brief Default ctor, doesn't do much. - - - \return - - */ + + + \return + + */ /***************************************************************************/ SHRenderGraph::SHRenderGraph(void) noexcept : logicalDeviceHdl{ } @@ -913,7 +997,7 @@ namespace SHADE } nodes.emplace_back(resourceManager.Create(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(resources), std::move(predecessors), &graphResources)); - nodeIndexing.emplace(nodeName, nodes.size() - 1); + nodeIndexing.emplace(nodeName, static_cast(nodes.size()) - 1u); return nodes.at(nodeIndexing[nodeName]); } @@ -936,6 +1020,37 @@ namespace SHADE ConfigureSubpasses(); ConfigureRenderpasses(); ConfigureFramebuffers(); + ConfigureCommands(); + } + + void SHRenderGraph::Execute(uint32_t frameIndex) noexcept + { + commandPool->Reset(); + + auto& cmdBuffer = commandBuffers[frameIndex]; + cmdBuffer->BeginRecording(); + + cmdBuffer->SetviewportScissor(1920.0f, 1080.0f, 1920, 1080); + + for (auto& node : nodes) + { + node->Execute(commandBuffers[frameIndex], frameIndex); + } + + cmdBuffer->EndRecording(); + } + + Handle SHRenderGraph::GetNode(std::string const& nodeName) const noexcept + { + if (nodeIndexing.contains(nodeName)) + return nodes[nodeIndexing.at(nodeName)]; + + return {}; + } + + Handle const& SHRenderGraph::GetCommandBuffer(uint32_t frameIndex) const noexcept + { + return commandBuffers[frameIndex]; } } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h index f81e84bd..719c2d46 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.h @@ -3,6 +3,7 @@ #include "Graphics/Renderpass/SHVkRenderpass.h" #include "Resource/ResourceLibrary.h" +#include "SH_API.h" #include #include @@ -15,6 +16,8 @@ namespace SHADE class SHVkImage; class SHVkImageView; class SHVkFramebuffer; + class SHVkCommandPool; + class SHVkCommandBuffer; // Used for attachment description creation for renderpass node enum class SH_ATT_DESC_TYPE @@ -26,7 +29,7 @@ namespace SHADE DEPTH_STENCIL, }; - class SHRenderGraphResource + class SH_API SHRenderGraphResource { private: /*-----------------------------------------------------------------------*/ @@ -72,25 +75,44 @@ namespace SHADE friend class SHRenderGraph; }; - class SHRenderGraphNode + class SH_API SHRenderGraphNode : public ISelfHandle { public: - class SHSubpass + class SH_API SHSubpass { public: - SHSubpass(std::unordered_map const* mapping, std::unordered_map> const* ptrToResources) noexcept; + /*-----------------------------------------------------------------------*/ + /* CTORS AND DTORS */ + /*-----------------------------------------------------------------------*/ + SHSubpass(Handle const& parent, std::unordered_map const* mapping, std::unordered_map> const* ptrToResources) noexcept; SHSubpass(SHSubpass&& rhs) noexcept; SHSubpass& operator=(SHSubpass&& rhs) noexcept; + /*-----------------------------------------------------------------------*/ + /* PUBLIC MEMBER FUNCTIONS */ + /*-----------------------------------------------------------------------*/ + // Preparation functions void AddColorOutput (std::string resourceToReference) noexcept; void AddDepthOutput (std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType = SH_ATT_DESC_TYPE::DEPTH_STENCIL) noexcept; void AddInput (std::string resourceToReference) noexcept; + + // Runtime functions + void Execute (Handle& commandBuffer) noexcept; + void AddExteriorDrawCalls (std::function&)> const& newDrawCall) noexcept; + + /*-----------------------------------------------------------------------*/ + /* GETTERS AND SETTERS */ + /*-----------------------------------------------------------------------*/ + Handle const& GetParentNode (void) const noexcept; private: /*---------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ /*---------------------------------------------------------------------*/ + //! The parent renderpass that this subpass belongs to + Handle parentNode; + //! Color attachments std::vector colorReferences; @@ -106,6 +128,14 @@ namespace SHADE //! Pointer to resources in the render graph (for getting handle IDs) std::unordered_map> const* ptrToResources; + //! Sometimes there exists entities that we want to render onto a render target + //! but don't want it to come from the batching system. An example would be ImGUI. + //! For these entities we want to link a function from the outside and draw them + //! after we draw everything from the batch. Because of this, these draw calls + //! are always the last things drawn, so DO NOT USE THIS FUNCTIONALITY FOR ANYTHING + //! COMPLEX. + std::vector&)>> exteriorDrawCalls; + friend class SHRenderGraphNode; friend class SHRenderGraph; }; @@ -179,11 +209,17 @@ namespace SHADE /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ Handle AddSubpass (std::string subpassName) noexcept; + void Execute (Handle& commandBuffer, uint32_t frameIndex) noexcept; + + /*-----------------------------------------------------------------------*/ + /* SETTERS AND GETTERS */ + /*-----------------------------------------------------------------------*/ + Handle GetRenderpass (void) const noexcept; friend class SHRenderGraph; }; - class SHRenderGraph + class SH_API SHRenderGraph { private: /*-----------------------------------------------------------------------*/ @@ -193,6 +229,7 @@ namespace SHADE void ConfigureSubpasses (void) noexcept; void ConfigureRenderpasses (void) noexcept; void ConfigureFramebuffers (void) noexcept; + void ConfigureCommands (void) noexcept; /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ @@ -214,6 +251,13 @@ namespace SHADE //! Resource library for graph handles ResourceManager resourceManager; + //! Command pool for the render graph + Handle commandPool; + + //! Command buffers for the render graph + std::vector> commandBuffers; + + public: /*-----------------------------------------------------------------------*/ /* CTORS AND DTORS */ @@ -223,10 +267,17 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ - void Init (Handle const& logicalDevice, Handle const& swapchain) noexcept; - void AddResource(std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast(-1), uint32_t h = static_cast(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint32_t levels = 1, vk::ImageCreateFlagBits createFlags = {}); - Handle AddNode (std::string nodeName, std::initializer_list resourceNames, std::initializer_list predecessorNodes) noexcept; - void Generate (void) noexcept; + void Init (Handle const& logicalDevice, Handle const& swapchain) noexcept; + void AddResource (std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast(-1), uint32_t h = static_cast(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageCreateFlagBits createFlags = {}); + Handle AddNode (std::string nodeName, std::initializer_list resourceNames, std::initializer_list predecessorNodes) noexcept; + void Generate (void) noexcept; + void Execute (uint32_t frameIndex) noexcept; + + /*-----------------------------------------------------------------------*/ + /* SETTERS AND GETTERS */ + /*-----------------------------------------------------------------------*/ + Handle GetNode (std::string const& nodeName) const noexcept; + Handle const& GetCommandBuffer (uint32_t frameIndex) const noexcept; }; } diff --git a/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.cpp b/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.cpp index 53e3326e..29de5954 100644 --- a/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.cpp +++ b/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.cpp @@ -29,11 +29,17 @@ namespace SHADE /***************************************************************************/ SHVkRenderpass::SHVkRenderpass(Handle const& inLogicalDeviceHdl, std::span const vkDescriptions, std::vector const& subpasses) noexcept : logicalDeviceHdl {inLogicalDeviceHdl} + , numAttDescs {static_cast(vkDescriptions.size())} , clearColors{} { - // TODO: temporary only - clearColors[0].color = { {{0.0f, 0.0f, 0.0f, 1.0f}} }; - clearColors[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); + for (uint32_t i = 0; i < vkDescriptions.size(); ++i) + { + if (SHVkUtil::IsDepthStencilAttachment(vkDescriptions[i].format)) + clearColors[i].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); + else + clearColors[i].color = { {{0.0f, 0.0f, 0.0f, 1.0f}} }; + } + vk::RenderPassCreateInfo renderPassCreateInfo{}; std::vector subpassDeps; @@ -164,11 +170,16 @@ namespace SHADE SHVkRenderpass::SHVkRenderpass(Handle const& inLogicalDeviceHdl, std::span const vkDescriptions, std::span const spDescs, std::span const spDeps) noexcept : logicalDeviceHdl{ inLogicalDeviceHdl } + , numAttDescs{ static_cast(vkDescriptions.size()) } , clearColors{} { - // TODO: temporary only - clearColors[0].color = { {{0.0f, 0.0f, 0.0f, 1.0f}} }; - clearColors[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); + for (uint32_t i = 0; i < vkDescriptions.size(); ++i) + { + if (SHVkUtil::IsDepthStencilAttachment(vkDescriptions[i].format)) + clearColors[i].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); + else + clearColors[i].color = { {{0.0f, 0.0f, 0.0f, 1.0f}} }; + } subpassDescriptions.resize (spDescs.size()); for (uint32_t i = 0; i < subpassDescriptions.size(); ++i) diff --git a/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.h b/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.h index 6ffd6c38..b0ae7445 100644 --- a/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.h +++ b/SHADE_Engine/src/Graphics/Renderpass/SHVkRenderpass.h @@ -17,7 +17,7 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* STATIC CONSTEXPR VALUES */ /*-----------------------------------------------------------------------*/ - static constexpr uint32_t NUM_CLEAR_COLORS = 2; + static constexpr uint32_t NUM_CLEAR_COLORS = 10; /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ @@ -34,6 +34,9 @@ namespace SHADE //! Clear colors for the color and depth std::array clearColors; + // number of attachment descriptions + uint32_t numAttDescs; + public: /*-----------------------------------------------------------------------*/ /* CTOR AND DTOR */ diff --git a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp index 8beb7d98..1e5fb074 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp +++ b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.cpp @@ -189,7 +189,7 @@ namespace SHADE Handle SHShaderDescriptorBindingInfo::GetShaderBlockInterface(uint32_t set, uint32_t binding) const noexcept { - SHShaderDescriptorBindingInfo::BindingAndSetHash hash = binding; + BindingAndSetHash hash = binding; hash |= static_cast(set) << 32; if (blockInterfaces.contains(hash)) return blockInterfaces.at(hash); diff --git a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h index 1250b54f..88c7a2e1 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h +++ b/SHADE_Engine/src/Graphics/Shaders/SHShaderReflected.h @@ -9,11 +9,10 @@ namespace SHADE { + using BindingAndSetHash = uint64_t; + struct SHShaderDescriptorBindingInfo { - public: - using BindingAndSetHash = uint64_t; - private: /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ diff --git a/SHADE_Engine/src/Graphics/Swapchain/SHVkSwapchain.cpp b/SHADE_Engine/src/Graphics/Swapchain/SHVkSwapchain.cpp index 4dd6f9d6..f46d5d17 100644 --- a/SHADE_Engine/src/Graphics/Swapchain/SHVkSwapchain.cpp +++ b/SHADE_Engine/src/Graphics/Swapchain/SHVkSwapchain.cpp @@ -19,10 +19,14 @@ namespace SHADE vkPresentModes = physicalDeviceHdl->GetVkPhysicalDevice().getSurfacePresentModesKHR(surfaceHdl->GetVkSurface()); if (vkSurfaceFormats.size() == 0) + { SHLOG_ERROR("Failed to get surface formats from the physical device. "); + } if (vkPresentModes.size() == 0) + { SHLOG_ERROR("Failed to get present modes from the physical device. "); + } } vk::SurfaceFormatKHR SHVkSwapchain::ChooseSwapSurfaceFormat(std::vector const& surfaceFormats) const noexcept diff --git a/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h b/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h index fd8ee3d1..b216f5f4 100644 --- a/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h +++ b/SHADE_Engine/src/Graphics/VertexDescriptors/SHVertexAttribute.h @@ -18,7 +18,10 @@ namespace SHADE // that a mat2 can be interpreted as (x, y, x, y), (o, o, o, o) instead of (x, y, o, o), (o, o, o, o)? MAT_2D, MAT_3D, - MAT_4D + MAT_4D, + + // integer formats + UINT32_1D, }; struct SHVertexAttribute diff --git a/SHADE_Engine/src/Graphics/Windowing/SHWindow.cpp b/SHADE_Engine/src/Graphics/Windowing/SHWindow.cpp index 6ac6672b..957ffc34 100644 --- a/SHADE_Engine/src/Graphics/Windowing/SHWindow.cpp +++ b/SHADE_Engine/src/Graphics/Windowing/SHWindow.cpp @@ -222,7 +222,7 @@ namespace SHADE return true; { MSG Message; - while (PeekMessageW(&Message, NULL, 0, 0, PM_REMOVE)) + while (PeekMessageW(&Message, wndHWND, 0, 0, PM_REMOVE)) { if (WM_QUIT == Message.message) { diff --git a/SHADE_Engine/src/Resource/Handle.h b/SHADE_Engine/src/Resource/Handle.h index 34662112..afaec8e1 100644 --- a/SHADE_Engine/src/Resource/Handle.h +++ b/SHADE_Engine/src/Resource/Handle.h @@ -139,7 +139,7 @@ namespace SHADE /*-----------------------------------------------------------------------------*/ /* Data Members */ /*-----------------------------------------------------------------------------*/ - ResourceLibrary* library; + ResourceLibrary* library = nullptr; /*-----------------------------------------------------------------------------*/ /* Friend Declarations */ diff --git a/SHADE_Engine/src/Resource/ResourceLibrary.h b/SHADE_Engine/src/Resource/ResourceLibrary.h index b05dc499..01a78d16 100644 --- a/SHADE_Engine/src/Resource/ResourceLibrary.h +++ b/SHADE_Engine/src/Resource/ResourceLibrary.h @@ -69,7 +69,7 @@ namespace SHADE /* Helper Functions */ /*-----------------------------------------------------------------------------*/ void assertHandleValid(Handle handle) const; - int getAvailableFreeIndex(); + uint32_t getAvailableFreeIndex(); }; /// diff --git a/SHADE_Engine/src/Resource/ResourceLibrary.hpp b/SHADE_Engine/src/Resource/ResourceLibrary.hpp index 2ad856c6..9aa72ead 100644 --- a/SHADE_Engine/src/Resource/ResourceLibrary.hpp +++ b/SHADE_Engine/src/Resource/ResourceLibrary.hpp @@ -35,13 +35,13 @@ namespace SHADE } else { - handle.id.Data.Version = 0; - versionCounts.insert(handle.id.Data.Index, handle.id.Data.Version); + handle.id.Data.Version = 0U; + versionCounts.insert(static_cast(handle.id.Data.Index), handle.id.Data.Version); } handle.library = this; // Create the resource - [[maybe_unused]] T& obj = objects.insert(handle.id.Data.Index, std::forward(args) ...); + [[maybe_unused]] T& obj = objects.insert(static_cast(handle.id.Data.Index), std::forward(args) ...); // Handling SelfHandle assignment if constexpr (std::is_base_of_v, T>) @@ -89,7 +89,7 @@ namespace SHADE } template - inline int ResourceLibrary::getAvailableFreeIndex() + inline uint32_t ResourceLibrary::getAvailableFreeIndex() { // Get from the free list if present if (!freeList.empty()) diff --git a/SHADE_Engine/src/Resource/SparseSet.hpp b/SHADE_Engine/src/Resource/SparseSet.hpp index 70e15f29..5afcdee7 100644 --- a/SHADE_Engine/src/Resource/SparseSet.hpp +++ b/SHADE_Engine/src/Resource/SparseSet.hpp @@ -56,7 +56,7 @@ namespace SHADE throw std::invalid_argument("An element at this index does not exist!"); // Swap with the last element - const int BACK_IDX = denseArray.size() - 1; + const auto BACK_IDX = denseArray.size() - 1; std::swap(denseArray[sparseArray[idx]], denseArray.back()); denseArray.pop_back(); // Update the sparse set by swapping the indices @@ -110,7 +110,7 @@ namespace SHADE // We need to resize the array if (idx >= sparseArray.size()) { - const int NEW_SIZE = idx + 1; + const auto NEW_SIZE = idx + 1; sparseArray.resize(NEW_SIZE, INVALID); inverseSparseArray.resize(NEW_SIZE, INVALID); } @@ -123,7 +123,7 @@ namespace SHADE auto& insertedElem = denseArray.emplace_back(std::forward(args) ...); // Update sparse and inverse sparse arrays - const index_type DENSE_IDX = denseArray.size() - 1; + const auto DENSE_IDX = static_cast(denseArray.size()) - 1; sparseArray[idx] = DENSE_IDX; inverseSparseArray[DENSE_IDX] = idx; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 9c99fb5a..9fddf10e 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -14,7 +14,7 @@ #include "SHSceneGraph.h" // Project Headers -#include "ECS_Base/System/SHEntityManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" #include "Tools/SHLogger.h" #include "Tools/SHException.h" diff --git a/SHADE_Engine/src/Scene/SHSceneManager.cpp b/SHADE_Engine/src/Scene/SHSceneManager.cpp index a60df922..d5223af8 100644 --- a/SHADE_Engine/src/Scene/SHSceneManager.cpp +++ b/SHADE_Engine/src/Scene/SHSceneManager.cpp @@ -10,11 +10,11 @@ *********************************************************************/ #include "SHpch.h" #include "SHSceneManager.h" -#include "ECS_Base/System/SHComponentManager.h" +#include "ECS_Base/Managers/SHComponentManager.h" //#include "Input/SHInputManager.h" //#include "Rendering/Window/SHRenderingWindow.h" -#include "ECS_Base/System/SHEntityManager.h" -#include "ECS_Base/System/SHSystemManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" +#include "ECS_Base/Managers/SHSystemManager.h" //#include "FRC/SHFrameRateController.h" //#include "ECS_Base/System/SHApplication.h" diff --git a/SHADE_Engine/src/Scripting/SHDotNetRuntime.cpp b/SHADE_Engine/src/Scripting/SHDotNetRuntime.cpp index 89603524..6226949e 100644 --- a/SHADE_Engine/src/Scripting/SHDotNetRuntime.cpp +++ b/SHADE_Engine/src/Scripting/SHDotNetRuntime.cpp @@ -126,7 +126,7 @@ namespace SHADE throwIfFailed("[DotNetRuntime] Failed to initialize CoreCLR.", result); initialised = true; - SHLOG_INFO("[DotNetRuntime] Successfully loaded the .NET 6.0 Runtime."); + SHLOG_INFO("[DotNetRuntime] Successfully loaded the .NET 5.0 Runtime."); } void SHDotNetRuntime::Exit() @@ -144,7 +144,7 @@ namespace SHADE domainId = 0; initialised = false; - SHLOG_INFO("[DotNetRuntime] Successfully shut down the .NET 6.0 Runtime."); + SHLOG_INFO("[DotNetRuntime] Successfully shut down the .NET 5.0 Runtime."); } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp index 47c722dd..09f6ecec 100644 --- a/SHADE_Engine/src/Scripting/SHScriptEngine.cpp +++ b/SHADE_Engine/src/Scripting/SHScriptEngine.cpp @@ -190,7 +190,7 @@ namespace SHADE } // Prepare directory (delete useless files) - deleteFolder("net6.0"); + deleteFolder("net5.0"); deleteFolder("ref"); deleteFolder("../SHADE_Scripting"); deleteFolder("../obj"); @@ -236,7 +236,7 @@ namespace SHADE static std::string_view FILE_CONTENTS = "\n\ \n\ - net6.0\n\ + net5.0\n\ x64\n\ Release;Debug\n\ \n\ diff --git a/SHADE_Managed/premake5.lua b/SHADE_Managed/premake5.lua index 092e92af..e50e9e86 100644 --- a/SHADE_Managed/premake5.lua +++ b/SHADE_Managed/premake5.lua @@ -2,7 +2,7 @@ project "SHADE_Managed" kind "SharedLib" language "C++" clr "NetCore" - dotnetframework "net6.0" + dotnetframework "net5.0" cppdialect "C++17" targetdir (outputdir) objdir (interdir) diff --git a/SHADE_Managed/src/Engine/ECS.cxx b/SHADE_Managed/src/Engine/ECS.cxx index 5aceceee..e4405006 100644 --- a/SHADE_Managed/src/Engine/ECS.cxx +++ b/SHADE_Managed/src/Engine/ECS.cxx @@ -20,7 +20,7 @@ of DigiPen Institute of Technology is prohibited. #include #include // External Dependencies -#include "ECS_Base/System/SHEntityManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" // Project Headers #include "Utility/Convert.hxx" #include "Utility/Debug.hxx" diff --git a/SHADE_Managed/src/Engine/ECS.h++ b/SHADE_Managed/src/Engine/ECS.h++ index e5ede5f2..daaa859f 100644 --- a/SHADE_Managed/src/Engine/ECS.h++ +++ b/SHADE_Managed/src/Engine/ECS.h++ @@ -17,8 +17,8 @@ of DigiPen Institute of Technology is prohibited. // Primary Include #include "ECS.hxx" // External Dependencies -#include "ECS_Base/System/SHComponentManager.h" -#include "ECS_Base/System/SHEntityManager.h" +#include "ECS_Base/Managers/SHComponentManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" namespace SHADE { diff --git a/SHADE_Managed/src/Engine/ECS.hxx b/SHADE_Managed/src/Engine/ECS.hxx index 72c88e11..da73f14c 100644 --- a/SHADE_Managed/src/Engine/ECS.hxx +++ b/SHADE_Managed/src/Engine/ECS.hxx @@ -15,7 +15,7 @@ of DigiPen Institute of Technology is prohibited. #pragma once // External Dependencies -#include "ECS_Base/System/SHComponentManager.h" +#include "ECS_Base/Managers/SHComponentManager.h" // Project Includes #include "Components/Component.hxx" diff --git a/SHADE_Managed/src/Engine/Entity.cxx b/SHADE_Managed/src/Engine/Entity.cxx index ba1a31c6..22e8a8c2 100644 --- a/SHADE_Managed/src/Engine/Entity.cxx +++ b/SHADE_Managed/src/Engine/Entity.cxx @@ -17,7 +17,7 @@ of DigiPen Institute of Technology is prohibited. // Primary Header #include "Entity.hxx" // External Dependencies -#include "ECS_Base/System/SHEntityManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" namespace SHADE { diff --git a/SHADE_Managed/src/Engine/GameObject.cxx b/SHADE_Managed/src/Engine/GameObject.cxx index 3896fac5..1fbc3b4a 100644 --- a/SHADE_Managed/src/Engine/GameObject.cxx +++ b/SHADE_Managed/src/Engine/GameObject.cxx @@ -16,7 +16,7 @@ of DigiPen Institute of Technology is prohibited. // Primary Header #include "GameObject.hxx" // External Dependencies -#include "ECS_Base/System/SHEntityManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" // Project Headers #include "ECS.hxx" #include "Scripts/ScriptStore.hxx" @@ -52,7 +52,7 @@ namespace SHADE } bool GameObject::IsActiveSelf::get() { - return GetNativeEntity().isActive; + return GetNativeEntity().GetActive(); } bool GameObject::IsActiveInHierarchy::get() { @@ -68,7 +68,7 @@ namespace SHADE } void GameObject::SetActive(bool active) { - GetNativeEntity().isActive = active; + GetNativeEntity().SetActive(active); } /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Scripts/ScriptStore.cxx b/SHADE_Managed/src/Scripts/ScriptStore.cxx index 9a9eff54..d30cad6b 100644 --- a/SHADE_Managed/src/Scripts/ScriptStore.cxx +++ b/SHADE_Managed/src/Scripts/ScriptStore.cxx @@ -19,7 +19,7 @@ of DigiPen Institute of Technology is prohibited. // Standard Libraries #include // External Dependencies -#include "ECS_Base/System/SHEntityManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" // Project Headers #include "Utility/Debug.hxx" #include "Utility/Convert.hxx" @@ -668,6 +668,6 @@ namespace SHADE throw gcnew System::InvalidOperationException("Attempted to get native Component to an invalid Entity."); // Check active state - return nativeEntity->isActive; + return nativeEntity->GetActive(); } } diff --git a/SHADE_Managed/src/Utility/Convert.cxx b/SHADE_Managed/src/Utility/Convert.cxx index 8a8aff70..d222fbb3 100644 --- a/SHADE_Managed/src/Utility/Convert.cxx +++ b/SHADE_Managed/src/Utility/Convert.cxx @@ -17,7 +17,7 @@ of DigiPen Institute of Technology is prohibited. // Primary Header #include "Convert.hxx" // External Dependencies -#include "ECS_Base/System//SHEntityManager.h" +#include "ECS_Base/Managers/SHEntityManager.h" #include namespace SHADE