Merge remote-tracking branch 'origin/main' into SP3-12-SceneGraph
This commit is contained in:
commit
45d526c0e0
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -19,10 +19,11 @@ echo "L - yamlcpp"
|
|||
echo "M - SDL"
|
||||
echo "N - dotnet"
|
||||
echo "O - tinyddsloader"
|
||||
echo "P - fmod"
|
||||
echo ---------------------------------------------------
|
||||
echo.
|
||||
|
||||
choice /C ABCDEFGHIJKLMNO /T 10 /D A
|
||||
choice /C ABCDEFGHIJKLMNOP /T 10 /D A
|
||||
set _e=%ERRORLEVEL%
|
||||
|
||||
if %_e%==1 goto VMA
|
||||
|
@ -40,6 +41,7 @@ if %_e%==12 goto yamlcpp
|
|||
if %_e%==13 goto SDL
|
||||
if %_e%==14 goto dotnet
|
||||
if %_e%==15 goto tinyddsloader
|
||||
if %_e%==16 goto fmod
|
||||
|
||||
:VMA
|
||||
echo -----------------------VMA----------------------------
|
||||
|
@ -145,6 +147,12 @@ if %_e%==14 (goto :done) else (goto :tinyddsloader)
|
|||
echo --------------------tinyddsloader-------------------------
|
||||
rmdir "Dependencies/tinyddsloader" /S /Q
|
||||
git clone https://github.com/SHADE-DP/tinyddsloader.git "Dependencies/tinyddsloader"
|
||||
if %_e%==15 (goto :done) else (goto :fmod)
|
||||
|
||||
:fmod
|
||||
echo --------------------fmod-------------------------
|
||||
rmdir "Dependencies/fmod" /S /Q
|
||||
git clone https://github.com/SHADE-DP/FMOD.git "Dependencies/fmod"
|
||||
|
||||
:done
|
||||
echo DONE!
|
||||
|
|
|
@ -15,3 +15,4 @@ IncludeDir["SDL"] = "%{wks.location}\\Dependencies\\SDL"
|
|||
IncludeDir["VULKAN"] = "$(VULKAN_SDK)"
|
||||
IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet"
|
||||
IncludeDir["tinyddsloader"] = "%{wks.location}\\Dependencies\\tinyddsloader"
|
||||
IncludeDir["fmod"] = "%{wks.location}\\Dependencies\\fmod"
|
|
@ -30,12 +30,13 @@ project "SHADE_Application"
|
|||
|
||||
externalincludedirs
|
||||
{
|
||||
"%{IncludeDir.spdlog}/include",
|
||||
"%{IncludeDir.VULKAN}/include",
|
||||
"%{IncludeDir.VMA}/include",
|
||||
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
|
||||
"%{IncludeDir.RTTR}/include",
|
||||
"%{IncludeDir.tinyddsloader}"
|
||||
"%{IncludeDir.spdlog}/include",
|
||||
"%{IncludeDir.VULKAN}/include",
|
||||
"%{IncludeDir.VMA}/include",
|
||||
"%{IncludeDir.VULKAN}/Source/SPIRV-Reflect",
|
||||
"%{IncludeDir.tinyddsloader}",
|
||||
"%{IncludeDir.fmod}/include",
|
||||
"%{IncludeDir.RTTR}\\include"
|
||||
}
|
||||
|
||||
externalwarnings "Off"
|
||||
|
@ -66,9 +67,16 @@ project "SHADE_Application"
|
|||
|
||||
disablewarnings
|
||||
{
|
||||
"4251"
|
||||
"4251",
|
||||
"26812",
|
||||
"26439",
|
||||
"26451",
|
||||
"26437",
|
||||
"4275"
|
||||
}
|
||||
|
||||
linkoptions { "-IGNORE:4006" }
|
||||
|
||||
warnings 'Extra'
|
||||
|
||||
filter "configurations:Debug"
|
||||
|
@ -81,4 +89,4 @@ project "SHADE_Application"
|
|||
|
||||
filter "configurations:Publish"
|
||||
optimize "On"
|
||||
defines{"_RELEASE"}
|
||||
defines{"_RELEASE", "_PUBLISH"}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <chrono>
|
||||
#include <ratio>
|
||||
#include <ctime>
|
||||
#define SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN 1
|
||||
#include <SDL.h>
|
||||
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
|
@ -23,13 +22,17 @@
|
|||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Math/Transform/SHTransformSystem.h"
|
||||
#include "Input/SHInputManagerSystem.h"
|
||||
#include "Input/SHInputManager.h"
|
||||
#include "FRC/SHFramerateController.h"
|
||||
#include "AudioSystem/SHAudioSystem.h"
|
||||
|
||||
#include "Scenes/SBTestScene.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
|
||||
#include "Tools/SHLogger.h"
|
||||
|
||||
using namespace SHADE;
|
||||
|
||||
namespace Sandbox
|
||||
|
@ -54,7 +57,7 @@ namespace Sandbox
|
|||
// TODO(Diren): Create Physics System here
|
||||
SHADE::SHSystemManager::CreateSystem<SHADE::SHTransformSystem>();
|
||||
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
|
||||
SHADE::SHSystemManager::CreateSystem<SHADE::SHInputManagerSystem>();
|
||||
SHADE::SHSystemManager::CreateSystem<SHADE::SHAudioSystem>();
|
||||
|
||||
// Create Routines
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHScriptEngine, SHADE::SHScriptEngine::FrameSetUpRoutine>();
|
||||
|
@ -75,13 +78,20 @@ namespace Sandbox
|
|||
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>();
|
||||
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
|
||||
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHInputManagerSystem, SHADE::SHInputManagerSystem::InputManagerRoutine>();
|
||||
//TODO: REMOVE AFTER PRESENTATION
|
||||
//SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
|
||||
SHADE::SHAssetManager::LoadDataTemp("../../Assets/Cube.012.shmesh");
|
||||
//SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
|
||||
//SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
|
||||
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.shtex");
|
||||
//TODO: REMOVE AFTER PRESENTATION
|
||||
|
||||
//TODO: REMOVE AFTER PRESENTATION
|
||||
SHADE::SHAssetManager::LoadDataTemp("../../Assets/racoon.gltf");
|
||||
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonBag_Color_Ver4.dds");
|
||||
SHADE::SHAssetManager::LoadDataTemp("../../Assets/RaccoonPreTexturedVer1_Base9.dds");
|
||||
//TODO: REMOVE AFTER PRESENTATION
|
||||
|
||||
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
auto id2 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
|
||||
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHAudioSystem, SHADE::SHAudioSystem::AudioRoutine>();
|
||||
|
||||
// Set up graphics system and windows
|
||||
graphicsSystem->SetWindow(&window);
|
||||
|
@ -94,7 +104,10 @@ namespace Sandbox
|
|||
#else
|
||||
#endif
|
||||
|
||||
|
||||
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
|
||||
|
||||
SHFrameRateController::UpdateFRC();
|
||||
}
|
||||
|
||||
void SBApplication::Update(void)
|
||||
|
@ -103,6 +116,8 @@ namespace Sandbox
|
|||
//TODO: Change true to window is open
|
||||
while (!window.WindowShouldClose())
|
||||
{
|
||||
SHFrameRateController::UpdateFRC();
|
||||
SHInputManager::UpdateInput(SHFrameRateController::GetRawDeltaTime());
|
||||
SHSceneManager::UpdateSceneManager();
|
||||
SHSceneManager::SceneUpdate(1/60.0f);
|
||||
//#ifdef SHEDITOR
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
|
||||
|
@ -35,89 +36,138 @@ namespace Sandbox
|
|||
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
|
||||
// Create temp meshes
|
||||
const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem);
|
||||
//graphicsSystem->BuildMeshBuffers();
|
||||
|
||||
//Test Racoon mesh
|
||||
auto meshes = SHADE::SHAssetManager::GetAllMeshes();
|
||||
std::vector<Handle<SHMesh>> handles;
|
||||
for (auto const& mesh : meshes)
|
||||
{
|
||||
if (mesh.header.meshName == "Cube.012")
|
||||
{
|
||||
handles.push_back(graphicsSystem->AddMesh(
|
||||
mesh.header.vertexCount,
|
||||
mesh.vertexPosition.data(),
|
||||
mesh.texCoords.data(),
|
||||
mesh.vertexTangent.data(),
|
||||
mesh.vertexNormal.data(),
|
||||
mesh.header.indexCount,
|
||||
mesh.indices.data()
|
||||
));
|
||||
mesh.header.vertexCount,
|
||||
mesh.vertexPosition.data(),
|
||||
mesh.texCoords.data(),
|
||||
mesh.vertexTangent.data(),
|
||||
mesh.vertexNormal.data(),
|
||||
mesh.header.indexCount,
|
||||
mesh.indices.data()
|
||||
));
|
||||
}
|
||||
}
|
||||
graphicsSystem->BuildMeshBuffers();
|
||||
|
||||
//Test Textures
|
||||
auto textures{ SHADE::SHAssetManager::GetAllTextures() };
|
||||
// Load Textures
|
||||
auto textures = SHADE::SHAssetManager::GetAllTextures();
|
||||
std::vector<Handle<SHTexture>> texHandles;
|
||||
for (const auto& tex : textures)
|
||||
{
|
||||
auto texture = graphicsSystem->Add(tex);
|
||||
texHandles.push_back(texture);
|
||||
}
|
||||
graphicsSystem->BuildTextures();
|
||||
|
||||
// Create Materials
|
||||
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance();
|
||||
auto customMat = graphicsSystem->AddMaterialInstanceCopy(matInst);
|
||||
customMat->SetProperty("data.color", SHVec4(0.0f, 1.0f, 1.0f, 1.0f));
|
||||
customMat->SetProperty("data.textureIndex", 0);
|
||||
customMat->SetProperty("data.alpha", 0.1f);
|
||||
|
||||
// Create Stress Test Objects
|
||||
static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f };
|
||||
constexpr int NUM_ROWS = 1;
|
||||
constexpr int NUM_COLS = 1;
|
||||
static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f };
|
||||
static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f };
|
||||
//for (int z = 0; z < NUM_ROWS; ++z)
|
||||
//for (int x = 0; x < NUM_COLS; ++x)
|
||||
//{
|
||||
// auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
// auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
|
||||
// auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
|
||||
|
||||
// renderable.Mesh = handles.front();
|
||||
// renderable.SetMaterial(matInst);
|
||||
|
||||
// // Set initial positions
|
||||
// transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, 0.0f, z * TEST_OBJ_SPACING.z });
|
||||
// //transform.SetLocalScale(TEST_OBJ_SCALE);
|
||||
|
||||
// stressTestObjects.emplace_back(entity);
|
||||
//}
|
||||
static const SHVec3 TEST_OBJ_SCALE = { 0.05f, 0.05f, 0.05f };
|
||||
constexpr int NUM_ROWS = 100;
|
||||
constexpr int NUM_COLS = 100;
|
||||
static const SHVec3 TEST_OBJ_SPACING = { 0.05f, 0.05f, 0.05f };
|
||||
static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ) + 1.0f, -2.0f, -1.0f };
|
||||
|
||||
for (int y = 0; y < NUM_ROWS; ++y)
|
||||
for (int x = 0; x < NUM_COLS; ++x)
|
||||
{
|
||||
auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
|
||||
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
|
||||
|
||||
renderable.Mesh = handles.front();
|
||||
renderable.SetMaterial(matInst);
|
||||
renderable.SetMaterial(customMat);
|
||||
|
||||
//transform.SetLocalScale(TEST_OBJ_SCALE);
|
||||
if (y == 50)
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
//Set initial positions
|
||||
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{
|
||||
x * TEST_OBJ_SPACING.x,
|
||||
y * TEST_OBJ_SPACING.y,
|
||||
0.0f
|
||||
});
|
||||
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
|
||||
//transform.SetWorldRotation(3.14159265f * 1.5f, -3.14159265f / 2.0f, 0.0f);
|
||||
transform.SetLocalScale(TEST_OBJ_SCALE);
|
||||
|
||||
stressTestObjects.emplace_back(entity);
|
||||
}
|
||||
|
||||
auto raccoonSpin = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonSpin);
|
||||
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonSpin);
|
||||
|
||||
renderable.Mesh = handles.front();
|
||||
renderable.SetMaterial(customMat);
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
|
||||
|
||||
transform.SetWorldPosition ({-3.0f, -1.0f, -1.0f});
|
||||
transform.SetLocalScale({5.0f, 5.0f, 5.0f});
|
||||
|
||||
//auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
//auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
|
||||
//auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
|
||||
|
||||
//renderable.Mesh = handles.back();
|
||||
//renderable.SetMaterial(customMat);
|
||||
|
||||
//transform.SetLocalScale(TEST_OBJ_SCALE);
|
||||
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
|
||||
|
||||
// Create blank entity with a script
|
||||
testObj = SHADE::SHEntityManager::CreateEntity();
|
||||
//testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
//auto& testObjRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(testObj);
|
||||
//testObjRenderable.Mesh = CUBE_MESH;
|
||||
//testObjRenderable.SetMaterial(matInst);
|
||||
|
||||
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
|
||||
scriptEngine->AddScript(testObj, "TestScript");
|
||||
scriptEngine->AddScript(raccoonSpin, "RaccoonSpin");
|
||||
|
||||
auto raccoonShowcase = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
|
||||
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
|
||||
|
||||
renderableShowcase.Mesh = handles.front();
|
||||
renderableShowcase.SetMaterial(customMat);
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
|
||||
|
||||
transformShowcase.SetWorldPosition({ 3.0f, -1.0f, -1.0f });
|
||||
transformShowcase.SetLocalScale({ 5.0f, 5.0f, 5.0f });
|
||||
scriptEngine->AddScript(raccoonShowcase, "RaccoonShowcase");
|
||||
}
|
||||
|
||||
void SBTestScene::Update(float dt)
|
||||
{
|
||||
/*static float rotation = 0.0f;
|
||||
static float rotation = 0.0f;
|
||||
|
||||
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj);
|
||||
//auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj);
|
||||
|
||||
transform.SetLocalRotation(rotation, 0.0f, 0.0f);
|
||||
rotation += dt * 10.0f;*/
|
||||
/*static float rotation = 0.0f;
|
||||
|
||||
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(stressTestObjects[0]);
|
||||
|
||||
transform.SetWorldPosition({rotation, 0.0f, 0.0f});
|
||||
rotation += dt * 10.0f;*/
|
||||
//transform.SetWorldPosition({1.0f, 1.0f, -1.0f});
|
||||
//transform.SetWorldRotation(0.0f, 0.0f + rotation, 0.0f);
|
||||
//rotation += dt * 0.2f;
|
||||
|
||||
// Destroy entity if space is pressed
|
||||
if (GetKeyState(VK_SPACE) & 0x8000)
|
||||
{
|
||||
rotation = 0.0f;
|
||||
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
|
||||
scriptEngine->RemoveAllScripts(testObj);
|
||||
}
|
||||
|
@ -125,6 +175,7 @@ namespace Sandbox
|
|||
|
||||
void SBTestScene::Render()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SBTestScene::Unload()
|
||||
|
|
|
@ -42,7 +42,8 @@ project "SHADE_Engine"
|
|||
"%{IncludeDir.VULKAN}\\include",
|
||||
"%{IncludeDir.VULKAN}\\Source\\SPIRV-Reflect",
|
||||
"%{IncludeDir.dotnet}\\include",
|
||||
"%{IncludeDir.tinyddsloader}"
|
||||
"%{IncludeDir.tinyddsloader}",
|
||||
"%{IncludeDir.fmod}\\include"
|
||||
}
|
||||
|
||||
externalwarnings "Off"
|
||||
|
@ -55,7 +56,8 @@ project "SHADE_Engine"
|
|||
"%{IncludeDir.assimp}/lib/Release",
|
||||
"%{IncludeDir.RTTR}/lib",
|
||||
"%{IncludeDir.SDL}/lib",
|
||||
"%{IncludeDir.spdlog}/lib"
|
||||
"%{IncludeDir.spdlog}/lib",
|
||||
"%{IncludeDir.fmod}/lib",
|
||||
}
|
||||
|
||||
links
|
||||
|
@ -74,9 +76,16 @@ project "SHADE_Engine"
|
|||
|
||||
disablewarnings
|
||||
{
|
||||
"4251"
|
||||
"4251",
|
||||
"26812",
|
||||
"26439",
|
||||
"26451",
|
||||
"26437",
|
||||
"4275"
|
||||
}
|
||||
|
||||
linkoptions { "-IGNORE:4006" }
|
||||
|
||||
defines
|
||||
{
|
||||
"_LIB",
|
||||
|
@ -108,9 +117,30 @@ project "SHADE_Engine"
|
|||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
postbuildcommands {"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Debug\\assimp-vc142-mtd.dll\" \"$(OutDir)\""}
|
||||
postbuildcommands
|
||||
{
|
||||
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Debug\\assimp-vc142-mtd.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodL.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudioL.dll\" \"$(OutDir)\""
|
||||
}
|
||||
|
||||
filter "configurations:Release"
|
||||
postbuildcommands
|
||||
{
|
||||
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
|
||||
}
|
||||
|
||||
filter "configurations:Publish"
|
||||
postbuildcommands
|
||||
{
|
||||
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
|
||||
}
|
||||
|
||||
filter "configurations:Publish"
|
||||
postbuildcommands {"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\""}
|
||||
|
||||
warnings 'Extra'
|
||||
|
@ -119,17 +149,17 @@ project "SHADE_Engine"
|
|||
symbols "On"
|
||||
defines {"_DEBUG", "SHEDITOR"}
|
||||
links{"assimp-vc142-mtd.lib", "librttr_core_d.lib", "spdlogd.lib"}
|
||||
--links{"fmodstudioL_vc.lib", "fmodL_vc.lib"}
|
||||
links{"fmodstudioL_vc.lib", "fmodL_vc.lib"}
|
||||
|
||||
filter "configurations:Release"
|
||||
optimize "On"
|
||||
defines{"_RELEASE", "SHEDITOR"}
|
||||
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
|
||||
--links{"fmodstudio_vc.lib", "fmod_vc.lib"}
|
||||
links{"fmodstudio_vc.lib", "fmod_vc.lib"}
|
||||
|
||||
filter "configurations:Publish"
|
||||
optimize "On"
|
||||
defines{"_RELEASE"}
|
||||
defines{"_RELEASE", "_PUBLISH"}
|
||||
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
|
||||
excludes
|
||||
{
|
||||
|
@ -137,4 +167,4 @@ project "SHADE_Engine"
|
|||
"%{prj.location}/src/Editor/**.h",
|
||||
"%{prj.location}/src/Editor/**.hpp",
|
||||
}
|
||||
--links{"fmodstudio_vc.lib", "fmod_vc.lib"}
|
||||
links{"fmodstudio_vc.lib", "fmod_vc.lib"}
|
|
@ -1,25 +1,37 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshAsset.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Struct to contain ready data for loading into GPU. Also used for
|
||||
* compilation into binary files
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "Math/SHMath.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHMeshAssetHeader
|
||||
struct SH_API SHMeshAssetHeader
|
||||
{
|
||||
uint32_t vertexCount;
|
||||
uint32_t indexCount;
|
||||
std::string meshName;
|
||||
};
|
||||
|
||||
struct SHMeshAsset
|
||||
struct SH_API SHMeshAsset
|
||||
{
|
||||
bool compiled;
|
||||
bool changed;
|
||||
|
||||
SHMeshAssetHeader header;
|
||||
|
||||
std::string meshName;
|
||||
|
||||
std::vector<SHVec3> vertexPosition;
|
||||
std::vector<SHVec3> vertexTangent;
|
||||
std::vector<SHVec3> vertexNormal;
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "tinyddsloader.h"
|
||||
|
||||
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHTextureAsset
|
||||
{
|
||||
bool compiled;
|
||||
|
||||
uint32_t numBytes;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshCompiler.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHMeshAsset into binary file for faster
|
||||
* loading in the future
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHMeshCompiler.h"
|
||||
#include "Graphics/MiddleEnd/Meshes/SHMeshData.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
void SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
|
||||
{
|
||||
std::string newPath{ path.string() };
|
||||
newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
|
||||
newPath += asset.header.meshName + MESH_EXTENSION;
|
||||
|
||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
|
||||
}
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<const char*>(&(asset.header.indexCount)),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
auto const vertexVec3Byte {sizeof(SHVec3) * asset.header.vertexCount};
|
||||
auto const vertexVec2Byte {sizeof(SHVec2) * asset.header.vertexCount};
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.texCoords.data()),
|
||||
vertexVec2Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.indices.data()),
|
||||
sizeof(uint32_t) * asset.header.indexCount
|
||||
);
|
||||
|
||||
file.close();
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshCompiler.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHMeshAsset into binary file for faster
|
||||
* loading in the future
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "../Asset Types/SHMeshAsset.h"
|
||||
#include "../SHAssetMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHMeshCompiler
|
||||
{
|
||||
private:
|
||||
public:
|
||||
static void CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
|
||||
};
|
||||
}
|
|
@ -1,12 +1,25 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshLoader.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Implementation for Mesh loader. Accounts for custom binary format
|
||||
* as well as GLTF file format.
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHMeshLoader.h"
|
||||
#include <assimp/postprocess.h>
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
Assimp::Importer SHMeshLoader::aiImporter;
|
||||
|
||||
void SHMeshLoader::ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes)
|
||||
void SHMeshLoader::ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept
|
||||
{
|
||||
for (size_t i {0}; i < node.mNumMeshes; ++i)
|
||||
{
|
||||
|
@ -20,15 +33,14 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
SHMeshAsset SHMeshLoader::ProcessMesh(aiMesh const& mesh, aiScene const& scene)
|
||||
SHMeshAsset SHMeshLoader::ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept
|
||||
{
|
||||
(void)scene;
|
||||
|
||||
SHMeshAsset result
|
||||
{
|
||||
.compiled { false},
|
||||
.changed { false },
|
||||
.meshName { mesh.mName.C_Str() }
|
||||
.changed { false }
|
||||
};
|
||||
|
||||
for (size_t i{0}; i < mesh.mNumVertices; ++i)
|
||||
|
@ -81,34 +93,31 @@ namespace SHADE
|
|||
|
||||
result.header.vertexCount = result.vertexPosition.size();
|
||||
result.header.indexCount = result.indices.size();
|
||||
result.header.meshName = mesh.mName.C_Str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SHMeshLoader::LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path)
|
||||
{
|
||||
void SHMeshLoader::LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
|
||||
{
|
||||
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
||||
aiProcess_Triangulate
|
||||
// Make sure we get triangles rather than nvert polygons
|
||||
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
||||
| aiProcess_TransformUVCoords
|
||||
// preprocess UV transformations (scaling, translation ...)
|
||||
| aiProcess_FindInstances
|
||||
// search for instanced meshes and remove them by references to one master
|
||||
| aiProcess_CalcTangentSpace
|
||||
// calculate tangents and bitangents if possible
|
||||
| aiProcess_JoinIdenticalVertices
|
||||
// join identical vertices/ optimize indexing
|
||||
| aiProcess_RemoveRedundantMaterials // remove redundant materials
|
||||
| aiProcess_FindInvalidData// detect invalid model data, such as invalid normal vectors
|
||||
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
||||
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
||||
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
||||
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
|
||||
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
|
||||
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
|
||||
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
|
||||
| aiProcess_RemoveRedundantMaterials // remove redundant materials
|
||||
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
||||
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
||||
);
|
||||
|
||||
if (!scene || !scene->HasMeshes())
|
||||
{
|
||||
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO MATERIALS FROM MESHES
|
||||
//if (scene->HasMaterials())
|
||||
//{
|
||||
|
@ -116,14 +125,108 @@ namespace SHADE
|
|||
// {
|
||||
// if (scene->mMaterials[i]->mNumProperties > 0)
|
||||
// {
|
||||
// for (int j{0}; j < scene->mMaterials[i]->mProperties[j].)
|
||||
// for (int j{0}; j < scene->mMaterials[i]->mProperties[j].)
|
||||
// }
|
||||
//std::cout << scene->mMaterials[i]->;
|
||||
//std::cout << scene->mMaterials[i]->;
|
||||
// }
|
||||
//}
|
||||
|
||||
ProcessNode(*scene->mRootNode, *scene, meshes);
|
||||
}
|
||||
|
||||
return true;
|
||||
void SHMeshLoader::LoadSHMesh(SHMeshAsset& mesh, AssetPath path) noexcept
|
||||
{
|
||||
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
|
||||
}
|
||||
|
||||
std::string name{ path.filename().string() };
|
||||
name = name.substr(0, name.find_last_of('.'));
|
||||
|
||||
file.seekg(0);
|
||||
|
||||
uint32_t vertCount, indexCount;
|
||||
std::vector<SHVec3> vertPos, vertTan, vertNorm;
|
||||
std::vector<SHVec2> texCoord;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
file.read(reinterpret_cast<char*>(&vertCount), sizeof(uint32_t));
|
||||
file.read(reinterpret_cast<char*>(&indexCount), sizeof(uint32_t));
|
||||
|
||||
auto const vertexVec3Byte{ sizeof(SHVec3) * vertCount };
|
||||
auto const vertexVec2Byte{ sizeof(SHVec2) * vertCount };
|
||||
|
||||
vertPos.resize(vertCount);
|
||||
vertTan.resize(vertCount);
|
||||
vertNorm.resize(vertCount);
|
||||
texCoord.resize(vertCount);
|
||||
indices.resize(indexCount);
|
||||
|
||||
file.read(reinterpret_cast<char *>(vertPos.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(vertTan.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
|
||||
file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
|
||||
|
||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
||||
//{
|
||||
// file >> vertPos[i].x;
|
||||
// file >> vertPos[i].y;
|
||||
// file >> vertPos[i].z;
|
||||
//}
|
||||
//
|
||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
||||
//{
|
||||
// file >> vertTan[i].x;
|
||||
// file >> vertTan[i].y;
|
||||
// file >> vertTan[i].z;
|
||||
//}
|
||||
|
||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
||||
//{
|
||||
// file >> vertNorm[i].x;
|
||||
// file >> vertNorm[i].y;
|
||||
// file >> vertNorm[i].z;
|
||||
//}
|
||||
|
||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
||||
//{
|
||||
// file >> texCoord[i].x;
|
||||
// file >> texCoord[i].y;
|
||||
//}
|
||||
|
||||
//for (auto i{ 0 }; i < indexCount; ++i)
|
||||
//{
|
||||
// file >> indices[i];
|
||||
//}
|
||||
|
||||
mesh.compiled = true;
|
||||
mesh.changed = false;
|
||||
|
||||
mesh.header.indexCount = indexCount;
|
||||
mesh.header.vertexCount = vertCount;
|
||||
mesh.header.meshName = name;
|
||||
|
||||
mesh.vertexPosition = std::move(vertPos);
|
||||
mesh.vertexTangent = std::move(vertTan);
|
||||
mesh.vertexNormal = std::move(vertNorm);
|
||||
mesh.texCoords = std::move(texCoord);
|
||||
mesh.indices = std::move(indices);
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void SHMeshLoader::LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
|
||||
{
|
||||
if (path.extension().string() == GLTF_EXTENSION)
|
||||
{
|
||||
LoadExternal(meshes, path);
|
||||
return;
|
||||
}
|
||||
|
||||
meshes.emplace_back();
|
||||
LoadSHMesh(meshes.back(), path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshLoader.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to load gltf mesh files and custom binary format
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/scene.h>
|
||||
|
@ -12,10 +23,14 @@ namespace SHADE
|
|||
private:
|
||||
static Assimp::Importer aiImporter;
|
||||
|
||||
static void ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes);
|
||||
static void ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept;
|
||||
|
||||
static SHMeshAsset ProcessMesh(aiMesh const& mesh, aiScene const& scene);
|
||||
static SHMeshAsset ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept;
|
||||
|
||||
static void LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
|
||||
|
||||
static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept;
|
||||
public:
|
||||
static bool LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path);
|
||||
static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
|
||||
};
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHMeshWriter.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
void SHADE::SHMeshWriter::WriteMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
|
||||
{
|
||||
std::ofstream file{path, std::ios::out | std::ios::binary};
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
|
||||
}
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<const char*>(&(asset.header.indexCount)),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
auto const vertexVec3Byte {sizeof(SHVec3) * asset.header.vertexCount};
|
||||
auto const vertexVec2Byte {sizeof(SHVec2) * asset.header.vertexCount};
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.texCoords.data()),
|
||||
vertexVec2Byte
|
||||
);
|
||||
|
||||
file.close();
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Asset Types/SHMeshAsset.h"
|
||||
#include "../SHAssetMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHMeshWriter
|
||||
{
|
||||
private:
|
||||
public:
|
||||
static void WriteMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHTextureCompiler.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHTextureAsset into binary file for
|
||||
* faster loading in the future
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHTextureCompiler.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
void SHTextureCompiler::CompileTextureBinary(SHTextureAsset const& asset, AssetPath path)
|
||||
{
|
||||
std::string newPath{ path.string() };
|
||||
newPath = newPath.substr(0, newPath.find_last_of('.'));
|
||||
newPath += TEXTURE_EXTENSION;
|
||||
|
||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open file for writing texture file: {}", path.string());
|
||||
}
|
||||
|
||||
auto const intBytes{sizeof(uint32_t)};
|
||||
|
||||
uint32_t mipOffsetCount{ static_cast<uint32_t>(asset.mipOffsets.size()) };
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&asset.numBytes),
|
||||
intBytes
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&asset.width),
|
||||
intBytes
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&asset.height),
|
||||
intBytes
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&asset.format),
|
||||
sizeof(SHTexture::TextureFormat)
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&mipOffsetCount),
|
||||
intBytes
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.mipOffsets.data()),
|
||||
intBytes * asset.mipOffsets.size()
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.pixelData),
|
||||
asset.numBytes
|
||||
);
|
||||
|
||||
file.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHTextureCompiler.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHTextureAsset into binary file for
|
||||
* faster loading in the future
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHTextureCompiler
|
||||
{
|
||||
static void CompileTextureBinary(SHTextureAsset const& asset, AssetPath path);
|
||||
};
|
||||
}
|
|
@ -1,3 +1,14 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHTextureLoader.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to load dds textures and custom binary format
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHTextureLoader.h"
|
||||
|
||||
|
@ -58,7 +69,7 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
|
||||
void SHTextureLoader::LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept
|
||||
{
|
||||
tinyddsloader::Result loadResult = tinyddsloader::Result::Success;
|
||||
tinyddsloader::DDSFile file;
|
||||
|
@ -74,14 +85,15 @@ namespace SHADE
|
|||
|
||||
for (auto i{0}; i < file.GetMipCount(); ++i)
|
||||
{
|
||||
mipOff.push_back(totalBytes);
|
||||
mipOff[i] = totalBytes;
|
||||
totalBytes += file.GetImageData(i, 0)->m_memSlicePitch;
|
||||
}
|
||||
|
||||
SHTexture::PixelChannel* pixel = new SHTexture::PixelChannel[totalBytes];
|
||||
std::memcpy(pixel, file.GetDDSData(), totalBytes);
|
||||
std::memcpy(pixel, file.GetImageData()->m_mem, totalBytes);
|
||||
//pixel = std::move(reinterpret_cast<SHTexture::PixelChannel const*>(file.GetDDSData()));
|
||||
|
||||
asset.compiled = false;
|
||||
asset.numBytes = totalBytes;
|
||||
asset.width = file.GetWidth();
|
||||
asset.height = file.GetHeight();
|
||||
|
@ -89,4 +101,46 @@ namespace SHADE
|
|||
asset.mipOffsets = std::move(mipOff);
|
||||
asset.pixelData = std::move(pixel);
|
||||
}
|
||||
|
||||
void SHTextureLoader::LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept
|
||||
{
|
||||
std::ifstream file{path.string(), std::ios::in | std::ios::binary};
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Error opening SHTexture file: {}", path.string());
|
||||
}
|
||||
|
||||
auto const intBytes{ sizeof(uint32_t) };
|
||||
uint32_t mipCount;
|
||||
|
||||
file.read(reinterpret_cast<char*>(&asset.numBytes), intBytes);
|
||||
file.read(reinterpret_cast<char*>(&asset.width), intBytes);
|
||||
file.read(reinterpret_cast<char*>(&asset.height), intBytes);
|
||||
file.read(reinterpret_cast<char*>(&asset.format), sizeof(SHTexture::TextureFormat));
|
||||
|
||||
file.read(reinterpret_cast<char*>(&mipCount), intBytes);
|
||||
std::vector<uint32_t> mips(mipCount);
|
||||
file.read(reinterpret_cast<char*>(mips.data()), intBytes * mipCount);
|
||||
|
||||
auto pixel = new SHTexture::PixelChannel[asset.numBytes];
|
||||
file.read(reinterpret_cast<char*>(pixel), asset.numBytes);
|
||||
|
||||
asset.mipOffsets = std::move(mips);
|
||||
asset.pixelData = std::move( pixel );
|
||||
|
||||
asset.compiled = true;
|
||||
file.close();
|
||||
}
|
||||
|
||||
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
|
||||
{
|
||||
if (path.extension().string() == DDS_EXTENSION)
|
||||
{
|
||||
LoadTinyDDS(path, asset);
|
||||
}
|
||||
else if (path.extension().string() == TEXTURE_EXTENSION)
|
||||
{
|
||||
LoadSHTexture(path, asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHTextureLoader.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to load dds textures and custom binary format
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
#define TINYDDSLOADER_IMPLEMENTATION
|
||||
|
||||
|
@ -13,6 +24,9 @@ namespace SHADE
|
|||
static std::string TinyDDSResultToString(tinyddsloader::Result value);
|
||||
static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
||||
|
||||
|
||||
static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||
static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||
public:
|
||||
static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
|
||||
};
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHAsset.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Struct for asset identification and meta file writing
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "Filesystem/SHFileSystem.h"
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#include "Libraries/SHMeshLoader.h"
|
||||
#include "Libraries/SHTextureLoader.h"
|
||||
|
||||
#include "Libraries/SHMeshCompiler.h"
|
||||
#include "Libraries/SHTextureCompiler.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
FMOD::System* SHAssetManager::audioSystem;
|
||||
|
@ -199,7 +202,9 @@ namespace SHADE
|
|||
{
|
||||
AssetPath path{ p };
|
||||
|
||||
if (path.extension().string() == GLTF_EXTENSION)
|
||||
if (path.extension().string() == FBX_EXTENSION
|
||||
|| path.extension().string() == GLTF_EXTENSION
|
||||
|| path.extension().string() == MESH_EXTENSION)
|
||||
{
|
||||
LoadGLTF(
|
||||
{
|
||||
|
@ -211,7 +216,8 @@ namespace SHADE
|
|||
}
|
||||
);
|
||||
}
|
||||
else if (path.extension().string() == DDS_EXTENSION)
|
||||
else if (path.extension().string() == DDS_EXTENSION
|
||||
|| path.extension().string() == TEXTURE_EXTENSION)
|
||||
{
|
||||
LoadDDS(
|
||||
{
|
||||
|
@ -300,6 +306,11 @@ namespace SHADE
|
|||
for (auto const& mesh : meshes)
|
||||
{
|
||||
meshCollection.emplace(GenerateAssetID(AssetType::MESH), mesh);
|
||||
|
||||
if (!mesh.compiled)
|
||||
{
|
||||
SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,6 +321,11 @@ namespace SHADE
|
|||
SHTextureLoader::LoadImageAsset(asset.path, image);
|
||||
|
||||
textureCollection.emplace(GenerateAssetID(AssetType::DDS), image);
|
||||
|
||||
if (!image.compiled)
|
||||
{
|
||||
SHTextureCompiler::CompileTextureBinary(image, asset.path);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -99,6 +99,7 @@ namespace SHADE
|
|||
****************************************************************************/
|
||||
void SHAssetMetaHandler::WriteMetaData(SHAsset const& meta) noexcept
|
||||
{
|
||||
//TODO: Write into binary eventually
|
||||
std::string path{ meta.path.string() };
|
||||
path.append(META_EXTENSION);
|
||||
|
||||
|
@ -110,8 +111,20 @@ namespace SHADE
|
|||
return;
|
||||
}
|
||||
|
||||
metaFile << "Name: " << meta.name << "\n";
|
||||
metaFile << "ID: " << meta.id << "\n";
|
||||
metaFile << "Type: " << static_cast<int>(meta.type) << std::endl;
|
||||
|
||||
//TODO Add in information that is specific to types like mesh
|
||||
switch(meta.type)
|
||||
{
|
||||
case AssetType::MESH:
|
||||
break;
|
||||
|
||||
default:
|
||||
void;
|
||||
}
|
||||
|
||||
metaFile.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*********************************************************************
|
||||
* \file SHAudioListenerComponent.cpp
|
||||
* \author Glence Low
|
||||
* \brief Definition of the SHAudioListenerComponent class.
|
||||
*
|
||||
* \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 "SHAudioListenerComponent.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
const SHVec3 SHAudioListenerComponent::GetPos() const
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
||||
const SHVec3 SHAudioListenerComponent::GetVel() const
|
||||
{
|
||||
return vel;
|
||||
}
|
||||
|
||||
const SHVec3 SHAudioListenerComponent::GetForward() const
|
||||
{
|
||||
return forward;
|
||||
}
|
||||
|
||||
const SHVec3 SHAudioListenerComponent::GetUp() const
|
||||
{
|
||||
return up;
|
||||
}
|
||||
|
||||
void SHAudioListenerComponent::SetPos(const SHVec3 p)
|
||||
{
|
||||
pos = p;
|
||||
}
|
||||
|
||||
void SHAudioListenerComponent::SetVel(const SHVec3 v)
|
||||
{
|
||||
vel = v;
|
||||
}
|
||||
|
||||
void SHAudioListenerComponent::SetForward(const SHVec3 f)
|
||||
{
|
||||
forward = f;
|
||||
}
|
||||
|
||||
void SHAudioListenerComponent::SetUp(const SHVec3 u)
|
||||
{
|
||||
up = u;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
/*********************************************************************
|
||||
* \file SHAudioListenerComponent.h
|
||||
* \author Glence Low
|
||||
* \brief Declaration of the SHAudioListenerComponent class.
|
||||
*
|
||||
* \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.
|
||||
*********************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Math/SHMath.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHAudioListenerComponent : public SHComponent
|
||||
{
|
||||
friend class SHAudioSystem;
|
||||
public:
|
||||
|
||||
SHAudioListenerComponent() = default;
|
||||
~SHAudioListenerComponent() = default;
|
||||
|
||||
const SHVec3 GetPos() const;
|
||||
void SetPos(const SHVec3 p);
|
||||
|
||||
const SHVec3 GetVel() const;
|
||||
const SHVec3 GetForward() const;
|
||||
const SHVec3 GetUp() const;
|
||||
|
||||
void SetVel(const SHVec3 v);
|
||||
void SetForward(const SHVec3 f);
|
||||
void SetUp(const SHVec3 u);
|
||||
|
||||
private:
|
||||
SHVec3 pos{}, vel{}, forward{}, up{ 0.f,1.f,0.f };
|
||||
};
|
||||
}//namespace SHADE
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*********************************************************************
|
||||
* \file SHAudioSourceComponet.cpp
|
||||
* \author Glence Low
|
||||
* \brief Definition of the SHAudioSourceComponet class.
|
||||
*
|
||||
* \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 "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "AudioSystem/SHAudioSystem.h"
|
||||
#include "SHAudioSourceComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/**
|
||||
* @brief play the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void SHAudioSourceComponent::PlaySoundSFX(EntityID id, bool loop, bool spatial, float min , float max )
|
||||
{
|
||||
SHSystemManager::GetSystem<SHAudioSystem>()->PlaySFX(id, GetEID(),loop,spatial, min, max);
|
||||
}
|
||||
|
||||
void SHAudioSourceComponent::PlaySoundBGM(EntityID id, bool loop, bool spatial, float min, float max)
|
||||
{
|
||||
SHSystemManager::GetSystem<SHAudioSystem>()->PlayBGM(id, GetEID(), loop, spatial, min, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void SHAudioSourceComponent::StopSound(EntityID id)
|
||||
{
|
||||
SHSystemManager::GetSystem<SHAudioSystem>()->StopSound(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Mute the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void SHAudioSourceComponent::SetMute(EntityID id, bool mute)
|
||||
{
|
||||
SHSystemManager::GetSystem<SHAudioSystem>()->SetMute(id, mute);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*********************************************************************
|
||||
* \file SHAudioSourceComponet.h
|
||||
* \author Glence Low
|
||||
* \brief Declaration of the SHAudioSourceComponet class.
|
||||
*
|
||||
* \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.
|
||||
*********************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHAudioSourceComponent : public SHComponent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief default constructor for the component
|
||||
*
|
||||
*/
|
||||
SHAudioSourceComponent() = default;
|
||||
|
||||
|
||||
/**
|
||||
* @brief default destructor for the component
|
||||
*
|
||||
*/
|
||||
~SHAudioSourceComponent() = default;
|
||||
|
||||
/**
|
||||
* @brief play the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void PlaySoundSFX(EntityID id, bool loop = false, bool spatial = false, float min = 5.0f, float max = 1000.f);
|
||||
|
||||
void PlaySoundBGM(EntityID id, bool loop = false, bool spatial = false, float min = 5.0f, float max = 1000.f);
|
||||
|
||||
/**
|
||||
* @brief Stop the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void StopSound(EntityID id);
|
||||
|
||||
/**
|
||||
* @brief Mute the sound
|
||||
*
|
||||
* @param index where the sound is in the index
|
||||
*/
|
||||
void SetMute(EntityID id, bool mute);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
}//namespace SHADE
|
||||
|
|
@ -0,0 +1,557 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHAudioSystem.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "AudioSystem/SHAudioListenerComponent.h"
|
||||
#include "AudioSystem/SHAudioSourceComponent.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:26812) //disable warning about preference of enum class over enum as ImGuizmo uses enums
|
||||
#include <FMOD/fmod_errors.h>
|
||||
#include <FMOD/fmod.hpp>
|
||||
#include <FMOD/fmod_studio.hpp>
|
||||
#include <SDL_keyboard.h>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHAudioSystem::SHAudioSystem()
|
||||
: fmodStudioSystem(nullptr)
|
||||
, extraDriverData(nullptr)
|
||||
, soundList()
|
||||
, bgmChannelGroup(nullptr)
|
||||
, sfxChannelGroup(nullptr)
|
||||
, masterGroup(nullptr)
|
||||
, audioChannels()
|
||||
, result(FMOD_RESULT_FORCEINT)
|
||||
, bgmVolume(1.F)
|
||||
, sfxVolume(1.F)
|
||||
, masterVolume(1.0F)
|
||||
, version(0)
|
||||
, speakerMode(FMOD_SPEAKERMODE_5POINT1)
|
||||
, paused(false)
|
||||
{
|
||||
result = FMOD::Studio::System::create(&fmodStudioSystem);
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
SHAudioSystem::~SHAudioSystem()
|
||||
{
|
||||
}
|
||||
|
||||
void SHADE::SHAudioSystem::Init()
|
||||
{
|
||||
|
||||
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHAudioSourceComponent>();
|
||||
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHAudioListenerComponent>();
|
||||
|
||||
denseListener = &SHComponentManager::GetDense<SHAudioListenerComponent>();
|
||||
fmodStudioSystem->getCoreSystem(&fmodSystem);
|
||||
|
||||
result = fmodStudioSystem->initialize(AUDIO_SYS_MAX_CHANNELS, AUDIO_SYS_MAX_CHANNELS, FMOD_STUDIO_INIT_NORMAL, extraDriverData);
|
||||
ErrorCheck();
|
||||
|
||||
fmodSystem->setSoftwareFormat(0, speakerMode, 0);
|
||||
|
||||
result = fmodSystem->createChannelGroup("SFX", &sfxChannelGroup);
|
||||
ErrorCheck();
|
||||
|
||||
result = fmodSystem->createChannelGroup("BGM", &bgmChannelGroup);
|
||||
ErrorCheck();
|
||||
|
||||
result = fmodSystem->getMasterChannelGroup(&masterGroup);
|
||||
ErrorCheck();
|
||||
|
||||
result = masterGroup->addGroup(bgmChannelGroup);
|
||||
ErrorCheck();
|
||||
|
||||
result = masterGroup->addGroup(sfxChannelGroup);
|
||||
ErrorCheck();
|
||||
|
||||
bgmChannelGroup->setVolume(bgmVolume);
|
||||
sfxChannelGroup->setVolume(sfxVolume);
|
||||
masterGroup->setVolume(masterVolume);
|
||||
|
||||
//SHResourceManager::LoadAllAudio(system, soundList);
|
||||
|
||||
|
||||
LoadBank("../../Assets/Audio/Master.bank");
|
||||
LoadBank("../../Assets/Audio/Master.strings.bank");
|
||||
//LoadBank("../../Assets/Audio/Music.bank");
|
||||
LoadBank("../../Assets/Audio/footsteps.bank");
|
||||
|
||||
//auto clip = CreateAudioClip("event:/Characters/sfx_footsteps_human");
|
||||
//clip->Play();
|
||||
//PlayEventOnce("event:/Characters/sfx_footsteps_raccoon");
|
||||
//PlayEventOnce("event:/SFX/Dawn/Dawn_Attack");
|
||||
}
|
||||
|
||||
void SHADE::SHAudioSystem::Run(double dt)
|
||||
{
|
||||
static_cast<void>(dt);
|
||||
//if (GetKeyState(VK_SPACE) & 0x8000)
|
||||
// PlayEventOnce("event:/Characters/sfx_footsteps_raccoon");
|
||||
|
||||
fmodStudioSystem->update();
|
||||
if (!denseListener->empty())
|
||||
{
|
||||
SHAudioListenerComponent& listener = denseListener->at(0);
|
||||
SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
|
||||
if (listenerTransform)
|
||||
{
|
||||
listener.SetPos(listenerTransform->GetLocalPosition());
|
||||
listener.SetForward({ (listenerTransform->GetLocalScale()[0] > 0.f) ? 1.f : -1.f, 0.f, 0.f });
|
||||
FMOD_VECTOR pos = { listener.pos[0] ,listener.pos[1] ,0.f };
|
||||
FMOD_VECTOR forward = { listener.forward[0] ,listener.forward[1] ,listener.forward[2] };
|
||||
FMOD_VECTOR up = { listener.up[0] ,listener.up[1] ,listener.up[2] };
|
||||
fmodSystem->set3DListenerAttributes(0, &pos, nullptr, &forward, &up);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SHAudioSystem::AudioRoutine::AudioRoutine()
|
||||
: SHSystemRoutine("Audio Routine", false) {}
|
||||
|
||||
void SHAudioSystem::AudioRoutine::Execute(double dt) noexcept
|
||||
{
|
||||
reinterpret_cast<SHAudioSystem*>(system)->Run(dt);
|
||||
}
|
||||
|
||||
void SHADE::SHAudioSystem::Exit()
|
||||
{
|
||||
for (auto& event : eventMap)
|
||||
{
|
||||
result = event.second->releaseAllInstances();
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
for (auto& bank : bankMap)
|
||||
{
|
||||
result = bank.second->unload();
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
for (auto& sound : soundList)
|
||||
{
|
||||
result = sound.second->release();
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
if (bgmChannelGroup)
|
||||
{
|
||||
result = bgmChannelGroup->release();
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
if (sfxChannelGroup)
|
||||
{
|
||||
result = sfxChannelGroup->release();
|
||||
ErrorCheck();
|
||||
}
|
||||
|
||||
if (fmodStudioSystem)
|
||||
{
|
||||
result = fmodStudioSystem->release();
|
||||
ErrorCheck();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::ErrorCheck() const
|
||||
{
|
||||
if (result != FMOD_OK)
|
||||
std::cerr << "Audio system error: " << FMOD_ErrorString(result) << std::endl;
|
||||
}
|
||||
|
||||
void SHAudioSystem::PlayEventOnce(const char* path, bool isSFX, EntityID eid, bool spatial)
|
||||
{
|
||||
if (paused)
|
||||
return;
|
||||
auto it = eventMap.find(path);
|
||||
if (it != eventMap.end())
|
||||
{
|
||||
FMOD::Studio::EventInstance* event = nullptr;
|
||||
it->second->createInstance(&event);
|
||||
if (event)
|
||||
{
|
||||
|
||||
event->setVolume(masterVolume * (isSFX ? sfxVolume : bgmVolume));
|
||||
if (spatial)
|
||||
{
|
||||
if (SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
|
||||
{
|
||||
FMOD_3D_ATTRIBUTES attributes{ {} };
|
||||
attributes.forward.z = 1.0f;
|
||||
attributes.up.y = 1.0f;
|
||||
SHAudioListenerComponent& listener = denseListener->at(0);
|
||||
SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
|
||||
if (listenerTransform)
|
||||
{
|
||||
attributes.position.z = listenerTransform->GetLocalPosition()[2];
|
||||
}
|
||||
attributes.position.x = audioTransform->GetLocalPosition()[0];
|
||||
attributes.position.y = audioTransform->GetLocalPosition()[1];
|
||||
event->set3DAttributes(&attributes);
|
||||
}
|
||||
}
|
||||
event->start();
|
||||
event->release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::PlaySFX(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min, float max)
|
||||
{
|
||||
SHSound sound = soundList[id];
|
||||
int index = GetAvailableChannelIndex();
|
||||
if (index >= 0)
|
||||
{
|
||||
unsigned int mode{};
|
||||
mode |= (loop ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
|
||||
mode |= (spatial ? FMOD_3D : FMOD_2D);
|
||||
sound->setMode(mode);
|
||||
result = fmodSystem->playSound(sound, sfxChannelGroup, false, &audioChannels[index]);
|
||||
if (spatial && SHComponentManager::HasComponent<SHTransformComponent>(eid))
|
||||
{
|
||||
SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||
FMOD_VECTOR fpos{ audioTransform->GetLocalPosition()[0],audioTransform->GetLocalPosition()[1] ,0.f};
|
||||
audioChannels[index]->set3DAttributes(&fpos, nullptr);
|
||||
audioChannels[index]->setMode(mode);
|
||||
audioChannels[index]->set3DMinMaxDistance(min, max);
|
||||
}
|
||||
ErrorCheck();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::PlayBGM(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min, float max)
|
||||
{
|
||||
SHSound sound = soundList[id];
|
||||
int index = GetAvailableChannelIndex();
|
||||
if (index >= 0)
|
||||
{
|
||||
unsigned int mode{};
|
||||
mode |= (loop ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
|
||||
mode |= (spatial ? FMOD_3D : FMOD_2D);
|
||||
sound->setMode(mode);
|
||||
result = fmodSystem->playSound(sound, bgmChannelGroup, false, &audioChannels[index]);
|
||||
if (spatial && SHComponentManager::HasComponent<SHTransformComponent>(eid))
|
||||
{
|
||||
SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||
FMOD_VECTOR fpos{ audioTransform->GetLocalPosition()[0],audioTransform->GetLocalPosition()[1] ,0.f };
|
||||
audioChannels[index]->set3DAttributes(&fpos, nullptr);
|
||||
audioChannels[index]->setMode(mode);
|
||||
audioChannels[index]->set3DMinMaxDistance(min, max);
|
||||
}
|
||||
ErrorCheck();
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::SetMute(EntityID id, bool mute)
|
||||
{
|
||||
SHSound sound;
|
||||
for (auto& channel : audioChannels)
|
||||
{
|
||||
channel->getCurrentSound(&sound);
|
||||
if (soundList.find(id)->second == sound) // tbc
|
||||
{
|
||||
channel->setMute(mute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::StopSound(EntityID id)
|
||||
{
|
||||
SHSound sound;
|
||||
for (auto& channel : audioChannels)
|
||||
{
|
||||
channel->getCurrentSound(&sound);
|
||||
if (soundList.find(id)->second == sound) // tbc
|
||||
{
|
||||
channel->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHAudioSystem::StopAllSounds()
|
||||
{
|
||||
for (auto& channel : audioChannels)
|
||||
{
|
||||
bool isPlaying{ false };
|
||||
if (channel->isPlaying(&isPlaying) == FMOD_OK && isPlaying)
|
||||
channel->stop();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<FMOD_GUID> SHAudioSystem::GetEventGUID(const char* path)
|
||||
{
|
||||
FMOD_GUID guid;
|
||||
FMOD::Studio::EventDescription* event;
|
||||
result = fmodStudioSystem->getEvent(path, &event);
|
||||
ErrorCheck();
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
result = event->getID(&guid);
|
||||
ErrorCheck();
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
return guid;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
AudioClip* SHAudioSystem::CreateAudioClip(const char* path)
|
||||
{
|
||||
AudioClipID newID{};
|
||||
AudioClip* clip = nullptr;
|
||||
auto it = eventMap.find(path);
|
||||
if (it != eventMap.end())
|
||||
{
|
||||
FMOD::Studio::EventInstance* event = nullptr;
|
||||
it->second->createInstance(&event);
|
||||
if (event)
|
||||
{
|
||||
//event->start();
|
||||
newID = clipID;
|
||||
clipID++;
|
||||
eventInstances.emplace(newID, AudioClip(newID, event));
|
||||
clip = &eventInstances[newID];
|
||||
}
|
||||
}
|
||||
return clip;
|
||||
}
|
||||
|
||||
//std::vector<const char*> SHAudioSystem::GetAllEvents()
|
||||
//{
|
||||
// int count{};
|
||||
// stringsBank->getEventCount(&count);
|
||||
|
||||
// std::vector<FMOD::Studio::EventDescription*> events(count);
|
||||
// auto eventData = events.data();
|
||||
// int finalCount{};
|
||||
// stringsBank->getEventList(eventData, count, &finalCount);
|
||||
// std::vector<const char*> eventNames;
|
||||
// std::transform(events.begin(), events.end(), std::back_inserter(eventNames), [](FMOD::Studio::EventDescription* event)
|
||||
// {
|
||||
// char path[256];
|
||||
// event->getPath(path, 256, nullptr);
|
||||
// return path;
|
||||
// });
|
||||
// return eventNames;
|
||||
//}
|
||||
|
||||
//void SHAudioSystem::PlayEventInstance(FMOD::Studio::EventInstance* instance, bool isSFX, EntityID eid, bool spatial)
|
||||
//{
|
||||
// instance->setVolume(masterVolume * (isSFX ? sfxVolume : bgmVolume));
|
||||
// FMOD::ChannelGroup* channelGroup;
|
||||
// if (spatial)
|
||||
// {
|
||||
// if (SHTransformComponent* audioTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid))
|
||||
// {
|
||||
// FMOD_3D_ATTRIBUTES attributes{ {} };
|
||||
// attributes.forward.z = 1.0f;
|
||||
// attributes.up.y = 1.0f;
|
||||
// SHAudioListenerComponent& listener = denseListener->at(0);
|
||||
// SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
|
||||
// if (listenerTransform)
|
||||
// {
|
||||
// attributes.position.z = listenerTransform->GetTranslation()[2];
|
||||
// }
|
||||
// attributes.position.x = audioTransform->GetTranslation()[0];
|
||||
// attributes.position.y = audioTransform->GetTranslation()[1];
|
||||
// instance->set3DAttributes(&attributes);
|
||||
// }
|
||||
// }
|
||||
// instance->start();
|
||||
//}
|
||||
|
||||
int SHAudioSystem::GetAvailableChannelIndex()
|
||||
{
|
||||
bool isPlaying = false;
|
||||
for (int i = 0; i < AUDIO_SYS_MAX_CHANNELS; ++i)
|
||||
{
|
||||
audioChannels[i]->isPlaying(&isPlaying);
|
||||
if (!isPlaying)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
float SHAudioSystem::GetBgmVolume()
|
||||
{
|
||||
return bgmVolume;
|
||||
}
|
||||
float SHAudioSystem::GetSfxVolume()
|
||||
{
|
||||
return sfxVolume;
|
||||
}
|
||||
float SHAudioSystem::GetMasterVolume()
|
||||
{
|
||||
return masterVolume;
|
||||
}
|
||||
void SHAudioSystem::SetBgmVolume(float const bgmvol)
|
||||
{
|
||||
bgmChannelGroup->setVolume(bgmvol);
|
||||
}
|
||||
void SHAudioSystem::SetSfxVolume(float const sfxvol)
|
||||
{
|
||||
sfxChannelGroup->setVolume(sfxvol);
|
||||
}
|
||||
void SHAudioSystem::SetMasterVolume(float const mastervol)
|
||||
{
|
||||
masterGroup->setVolume(mastervol);
|
||||
}
|
||||
|
||||
void SHAudioSystem::SetPaused(bool pause)
|
||||
{
|
||||
paused = pause;
|
||||
for (auto const& channel : audioChannels)
|
||||
{
|
||||
channel->setPaused(paused);
|
||||
}
|
||||
for (auto const& event : eventMap)
|
||||
{
|
||||
int instanceCount = 0;
|
||||
event.second->getInstanceCount(&instanceCount);
|
||||
std::vector<FMOD::Studio::EventInstance*> instances(instanceCount);
|
||||
event.second->getInstanceList(instances.data(), static_cast<int>(instances.size()), &instanceCount);
|
||||
for (auto const& instance : instances)
|
||||
{
|
||||
instance->setPaused(pause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SHAudioSystem::GetPaused() const
|
||||
{
|
||||
return paused;
|
||||
}
|
||||
|
||||
SHVec3 SHAudioSystem::GetListenerPosition()
|
||||
{
|
||||
auto &listener = denseListener->at(0);
|
||||
SHTransformComponent* listenerTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(listener.GetEID());
|
||||
if (listenerTransform)
|
||||
{
|
||||
return listenerTransform->GetLocalPosition();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void SHAudioSystem::LoadBank(const char* path)
|
||||
{
|
||||
FMOD::Studio::Bank* bank = nullptr;
|
||||
result = fmodStudioSystem->loadBankFile(path, FMOD_STUDIO_LOAD_BANK_NORMAL, &bank);
|
||||
ErrorCheck();
|
||||
if (result != FMOD_OK)
|
||||
return;
|
||||
bankMap.emplace(path, bank);
|
||||
bank->loadSampleData();
|
||||
int numOfEvents;
|
||||
bank->getEventCount(&numOfEvents);
|
||||
if (numOfEvents > 0)
|
||||
{
|
||||
std::vector<FMOD::Studio::EventDescription*> events(numOfEvents);
|
||||
bank->getEventList(events.data(), numOfEvents, &numOfEvents);
|
||||
char eventName[512];
|
||||
for (int i{}; i < numOfEvents; ++i)
|
||||
{
|
||||
FMOD::Studio::EventDescription* event = events[i];
|
||||
event->getPath(eventName, 512, nullptr);
|
||||
eventMap.emplace(eventName, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioClip::AudioClip(AudioClipID clipID, FMOD::Studio::EventInstance* inst)
|
||||
:instance(inst), id(clipID)
|
||||
{
|
||||
}
|
||||
|
||||
AudioClip::~AudioClip()
|
||||
{
|
||||
}
|
||||
|
||||
void AudioClip::Play(bool isSfx)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->start();
|
||||
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
|
||||
instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume()));
|
||||
}
|
||||
|
||||
void AudioClip::Play(SHVec3 position, bool isSfx)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->start();
|
||||
FMOD_3D_ATTRIBUTES attributes{ {} };
|
||||
attributes.forward.z = 1.0f;
|
||||
attributes.up.y = 1.0f;
|
||||
|
||||
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
|
||||
SHVec3 listenerPos = audioSystem->GetListenerPosition();
|
||||
attributes.position.x = position[0];
|
||||
attributes.position.y = position[1];
|
||||
attributes.position.z = listenerPos[2];
|
||||
instance->set3DAttributes(&attributes);
|
||||
instance->setVolume(audioSystem->GetMasterVolume() * (isSfx ? audioSystem->GetSfxVolume() : audioSystem->GetBgmVolume()));
|
||||
}
|
||||
|
||||
void AudioClip::Stop(bool fadeOut)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->stop(fadeOut ? FMOD_STUDIO_STOP_ALLOWFADEOUT : FMOD_STUDIO_STOP_IMMEDIATE);
|
||||
}
|
||||
|
||||
void AudioClip::SetPause(bool pause)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->setPaused(pause);
|
||||
}
|
||||
|
||||
bool AudioClip::IsPaused()
|
||||
{
|
||||
if (!instance)
|
||||
return true;
|
||||
|
||||
bool paused{};
|
||||
instance->getPaused(&paused);
|
||||
return paused;
|
||||
}
|
||||
|
||||
|
||||
void AudioClip::SetParameter(const char* paramName, float value)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->setParameterByName(paramName, value);
|
||||
}
|
||||
|
||||
void AudioClip::SetParameterLabel(const char* paramName, const char* label)
|
||||
{
|
||||
if (!instance)
|
||||
return;
|
||||
instance->setParameterByNameWithLabel(paramName, label);
|
||||
}
|
||||
|
||||
float AudioClip::GetParameterValue(const char* paramName)
|
||||
{
|
||||
if (!instance)
|
||||
return {};
|
||||
float value{};
|
||||
instance->getParameterByName(paramName, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include "ECS_Base/System/SHSystem.h"
|
||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
#include "Math/SHMath.h"
|
||||
#include <optional>
|
||||
#include <FMOD/fmod_studio.hpp>
|
||||
#include "SH_API.h"
|
||||
#define AUDIO_SYS_MAX_CHANNELS 1024
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
typedef FMOD::Sound* SHSound;
|
||||
typedef FMOD::Studio::Bank* SHBank;
|
||||
|
||||
class SHAudioListenerComponent;
|
||||
|
||||
typedef uint64_t AudioClipID;
|
||||
|
||||
class AudioClip
|
||||
{
|
||||
public:
|
||||
AudioClip() = default;
|
||||
AudioClip(AudioClipID clipID, FMOD::Studio::EventInstance* inst);
|
||||
~AudioClip();
|
||||
void Play(bool isSfx = true);
|
||||
void Play(SHVec3 position, bool isSfx = true);
|
||||
void Stop(bool fadeOut = true);
|
||||
|
||||
void SetPause(bool pause);
|
||||
bool IsPaused();
|
||||
void SetParameter(const char* paramName, float value);
|
||||
void SetParameterLabel(const char* paramName, const char* label);
|
||||
float GetParameterValue(const char* paramName);
|
||||
friend class SHAudioSystem;
|
||||
private:
|
||||
FMOD::Studio::EventInstance* instance;
|
||||
AudioClipID id;
|
||||
};
|
||||
|
||||
class SH_API SHAudioSystem : public SHSystem
|
||||
{
|
||||
public:
|
||||
SHAudioSystem();
|
||||
~SHAudioSystem();
|
||||
|
||||
void Init();
|
||||
void Run(double dt);
|
||||
class SH_API AudioRoutine final : public SHSystemRoutine
|
||||
{
|
||||
public:
|
||||
AudioRoutine();
|
||||
void Execute(double dt) noexcept override final;
|
||||
};
|
||||
void Exit();
|
||||
|
||||
int GetAvailableChannelIndex();
|
||||
/*std::vector<SHSound>::size_type CreateSound(const char* filepath, bool loop = false);*/
|
||||
void PlaySFX(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f);
|
||||
void PlayBGM(EntityID id, EntityID eid, const bool& loop, const bool& spatial, float min = 5.0f, float max = 1000.0f);
|
||||
void PlayEventOnce(const char* path, bool isSFX = true, EntityID eid = MAX_EID, bool spatial = false);
|
||||
void SetMute(EntityID id, bool);
|
||||
void StopSound(EntityID id);
|
||||
void StopAllSounds();
|
||||
|
||||
std::optional<FMOD_GUID> GetEventGUID(const char* path);
|
||||
AudioClip* CreateAudioClip(const char* path);
|
||||
//std::vector<const char*> GetAllEvents();
|
||||
|
||||
float GetBgmVolume();
|
||||
float GetSfxVolume();
|
||||
float GetMasterVolume();
|
||||
void SetBgmVolume(float const bgmvol);
|
||||
void SetSfxVolume(float const sfxvol);
|
||||
void SetMasterVolume(float const mastervol);
|
||||
void SetPaused(bool pause);
|
||||
bool GetPaused() const;
|
||||
SHVec3 GetListenerPosition();
|
||||
void LoadBank(const char* path);
|
||||
private:
|
||||
FMOD::Studio::System* fmodStudioSystem;
|
||||
FMOD::System* fmodSystem;
|
||||
bool paused;
|
||||
void ErrorCheck() const;
|
||||
|
||||
void* extraDriverData;
|
||||
std::unordered_map<EntityID, SHSound> soundList;
|
||||
//std::unordered_map<ResourceID, SHBank> bankMap;
|
||||
std::unordered_map<std::string, SHBank> bankMap;
|
||||
std::unordered_map<std::string, FMOD::Studio::EventDescription*> eventMap;
|
||||
std::unordered_map<AudioClipID, AudioClip> eventInstances;
|
||||
FMOD::ChannelGroup* bgmChannelGroup, * sfxChannelGroup, * masterGroup;
|
||||
FMOD::Channel* audioChannels[AUDIO_SYS_MAX_CHANNELS];
|
||||
FMOD_RESULT result;
|
||||
float bgmVolume, sfxVolume, masterVolume;
|
||||
unsigned int version;
|
||||
FMOD_SPEAKERMODE speakerMode;
|
||||
SHBank masterBank, stringsBank, musicBank, sfxBank; //To do: change to map of banks loaded by resource manager
|
||||
|
||||
std::vector<SHAudioListenerComponent>* denseListener;
|
||||
AudioClipID clipID = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
#include "SHpch.h"
|
||||
#include "../SHECSMacros.h"
|
||||
#include "SH_API.h"
|
||||
#include "ECS_Base/General/SHFamily.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -117,4 +118,7 @@ namespace SHADE
|
|||
|
||||
|
||||
};
|
||||
|
||||
|
||||
template class SH_API SHFamilyID<SHComponent>;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHComponentAddedEvent
|
||||
{
|
||||
EntityID eid;
|
||||
ComponentTypeID addedComponentType;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHComponentRemovedEvent
|
||||
{
|
||||
EntityID eid;
|
||||
ComponentTypeID removedComponentType;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
#include "SHFamily.h"
|
||||
#include "SHpch.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
//initialize currentID as 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -14,16 +14,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "../SHECSMacros.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
template<typename BaseClass>
|
||||
class SHFamilyID
|
||||
class SH_API SHFamilyID
|
||||
{
|
||||
private:
|
||||
//this is used to keep track of the new current ID to be assign to a new Derived class type.
|
||||
static ComponentTypeID currentID;
|
||||
|
||||
|
||||
/*!*************************************************************************
|
||||
* \brief Construct a new SHFamilyID object
|
||||
|
@ -46,6 +47,9 @@ namespace SHADE
|
|||
}
|
||||
public:
|
||||
|
||||
//this is used to keep track of the new current ID to be assign to a new Derived class type.
|
||||
static inline ComponentTypeID currentID = 0;
|
||||
|
||||
/*!*************************************************************************
|
||||
* \brief
|
||||
* Checks if this identifier is cuurrently in use / valid.
|
||||
|
@ -59,7 +63,6 @@ namespace SHADE
|
|||
{
|
||||
return(id < currentID);
|
||||
}
|
||||
|
||||
/*!*************************************************************************
|
||||
* \brief
|
||||
* Get the ID of a derived class type.
|
||||
|
@ -68,16 +71,27 @@ namespace SHADE
|
|||
* @tparam DerivedClass
|
||||
* The derived class type that we are trying to get the ID of.
|
||||
***************************************************************************/
|
||||
#ifdef SH_API_EXPORT
|
||||
template<typename DerivedClass>
|
||||
static ENABLE_IF_DERIVED(ComponentTypeID, BaseClass, DerivedClass) GetID() noexcept
|
||||
static SH_API ENABLE_IF_DERIVED(ComponentTypeID, BaseClass, DerivedClass) GetID() noexcept
|
||||
{
|
||||
//The first time a new derived class type call this get id, it will initialize id using the currentID from familyID class.
|
||||
static ComponentTypeID id = currentID++;
|
||||
static ComponentTypeID id = SHFamilyID<BaseClass>::currentID++;
|
||||
return id;
|
||||
//return 0;
|
||||
}
|
||||
#else
|
||||
template<typename DerivedClass>
|
||||
static SH_API ENABLE_IF_DERIVED(ComponentTypeID, BaseClass, DerivedClass) GetID() noexcept;
|
||||
#endif // SH_API_EXPORT
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
//initialize currentID as 0
|
||||
template<typename BaseClass>
|
||||
ComponentTypeID SHFamilyID<BaseClass>::currentID = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -17,8 +17,11 @@
|
|||
#include "../General/SHSparseSetContainer.h"
|
||||
#include "../Components/SHComponent.h"
|
||||
#include "../Components/SHComponentGroup.h"
|
||||
#include "../Events/SHComponentAddedEvent.h"
|
||||
#include "../Events/SHComponentRemovedEvent.h"
|
||||
//#include "Scene/SHSceneNode.h"
|
||||
#include "SH_API.h"
|
||||
#include "Events/SHEventManager.hpp"
|
||||
|
||||
|
||||
#include <cassert>
|
||||
|
@ -216,6 +219,11 @@ namespace SHADE
|
|||
comp->OnCreate();
|
||||
}
|
||||
|
||||
SHComponentAddedEvent eventData;
|
||||
eventData.eid = entityID;
|
||||
eventData.addedComponentType = ComponentFamily::GetID<T>();
|
||||
|
||||
SHEventManager::BroadcastEvent<SHComponentAddedEvent>(eventData, SH_COMPONENT_ADDED_EVENT);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -247,6 +255,13 @@ namespace SHADE
|
|||
{
|
||||
comp->OnCreate();
|
||||
}
|
||||
|
||||
SHComponentAddedEvent eventData;
|
||||
eventData.eid = entityID;
|
||||
eventData.addedComponentType = componentTypeID;
|
||||
|
||||
SHEventManager::BroadcastEvent<SHComponentAddedEvent>(eventData, SH_COMPONENT_ADDED_EVENT);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -313,6 +328,12 @@ namespace SHADE
|
|||
|
||||
|
||||
componentSet.GetSparseSet<T>()->Remove(EntityHandleGenerator::GetIndex(entityID));
|
||||
|
||||
SHComponentRemovedEvent eventData;
|
||||
eventData.eid = entityID;
|
||||
eventData.removedComponentType = ComponentFamily::GetID<T>();
|
||||
|
||||
SHEventManager::BroadcastEvent<SHComponentRemovedEvent>(eventData, SH_COMPONENT_REMOVED_EVENT);
|
||||
}
|
||||
|
||||
/*!*************************************************************************
|
||||
|
@ -464,11 +485,6 @@ namespace SHADE
|
|||
return componentGroups[index];
|
||||
}
|
||||
|
||||
static void AddScriptComponent(EntityID eid, std::string const& scriptClassName) noexcept;
|
||||
|
||||
static void RemoveScriptComponent(EntityID eid, std::string const& scriptClassName) noexcept;
|
||||
|
||||
|
||||
};// end SHComponentManager
|
||||
|
||||
|
||||
|
|
|
@ -68,6 +68,9 @@ namespace SHADE
|
|||
id = ((SystemID)version << sizeof(SystemVersionID) * CHAR_BIT) + typeID;
|
||||
}
|
||||
systemContainer.emplace(id, std::make_unique<T>());
|
||||
|
||||
auto size = systemContainer.size();
|
||||
|
||||
systemContainer[id].get()->systemID = id;
|
||||
|
||||
return id;
|
||||
|
|
|
@ -26,4 +26,6 @@ const EntityIndex MAX_EID = 51000;
|
|||
#define ENABLE_IF_UINT(_TYPE, _RETURN)\
|
||||
typename std::enable_if<(std::is_integral<_TYPE>::value && !std::is_signed<_TYPE>::value),_RETURN>::type
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "../SHECSMacros.h"
|
||||
#include "SH_API.h"
|
||||
#include "ECS_Base/General/SHFamily.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -69,5 +70,9 @@ namespace SHADE
|
|||
};
|
||||
|
||||
|
||||
template class SH_API SHFamilyID<SHSystem>;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Components/SHComponent.h"
|
||||
#include <rttr/registration>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -27,4 +28,50 @@ namespace SHADE
|
|||
std::string value{};
|
||||
};
|
||||
|
||||
class SHComponent_ENUM : public SHComponent
|
||||
{
|
||||
public:
|
||||
enum class Option
|
||||
{
|
||||
OPT_A,
|
||||
OPT_B,
|
||||
OPT_C
|
||||
};
|
||||
|
||||
bool boolTest{};
|
||||
int intTest{};
|
||||
float floatTest{};
|
||||
double doubleTest{};
|
||||
long longTest{};
|
||||
uint8_t uint8Test{};
|
||||
uint16_t uint16Test{};
|
||||
uint32_t uint32Test{};
|
||||
uint64_t uint64Test{};
|
||||
|
||||
|
||||
Option option;
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
|
||||
RTTR_REGISTRATION
|
||||
{
|
||||
using namespace rttr;
|
||||
registration::enumeration<SHComponent_ENUM::Option>("Option")
|
||||
(
|
||||
value("Option A", SHComponent_ENUM::Option::OPT_A),
|
||||
value("Option B", SHComponent_ENUM::Option::OPT_B),
|
||||
value("Option C", SHComponent_ENUM::Option::OPT_C)
|
||||
);
|
||||
rttr::registration::class_<SHComponent_ENUM>("Enum Component")
|
||||
.property("Option", &SHComponent_ENUM::option)
|
||||
.property("boolTest", &SHComponent_ENUM::boolTest)
|
||||
.property("intTest", &SHComponent_ENUM::intTest)( metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("floatTest", &SHComponent_ENUM::floatTest)(metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("doubleTest", &SHComponent_ENUM::doubleTest)(metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("uint8Test", &SHComponent_ENUM::uint8Test)(metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("uint16Test", &SHComponent_ENUM::uint16Test)(metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("uint32Test", &SHComponent_ENUM::uint32Test)(metadata("MIN", 0.0f), metadata("MAX", 1.f))
|
||||
.property("uint64Test", &SHComponent_ENUM::uint64Test)(metadata("MIN", 0.0f), metadata("MAX", 1.f));
|
||||
}
|
||||
|
||||
}
|
|
@ -114,7 +114,7 @@ namespace SHADE
|
|||
|
||||
auto* entity = SHEntityManager::GetEntityByID(currentNode->GetEntityID());
|
||||
//Draw Node
|
||||
bool isNodeOpen = ImGui::TreeNodeEx((void*)eid, nodeFlags, "%u: %s", EntityHandleGenerator::GetIndex(eid), entity->name.c_str());
|
||||
bool isNodeOpen = ImGui::TreeNodeEx(reinterpret_cast<void*>(entity), nodeFlags, "%u: %s", EntityHandleGenerator::GetIndex(eid), entity->name.c_str());
|
||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||
|
||||
//Check For Begin Drag
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
#include "Reflection/SHReflectionMetadata.h"
|
||||
namespace SHADE
|
||||
{
|
||||
template<typename T, std::enable_if_t<std::is_base_of<SHComponent, T>::value, bool> = true>
|
||||
|
@ -45,7 +46,7 @@ namespace SHADE
|
|||
if (!component)
|
||||
return;
|
||||
auto componentType = rttr::type::get(*component);
|
||||
CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
|
||||
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
|
||||
ImGui::SameLine();
|
||||
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||
{
|
||||
|
@ -55,14 +56,136 @@ namespace SHADE
|
|||
{
|
||||
auto const& type = property.get_type();
|
||||
|
||||
if (type == rttr::type::get<SHVec4>())
|
||||
if(type.is_enumeration())
|
||||
{
|
||||
DragVec4(property.get_name().data(), { "X", "Y", "Z", "W" }, [component, property]() {return property.get_value(component).template convert<SHVec4>(); }, [component, property](SHVec4 vec) {return property.set_value(component, vec); });
|
||||
auto enumAlign = type.get_enumeration();
|
||||
auto names = enumAlign.get_names();
|
||||
std::vector<const char*> list;
|
||||
for(auto const& name : names)
|
||||
list.push_back(name.data());
|
||||
SHEditorWidgets::ComboBox(property.get_name().data(), list, [component, property]{return property.get_value(component).to_int();}, [component, property](int const& idx)
|
||||
{
|
||||
auto enumAlign = property.get_enumeration();
|
||||
auto values = enumAlign.get_values();
|
||||
auto it = std::next(values.begin(), idx);
|
||||
property.set_value(component, *it);
|
||||
});
|
||||
}
|
||||
else if(type.is_arithmetic())
|
||||
{
|
||||
if (type == rttr::type::get<bool>())
|
||||
{
|
||||
SHEditorWidgets::CheckBox(property.get_name().data(), [component, property]{return property.get_value(component).to_bool();}, [component, property](bool const& result){property.set_value(component, result);});
|
||||
}
|
||||
//else if (type == rttr::type::get<char>())
|
||||
//{
|
||||
//
|
||||
//}
|
||||
else if (type == rttr::type::get<int8_t>() || type == rttr::type::get<int16_t>() || type == rttr::type::get<int32_t>() || type == rttr::type::get<int64_t>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
if(metaMin && metaMax)
|
||||
{
|
||||
SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMin.template get_value<int>(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);});
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragInt(property.get_name().data(), [component, property]{return property.get_value(component).to_int();}, [component, property](int const& result){property.set_value(component, result);});
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<uint8_t>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
if(metaMin.is_valid() && metaMax.is_valid())
|
||||
{
|
||||
SHEditorWidgets::SliderScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, metaMin.template get_value<uint8_t>(), metaMax.template get_value<uint8_t>(), [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},"%zu");
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragScalar<uint8_t>(property.get_name().data(), ImGuiDataType_U8, [component, property]{return property.get_value(component).to_uint8();}, [component, property](uint8_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu");
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<uint16_t>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
if(metaMin.is_valid() && metaMax.is_valid())
|
||||
{
|
||||
SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMin.template get_value<uint16_t>(), [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},"%zu");
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, [component, property]{return property.get_value(component).to_uint16();}, [component, property](uint16_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu");
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<uint32_t>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
if (metaMin.is_valid() && metaMax.is_valid())
|
||||
{
|
||||
SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMin.template get_value<uint32_t>(), [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },"%zu");
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, [component, property]{ return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result){property.set_value(component, result); },0.1f,0,0,"%zu");
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<uint64_t>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
if(metaMin.is_valid() && metaMax.is_valid())
|
||||
{
|
||||
SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMin.template get_value<uint64_t>(), [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},"%zu");
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, [component, property]{return property.get_value(component).to_uint64();}, [component, property](uint64_t const& result){property.set_value(component, result);},0.1f,0,0,"%zu");
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<float>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
if(metaMin.is_valid() && metaMax.is_valid())
|
||||
{
|
||||
SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value<float>(), metaMin.template get_value<float>(), [component, property]{return property.get_value(component).to_float();}, [component, property](float const& result){property.set_value(component, result);});
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragFloat(property.get_name().data(), [component, property]{return property.get_value(component).to_float();}, [component, property](float const& result){property.set_value(component, result);});
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<double>())
|
||||
{
|
||||
auto metaMin = property.get_metadata(META::min);
|
||||
auto metaMax = property.get_metadata(META::max);
|
||||
if(metaMin.is_valid() && metaMax.is_valid())
|
||||
{
|
||||
SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMin.template get_value<double>(), [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);});
|
||||
}
|
||||
else
|
||||
{
|
||||
SHEditorWidgets::DragScalar<double>(property.get_name().data(), ImGuiDataType_Double, [component, property]{return property.get_value(component).to_double();}, [component, property](double const& result){property.set_value(component, result);}, 0.1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == rttr::type::get<SHVec4>())
|
||||
{
|
||||
SHEditorWidgets::DragVec4(property.get_name().data(), { "X", "Y", "Z", "W" }, [component, property]() {return property.get_value(component).template convert<SHVec4>(); }, [component, property](SHVec4 vec) {return property.set_value(component, vec); });
|
||||
}
|
||||
else if (type == rttr::type::get<SHVec3>())
|
||||
{
|
||||
DragVec3(property.get_name().data(), { "X", "Y", "Z" }, [component, property]() {return property.get_value(component).template convert<SHVec3>(); }, [component, property](SHVec3 vec) {return property.set_value(component, vec); });
|
||||
SHEditorWidgets::DragVec3(property.get_name().data(), { "X", "Y", "Z" }, [component, property]() {return property.get_value(component).template convert<SHVec3>(); }, [component, property](SHVec3 vec) {return property.set_value(component, vec); });
|
||||
}
|
||||
else if (type == rttr::type::get<SHVec2>())
|
||||
{
|
||||
SHEditorWidgets::DragVec2(property.get_name().data(), { "X", "Y"}, [component, property]() {return property.get_value(component).template convert<SHVec2>(); }, [component, property](SHVec2 vec) {return property.set_value(component, vec); });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else DrawContextMenu(component);
|
||||
|
|
|
@ -11,7 +11,13 @@
|
|||
#include "Editor/SHImGuiHelpers.hpp"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
#include "SHEditorComponentView.hpp"
|
||||
#include "ECS_Base/UnitTesting/SHTestComponents.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "AudioSystem/SHAudioSystem.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -39,13 +45,19 @@ namespace SHADE
|
|||
SHEditorWindow::Update();
|
||||
if (Begin())
|
||||
{
|
||||
if (ImGui::Button("AUDIO"))
|
||||
{
|
||||
auto audioSystem = SHSystemManager::GetSystem<SHADE::SHAudioSystem>();
|
||||
audioSystem->PlayEventOnce("event:/Characters/sfx_footsteps_raccoon");
|
||||
}
|
||||
|
||||
if (!SHEditor::selectedEntities.empty())
|
||||
{
|
||||
EntityID const& eid = SHEditor::selectedEntities[0];
|
||||
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
||||
|
||||
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
||||
CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
|
||||
SHEditorWidgets::CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::InputText("##EntityName", &entity->name);
|
||||
|
@ -54,13 +66,27 @@ namespace SHADE
|
|||
{
|
||||
DrawComponent(transformComponent);
|
||||
}
|
||||
if(auto renderableComponent = SHComponentManager::GetComponent_s<SHRenderable>(eid))
|
||||
{
|
||||
DrawComponent(renderableComponent);
|
||||
}
|
||||
if(auto testComponent = SHComponentManager::GetComponent_s<SHComponent_ENUM>(eid))
|
||||
{
|
||||
DrawComponent(testComponent);
|
||||
}
|
||||
ImGui::Separator();
|
||||
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
||||
{
|
||||
DrawAddComponentButton<SHTransformComponent>(eid);
|
||||
DrawAddComponentButton<SHRenderable>(eid);
|
||||
DrawAddComponentButton<SHComponent_ENUM>(eid);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
// Render Scripts
|
||||
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->RenderScriptsInInspector(eid);
|
||||
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
#include "SHEditorMenuBar.h"
|
||||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "Editor/Command/SHCommandManager.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
#include "Editor/SHEditor.hpp"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
|
||||
//#==============================================================#
|
||||
//|| Library Includes ||
|
||||
|
@ -14,9 +17,6 @@
|
|||
#include <imgui_internal.h>
|
||||
#include <rttr/type>
|
||||
|
||||
#include "Editor/SHEditor.hpp"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
constexpr ImGuiWindowFlags editorMenuBarFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
|
||||
|
@ -100,6 +100,25 @@ namespace SHADE
|
|||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Scripts"))
|
||||
{
|
||||
if (ImGui::Selectable("Generate Visual Studio Project"))
|
||||
{
|
||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->GenerateScriptsCsProjFile();
|
||||
}
|
||||
if (ImGui::Selectable("Build Scripts - Debug"))
|
||||
{
|
||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->BuildScriptAssembly(true, true);
|
||||
}
|
||||
if (ImGui::Selectable("Build Scripts - Release"))
|
||||
{
|
||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->BuildScriptAssembly(false, true);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHEditorProfiler.h"
|
||||
#include <imgui.h>
|
||||
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "FRC/SHFramerateController.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHEditorProfiler::SHEditorProfiler()
|
||||
:SHEditorWindow("Profiler", ImGuiWindowFlags_None)
|
||||
{
|
||||
}
|
||||
|
||||
void SHEditorProfiler::Init()
|
||||
{
|
||||
SHEditorWindow::Init();
|
||||
}
|
||||
|
||||
void SHEditorProfiler::Update()
|
||||
{
|
||||
SHEditorWindow::Update();
|
||||
|
||||
const float dt = static_cast<float>(SHFrameRateController::GetRawDeltaTime());
|
||||
if(frames.size() > MaxFramesDisplayed)
|
||||
{
|
||||
for (size_t i = 1; i < frames.size(); i++)
|
||||
{
|
||||
frames[i-1] = frames[i];
|
||||
}
|
||||
frames[frames.size() - 1] = dt;
|
||||
}
|
||||
else
|
||||
{
|
||||
frames.push_back(dt);
|
||||
}
|
||||
if(Begin())
|
||||
{
|
||||
ImGui::PlotLines("DT", frames.data(), static_cast<int>(frames.size()), 0, nullptr, 0.0f, 16.0f);
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void SHEditorProfiler::Exit()
|
||||
{
|
||||
SHEditorWindow::Exit();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||
#include <vector>
|
||||
constexpr uint32_t MaxFramesDisplayed = 100;
|
||||
namespace SHADE
|
||||
{
|
||||
class SHEditorProfiler final : public SHEditorWindow
|
||||
{
|
||||
public:
|
||||
SHEditorProfiler();
|
||||
void Init() override;
|
||||
void Update() override;
|
||||
void Exit() override;
|
||||
|
||||
private:
|
||||
std::vector<float> frames;
|
||||
};
|
||||
}
|
|
@ -2,3 +2,4 @@
|
|||
#include "MenuBar/SHEditorMenuBar.h" //Menu Bar
|
||||
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
||||
#include "Inspector/SHEditorInspector.h" //Inspector
|
||||
#include "Profiling/SHEditorProfiler.h" //Profiler
|
|
@ -843,7 +843,7 @@
|
|||
#define ICON_MD_FLIP_TO_FRONT "\xee\xa2\x83" // U+e883
|
||||
#define ICON_MD_FLOOD "\xee\xaf\xa6" // U+ebe6
|
||||
#define ICON_MD_FLOURESCENT "\xee\xb0\xb1" // U+ec31
|
||||
#define ICON_MD_FLOURESCENT "\xef\x80\x8d" // U+f00d
|
||||
#define ICON_MD_FLOURESCENT2 "\xef\x80\x8d" // U+f00d
|
||||
#define ICON_MD_FLUORESCENT "\xee\xb0\xb1" // U+ec31
|
||||
#define ICON_MD_FLUTTER_DASH "\xee\x80\x8b" // U+e00b
|
||||
#define ICON_MD_FMD_BAD "\xef\x80\x8e" // U+f00e
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "SHEditor.hpp"
|
||||
#include "SHEditorWidgets.hpp"
|
||||
|
||||
#include "Math/Transform/SHTransformSystem.h"
|
||||
|
||||
//#==============================================================#
|
||||
//|| Editor Window Includes ||
|
||||
//#==============================================================#
|
||||
|
@ -87,6 +89,11 @@ namespace SHADE
|
|||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; //Enable docking
|
||||
|
||||
InitFonts();
|
||||
|
||||
|
||||
auto id = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
auto id2 = SHFamilyID<SHSystem>::GetID<SHTransformSystem>();
|
||||
auto id3 = SHFamilyID<SHSystem>::GetID<SHGraphicsSystem>();
|
||||
InitBackend(sdlWindow);
|
||||
|
||||
SetStyle(Style::SHADE);
|
||||
|
@ -95,6 +102,7 @@ namespace SHADE
|
|||
CreateEditorWindow<SHEditorMenuBar>();
|
||||
CreateEditorWindow<SHHierarchyPanel>();
|
||||
CreateEditorWindow<SHEditorInspector>();
|
||||
CreateEditorWindow<SHEditorProfiler>();
|
||||
|
||||
SHLOG_INFO("Successfully initialised SHADE Engine Editor")
|
||||
}
|
||||
|
@ -103,10 +111,10 @@ namespace SHADE
|
|||
{
|
||||
(void)dt;
|
||||
NewFrame();
|
||||
|
||||
for (const auto& window : editorWindows | std::views::values)
|
||||
{
|
||||
window->Update();
|
||||
if(window->isOpen)
|
||||
window->Update();
|
||||
}
|
||||
|
||||
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||
|
@ -292,6 +300,8 @@ namespace SHADE
|
|||
imguiCommandBuffer->EndRecording();
|
||||
gfxSystem->GetQueue()->SubmitCommandBuffer({ imguiCommandBuffer }, {}, {}, vk::PipelineStageFlagBits::eNone, {});
|
||||
|
||||
gfxSystem->GetDevice()->WaitIdle();
|
||||
|
||||
ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
|
||||
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
/************************************************************************************//*!
|
||||
\file EditorUI.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Nov 7, 2021
|
||||
\brief Contains the implementation of the EditorUI class.
|
||||
|
||||
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.
|
||||
*//*************************************************************************************/
|
||||
// Precompiled Header
|
||||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "SHEditorUI.h"
|
||||
// External Dependencies
|
||||
#include <imgui.h>
|
||||
#include "SHEditorWidgets.hpp"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - ID Stack */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHEditorUI::PushID(const std::string& id)
|
||||
{
|
||||
ImGui::PushID(id.c_str());
|
||||
}
|
||||
|
||||
void SHEditorUI::PushID(int id)
|
||||
{
|
||||
ImGui::PushID(id);
|
||||
}
|
||||
|
||||
void SHEditorUI::PopID()
|
||||
{
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Indent */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHEditorUI::Indent()
|
||||
{
|
||||
ImGui::Indent();
|
||||
}
|
||||
void SHEditorUI::Unindent()
|
||||
{
|
||||
ImGui::Unindent();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Organizers */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
bool SHEditorUI::CollapsingHeader(const std::string& title)
|
||||
{
|
||||
return ImGui::CollapsingHeader(title.c_str());
|
||||
}
|
||||
|
||||
void SHEditorUI::SameLine()
|
||||
{
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
void SHEditorUI::Separator()
|
||||
{
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
bool SHEditorUI::BeginMenu(const std::string& label)
|
||||
{
|
||||
return ImGui::BeginMenu(label.data());
|
||||
}
|
||||
|
||||
bool SHEditorUI::BeginMenu(const std::string& label, const char* icon)
|
||||
{
|
||||
return ImGui::BeginMenu(std::format("{} {}", icon, label.data()).data());
|
||||
}
|
||||
|
||||
void SHEditorUI::EndMenu()
|
||||
{
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Pop Ups */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
bool SHEditorUI::BeginPopup(const std::string& label)
|
||||
{
|
||||
return ImGui::BeginPopup(label.c_str());
|
||||
}
|
||||
|
||||
bool SHEditorUI::BeginPopupContextItem(const std::string& label)
|
||||
{
|
||||
return ImGui::BeginPopupContextItem(label.data());
|
||||
}
|
||||
|
||||
void SHEditorUI::EndPopup()
|
||||
{
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
void SHEditorUI::OpenPopup(const std::string& label)
|
||||
{
|
||||
ImGui::OpenPopup(label.c_str());
|
||||
}
|
||||
|
||||
bool SHEditorUI::MenuItem(const std::string& label)
|
||||
{
|
||||
return ImGui::MenuItem(label.c_str());
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Widgets */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHEditorUI::Text(const std::string& title)
|
||||
{
|
||||
ImGui::Text(title.c_str());
|
||||
}
|
||||
bool SHEditorUI::SmallButton(const std::string& title)
|
||||
{
|
||||
return ImGui::SmallButton(title.c_str());
|
||||
}
|
||||
bool SHEditorUI::Button(const std::string& title)
|
||||
{
|
||||
return ImGui::Button(title.c_str());
|
||||
}
|
||||
|
||||
bool SHEditorUI::Selectable(const std::string& label)
|
||||
{
|
||||
return ImGui::Selectable(label.data());
|
||||
}
|
||||
|
||||
bool SHEditorUI::Selectable(const std::string& label, const char* icon)
|
||||
{
|
||||
return ImGui::Selectable(std::format("{} {}", icon, label).data());
|
||||
}
|
||||
|
||||
bool SHEditorUI::InputCheckbox(const std::string& label, bool& value)
|
||||
{
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
return ImGui::Checkbox("#", &value);
|
||||
}
|
||||
bool SHEditorUI::InputInt(const std::string& label, int& value)
|
||||
{
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputInt("#", &value,
|
||||
1, 10,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value)
|
||||
{
|
||||
int signedVal = static_cast<int>(value);
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
const bool CHANGED = InputInt("#", signedVal);
|
||||
if (CHANGED)
|
||||
{
|
||||
signedVal = std::clamp(signedVal, 0, std::numeric_limits<int>::max());
|
||||
value = static_cast<unsigned int>(signedVal);
|
||||
}
|
||||
return CHANGED;
|
||||
}
|
||||
bool SHEditorUI::InputFloat(const std::string& label, float& value)
|
||||
{
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputFloat("#", &value,
|
||||
0.1f, 1.0f, "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
bool SHEditorUI::InputDouble(const std::string& label, double& value)
|
||||
{
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputDouble("#", &value,
|
||||
0.1, 1.0, "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
bool SHEditorUI::InputAngle(const std::string& label, double& value)
|
||||
{
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputDouble("#", &value,
|
||||
1.0, 45.0, "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
|
||||
bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value)
|
||||
{
|
||||
float val = static_cast<float>(value);
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
const bool CHANGED = ImGui::SliderFloat("#", &val,
|
||||
static_cast<float>(min), static_cast<float>(max), "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
|
||||
if (CHANGED)
|
||||
{
|
||||
value = val;
|
||||
}
|
||||
|
||||
return CHANGED;
|
||||
}
|
||||
|
||||
bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value)
|
||||
{
|
||||
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y" };
|
||||
return SHEditorWidgets::DragN<float, 2>(label, COMPONENT_LABELS, { &value.x, &value.y });
|
||||
}
|
||||
bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, float speed)
|
||||
{
|
||||
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z"};
|
||||
return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, speed, "%.3f");
|
||||
}
|
||||
|
||||
bool SHEditorUI::InputTextField(const std::string& label, std::string& value)
|
||||
{
|
||||
std::array<char, TEXT_FIELD_MAX_LENGTH> buffer = { '\0' };
|
||||
strcpy_s(buffer.data(), TEXT_FIELD_MAX_LENGTH, value.c_str());
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
const bool CHANGED = ImGui::InputText("#", &buffer[0], TEXT_FIELD_MAX_LENGTH);
|
||||
if (CHANGED)
|
||||
{
|
||||
value = std::string(buffer.data(), buffer.data() + TEXT_FIELD_MAX_LENGTH);
|
||||
}
|
||||
return CHANGED;
|
||||
}
|
||||
|
||||
bool SHEditorUI::InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames)
|
||||
{
|
||||
// Clamp input value
|
||||
const std::string& INITIAL_NAME = v >= static_cast<int>(enumNames.size()) ? "Unknown" : enumNames[v];
|
||||
bool b = false;
|
||||
|
||||
ImGui::Text(label.c_str());
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("#", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
|
||||
{
|
||||
for (int i = 0; i < enumNames.size(); ++i)
|
||||
{
|
||||
const bool IS_SELECTED = v == i;
|
||||
if (ImGui::Selectable(enumNames[i].c_str(), IS_SELECTED))
|
||||
{
|
||||
v = i;
|
||||
b = true;
|
||||
}
|
||||
if (IS_SELECTED)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,286 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHEditorUI.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\par email: t.yanchongclarence\@digipen.edu
|
||||
\date Sep 27, 2022
|
||||
\brief Defines a class that contains wrapper functions for ImGui.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
// Standard Library
|
||||
#include <functional> // std::function
|
||||
#include <string> // std::string
|
||||
// Project Includes
|
||||
#include "Math/Vector/SHVec2.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/// <summary>
|
||||
/// Static class that contains useful functions for Editor UI using ImGui.
|
||||
/// </summary>
|
||||
class SH_API SHEditorUI final
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constants */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Maximum length of a string supported by InputTextField()
|
||||
/// </summary>
|
||||
static constexpr size_t TEXT_FIELD_MAX_LENGTH = 256;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - ID Stack */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Marks the start of a stack of ImGui widgets with the specified id.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::PushID().
|
||||
/// </summary>
|
||||
/// <param name="id">String-based ID.</param>
|
||||
static void PushID(const std::string& id);
|
||||
/// <summary>
|
||||
/// Marks the start of a stack of ImGui widgets with the specified id.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::PushID().
|
||||
/// </summary>
|
||||
/// <param name="id">Integer-based ID.</param>
|
||||
static void PushID(int id);
|
||||
/// <summary>
|
||||
/// Marks the end of a stack of ImGui widgets from the last PushID() call.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::PopID().
|
||||
/// </summary>
|
||||
static void PopID();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Indent */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Indents the widgets rendered after this call.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::Indent().
|
||||
/// </summary>
|
||||
static void Indent();
|
||||
/// <summary>
|
||||
/// Unindents the widgets rendered after this call.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::Unindent().
|
||||
/// </summary>
|
||||
static void Unindent();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Organizers */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Creates a collapsing title header.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::CollapsingHeader().
|
||||
/// </summary>
|
||||
/// <param name="title">Label for the header.</param>
|
||||
/// <returns>True if the header is open, false otherwise.</returns>
|
||||
static bool CollapsingHeader(const std::string& title);
|
||||
static void SameLine();
|
||||
static void Separator();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Menu */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
static bool BeginMenu(const std::string& label);
|
||||
static bool BeginMenu(const std::string& label, const char* icon);
|
||||
static void EndMenu();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Pop Ups */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Marks the start of a definition of a mini pop up that can show options.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::BeginPopup().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <returns>Whether or not the pop up is open.</returns>
|
||||
static bool BeginPopup(const std::string& label);
|
||||
static bool BeginPopupContextItem(const std::string& label);
|
||||
/// <summary>
|
||||
/// Marks the end of a definition of a mini pop up that can show options.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::EndPopup().
|
||||
/// </summary>
|
||||
static void EndPopup();
|
||||
/// <summary>
|
||||
/// Opens the popup that was defined with the specified label.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::OpenPopup().
|
||||
/// </summary>
|
||||
static void OpenPopup(const std::string& label);
|
||||
/// <summary>
|
||||
/// Creates a menu item in the list of items for a mini popup.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::MenuItem().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <returns>Whether or not the menu item was selected.</returns>
|
||||
static bool MenuItem(const std::string& label);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Widgets */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Creates a visual text widget.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::Text().
|
||||
/// </summary>
|
||||
/// <param name="title">Text to display.</param>
|
||||
static void Text(const std::string& title);
|
||||
/// <summary>
|
||||
/// Creates a small inline button widget.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::SmallButton().
|
||||
/// </summary>
|
||||
/// <param name="title">Text to display.</param>
|
||||
/// <returns>True if button was pressed.</returns>
|
||||
static bool SmallButton(const std::string& title);
|
||||
/// <summary>
|
||||
/// Creates a inline button widget.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::Button().
|
||||
/// </summary>
|
||||
/// <param name="title">Text to display.</param>
|
||||
/// <returns>True if button was pressed.</returns>
|
||||
static bool Button(const std::string& title);
|
||||
static bool Selectable(const std::string& label);
|
||||
static bool Selectable(const std::string& label, const char* icon);
|
||||
/// <summary>
|
||||
/// Creates a checkbox widget for boolean input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::Checkbox().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputCheckbox(const std::string& label, bool& value);
|
||||
/// <summary>
|
||||
/// Creates a integer field widget for integer input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputInt().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputInt(const std::string& label, int& value);
|
||||
/// <summary>
|
||||
/// Creates a integer field widget for unsigned integer input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputInt() with an additional clamping of values.
|
||||
/// <br/>
|
||||
/// Note: As a result, the range of this function limits it to the maximum
|
||||
/// value of a 32-bit signed integer instead of a 32-bit unsigned integer.
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputUnsignedInt(const std::string& label, unsigned int& value);
|
||||
/// <summary>
|
||||
/// Creates a decimal field widget for single precision float input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputFloat().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputFloat(const std::string& label, float& value);
|
||||
/// <summary>
|
||||
/// Creates a decimal field widget for double precision float input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputDouble().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputDouble(const std::string& label, double& value);
|
||||
/// <summary>
|
||||
/// Creates a decimal field widget for double input with increments of higher
|
||||
/// steps meant for angle variables.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputDouble().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputAngle(const std::string& label, double& value);
|
||||
/// <summary>
|
||||
/// Creates a double slider field widget for double input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputSliderFloat().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="min">Minimum value of the slider.</param>
|
||||
/// <param name="max">Maximum value of the slider.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputSlider(const std::string& label, double min, double max, double& value);
|
||||
/// <summary>
|
||||
/// Creates a 2x double field widget for Vector2 input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputFloat2().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputVec2(const std::string& label, SHVec2& value);
|
||||
/// <summary>
|
||||
/// Creates a 3x double field widget for Vector3 input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputFloat3().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputVec3(const std::string& label, SHVec3& value, float speed = 0.1f);
|
||||
/// <summary>
|
||||
/// Creates a text field widget for string input.
|
||||
/// <br/>
|
||||
/// Wraps up ImGui::InputText().
|
||||
/// </summary>
|
||||
/// <param name="label">Label used to identify this widget.</param>
|
||||
/// <param name="value">Reference to the variable to store the result.</param>
|
||||
/// <returns>True if the value was changed.</returns>
|
||||
static bool InputTextField(const std::string& label, std::string& value);
|
||||
/// <summary>
|
||||
/// Creates a combo box for enumeration input.
|
||||
/// </summary>
|
||||
/// <typeparam name="Enum">The type of enum to input.</typeparam>
|
||||
/// <param name="label">The name of the input.</param>
|
||||
/// <param name="v">The reference to the value to modify.</param>
|
||||
/// <param name="maxVal">The maximum value of the enum.</param>
|
||||
/// <param name="toStrFn">
|
||||
/// Conversion function from the type of enum to C-style string.
|
||||
/// </param>
|
||||
/// <returns>Whether the value was modified.</returns>
|
||||
template<typename Enum>
|
||||
static bool InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char*(Enum)> toStrFn);
|
||||
/// <summary>
|
||||
/// Creates a combo box for enumeration input using a specified list of names.
|
||||
/// </summary>
|
||||
/// <param name="label">The name of the input.</param>
|
||||
/// <param name="v">The reference to the value to modify.</param>
|
||||
/// <param name="enumNames">Vector of names for each enumeration value.</param>
|
||||
/// <returns>Whether the value was modified.</returns>
|
||||
static bool InputEnumCombo(const std::string& label, int& v, const std::vector<std::string>& enumNames);
|
||||
|
||||
|
||||
private:
|
||||
// Prevent instantiation of this static class
|
||||
SHEditorUI() = delete;
|
||||
};
|
||||
}
|
||||
|
||||
#include "SHEditorUI.hpp"
|
|
@ -0,0 +1,51 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHEditorUI.hpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Sep 27, 2022
|
||||
\brief Contains the implementation of editor inspector template functions.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
// Primary Header
|
||||
#include "SHEditorUI.h"
|
||||
// External Dependencies
|
||||
#include <imgui.h>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* ImGui Wrapper Functions - Widgets */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
template<typename Enum>
|
||||
inline bool SHEditorUI::InputEnumCombo(const std::string& label, Enum& v, int maxVal, std::function<const char* (Enum)> toStrFn)
|
||||
{
|
||||
std::vector<Enum> values;
|
||||
for (int i = 0; i <= maxVal; ++i)
|
||||
{
|
||||
values.emplace_back(static_cast<Enum>(i));
|
||||
}
|
||||
bool b = false;
|
||||
if (ImGui::BeginCombo(label.c_str(), toStrFn(v), ImGuiComboFlags_None))
|
||||
{
|
||||
for (int i = 0; i <= maxVal; ++i)
|
||||
{
|
||||
const auto VALUE = values[i];
|
||||
const bool IS_SELECTED = v == VALUE;
|
||||
if (ImGui::Selectable(toStrFn(VALUE), IS_SELECTED))
|
||||
{
|
||||
v = VALUE;
|
||||
b = true;
|
||||
}
|
||||
if (IS_SELECTED)
|
||||
{
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
#include "Math/SHMath.h"
|
||||
#include "Command/SHCommandManager.h"
|
||||
#include "SHImGuiHelpers.hpp"
|
||||
#include "SH_API.h"
|
||||
|
||||
//#==============================================================#
|
||||
//|| Library Includes ||
|
||||
|
@ -23,165 +24,315 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
//#==============================================================#
|
||||
//|| Custom Widgets ||
|
||||
//#==============================================================#
|
||||
static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f)
|
||||
class SH_API SHEditorWidgets
|
||||
{
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
const ImGuiID id = window->GetID("##Splitter");
|
||||
ImRect bb;
|
||||
bb.Min = window->DC.CursorPos + (verticalSplit ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
|
||||
bb.Max = bb.Min + (verticalSplit ? ImVec2(thickness, splitterAxisSize) : ImVec2(splitterAxisSize, thickness));
|
||||
return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f);
|
||||
}
|
||||
public:
|
||||
//#==============================================================#
|
||||
//|| Constructor ||
|
||||
//#==============================================================#
|
||||
SHEditorWidgets() = delete;
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
|
||||
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
const ImGuiContext& g = *GImGui;
|
||||
bool valueChanged = false;
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushID(fieldLabel.c_str());
|
||||
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
||||
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
||||
ImGui::SetColumnWidth(-1, 80.0f);
|
||||
ImGui::Text(fieldLabel.c_str());
|
||||
ImGui::NextColumn();
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
//#==============================================================#
|
||||
//|| Custom Widgets ||
|
||||
//#==============================================================#
|
||||
static bool Splitter(bool verticalSplit, float thickness, float* size1, float* size2, float minSize1, float minSize2, float splitterAxisSize = -1.0f)
|
||||
{
|
||||
ImGui::PushID(static_cast<int>(i));
|
||||
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(80.0f);
|
||||
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags);
|
||||
|
||||
const ImVec2 min = ImGui::GetItemRectMin();
|
||||
const ImVec2 max = ImGui::GetItemRectMax();
|
||||
const float spacing = g.Style.FrameRounding;
|
||||
const float halfSpacing = spacing / 2;
|
||||
|
||||
window->DrawList->AddLine({ min.x + spacing, max.y - halfSpacing }, { max.x - spacing, max.y - halfSpacing },
|
||||
ImGuiColors::colors[i], 4);
|
||||
|
||||
ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
|
||||
ImGui::PopID();
|
||||
ImGui::PopItemWidth();
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
const ImGuiID id = window->GetID("##Splitter");
|
||||
ImRect bb;
|
||||
bb.Min = window->DC.CursorPos + (verticalSplit ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
|
||||
bb.Max = bb.Min + (verticalSplit ? ImVec2(thickness, splitterAxisSize) : ImVec2(splitterAxisSize, thickness));
|
||||
return ImGui::SplitterBehavior(bb, id, verticalSplit ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, minSize1, minSize2, 0.0f);
|
||||
}
|
||||
ImGui::EndColumns();
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
|
||||
return valueChanged;
|
||||
}
|
||||
template <typename T, std::size_t N>
|
||||
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
|
||||
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
const ImGuiContext& g = *GImGui;
|
||||
bool valueChanged = false;
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushID(fieldLabel.c_str());
|
||||
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
||||
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
||||
ImGui::SetColumnWidth(-1, 80.0f);
|
||||
ImGui::Text(fieldLabel.c_str());
|
||||
ImGui::NextColumn();
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
{
|
||||
ImGui::PushID(static_cast<int>(i));
|
||||
ImGui::TextUnformatted(componentLabels[i].c_str(), ImGui::FindRenderedTextEnd(componentLabels[i].c_str())); ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(80.0f);
|
||||
valueChanged |= ImGui::DragFloat("##v", values[i], speed, valueMin, valueMax, displayFormat, flags);
|
||||
|
||||
const ImVec2 min = ImGui::GetItemRectMin();
|
||||
const ImVec2 max = ImGui::GetItemRectMax();
|
||||
const float spacing = g.Style.FrameRounding;
|
||||
const float halfSpacing = spacing / 2;
|
||||
|
||||
window->DrawList->AddLine({ min.x + spacing, max.y - halfSpacing }, { max.x - spacing, max.y - halfSpacing },
|
||||
ImGuiColors::colors[i], 4);
|
||||
|
||||
ImGui::SameLine(0, g.Style.ItemInnerSpacing.x);
|
||||
ImGui::PopID();
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
ImGui::EndColumns();
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
|
||||
return valueChanged;
|
||||
}
|
||||
|
||||
static bool DragVec2(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
|
||||
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
SHVec2 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 2>(fieldLabel, componentLabels, {&values.x, &values.y}, speed, displayFormat, valueMin, valueMax, flags))
|
||||
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
changed = true;
|
||||
SHVec2 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 2>(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
static bool DragVec3(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
|
||||
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
||||
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
|
||||
else if(ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
||||
SHVec3 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static bool DragVec3(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
|
||||
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
SHVec3 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 3>(fieldLabel, componentLabels, {&values.x, &values.y, &values.z}, speed, displayFormat, valueMin, valueMax, flags))
|
||||
static bool DragVec4(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
|
||||
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
changed = true;
|
||||
SHVec4 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 4>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags))
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
//#==============================================================#
|
||||
//|| Widget Extensions ||
|
||||
//#==============================================================#
|
||||
|
||||
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
||||
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
|
||||
else if(ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
||||
bool value = get();
|
||||
if (ImGui::Checkbox(label.c_str(), &value))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static bool DragVec4(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
|
||||
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
||||
ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
SHVec4 values = get();
|
||||
bool changed = false;
|
||||
if (DragN<float, 4>(fieldLabel, componentLabels, {&values.x, &values.y, &values.z, &values.w}, speed, displayFormat, valueMin, valueMax, flags))
|
||||
template<typename T>
|
||||
static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
||||
else if(ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
|
||||
else if(ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
//#==============================================================#
|
||||
//|| Widget Extensions ||
|
||||
//#==============================================================#
|
||||
|
||||
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
|
||||
{
|
||||
bool value = get();
|
||||
if (ImGui::Checkbox(label.c_str(), &value))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
||||
T type = get();
|
||||
for (size_t i = 0; i < listTypes.size(); i++)
|
||||
{
|
||||
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
|
||||
{
|
||||
T type = get();
|
||||
for (size_t i = 0; i < listTypes.size(); i++)
|
||||
static bool InputText(const std::string& label, const std::function<std::string(void)> get,
|
||||
const std::function<void(std::string)> set, ImGuiInputTextFlags flag = 0,
|
||||
ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
|
||||
{
|
||||
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
|
||||
std::string text = get();
|
||||
if (ImGui::InputText(label.c_str(), &text, flag, callback, userData))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
|
||||
if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool DragScalar(const std::string& fieldLabel, ImGuiDataType data_type, std::function<T(void)> get, std::function<void(T const&)> set,
|
||||
float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
T value = get();
|
||||
std::cout << value <<" \n";
|
||||
//bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
|
||||
|
||||
if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags))
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool DragFloat(const std::string& fieldLabel, std::function<float(void)> get, std::function<void(float const&)> set,
|
||||
float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
float value = get();
|
||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
||||
if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool DragInt(const std::string& fieldLabel, std::function<int(void)> get, std::function<void(int const&)> set,
|
||||
float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
int value = get();
|
||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
||||
if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
||||
{
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
|
||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
template <typename T>
|
||||
static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set,
|
||||
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
T value = get();
|
||||
if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags))
|
||||
{
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function<float(void)> get, std::function<void(float const&)> set,
|
||||
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
float value = get();
|
||||
if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
|
||||
{
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function<int(void)> get, std::function<void(int const&)> set,
|
||||
const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
||||
{
|
||||
int value = get();
|
||||
if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
|
||||
{
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ComboBox(const std::string& fieldLabel, std::vector<const char*> list, std::function<int(void)> get, std::function<void(int const&)> set)
|
||||
{
|
||||
bool edited = false;
|
||||
int selected = get();
|
||||
ImGui::PushID(fieldLabel.c_str());
|
||||
ImGui::Text(fieldLabel.c_str()); ImGui::SameLine();
|
||||
|
||||
if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast<int>(list.size())))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
|
||||
}
|
||||
ImGui::PopID();
|
||||
return edited;
|
||||
}
|
||||
};
|
||||
}//namespace SHADE
|
||||
|
|
|
@ -8,3 +8,5 @@ typedef uint32_t SHEventHandle;
|
|||
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0};
|
||||
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 };
|
||||
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 };
|
||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 };
|
||||
|
|
|
@ -9,12 +9,31 @@
|
|||
consent of DigiPen Institute of Technology is prohibited.
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
//TODO Legacy code. Delete soon
|
||||
|
||||
#include <chrono>
|
||||
#include <cassert>
|
||||
#include <SHpch.h>
|
||||
#include "SHFramerateController.h"
|
||||
#include "../Tools/SHLogger.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
double SHFrameRateController::rawDeltaTime = 0.0;
|
||||
std::chrono::steady_clock::time_point SHFrameRateController::prevFrameTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
void SHFrameRateController::UpdateFRC() noexcept
|
||||
{
|
||||
std::chrono::duration<double> deltaTime;
|
||||
deltaTime = std::chrono::high_resolution_clock::now() - prevFrameTime;
|
||||
prevFrameTime = std::chrono::high_resolution_clock::now();
|
||||
rawDeltaTime = deltaTime.count();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Legacy code. Delete soon
|
||||
#if 0
|
||||
namespace SHADE
|
||||
{
|
||||
//Init statics
|
||||
|
@ -132,3 +151,4 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -13,6 +13,38 @@
|
|||
#define SH_FRAMERATECONTROLLER_H
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include "Tools/SHLogger.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SH_API SHFrameRateController
|
||||
{
|
||||
private:
|
||||
//Varying delta time. The actual time it took for every frame
|
||||
static double rawDeltaTime;
|
||||
static std::chrono::steady_clock::time_point prevFrameTime;
|
||||
|
||||
|
||||
public:
|
||||
//Gets the raw delta time
|
||||
static inline double GetRawDeltaTime() noexcept
|
||||
{
|
||||
return rawDeltaTime;
|
||||
}
|
||||
|
||||
//Updates the raw delta time accordingly
|
||||
static void UpdateFRC() noexcept;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//TODO Legacy code. Delete soon
|
||||
#if 0
|
||||
#include "../Scene/SHScene.h"
|
||||
|
||||
namespace SHADE
|
||||
|
@ -56,7 +88,19 @@ namespace SHADE
|
|||
//halt execution of the current scene and prepare
|
||||
//execution of the next
|
||||
static inline void SetNextScene(SHScene* const next) { nextScene = next; }
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -39,8 +39,10 @@ namespace SHADE
|
|||
std::vector<vk::DescriptorPoolSize> Limits =
|
||||
{
|
||||
{ vk::DescriptorType::eCombinedImageSampler, 100 },
|
||||
{ vk::DescriptorType::eUniformBuffer, 100 },
|
||||
{ vk::DescriptorType::eUniformBufferDynamic, 100 }
|
||||
{ vk::DescriptorType::eUniformBuffer, 100 },
|
||||
{ vk::DescriptorType::eUniformBufferDynamic, 100 },
|
||||
{ vk::DescriptorType::eStorageImage, 100},
|
||||
{ vk::DescriptorType::eStorageBufferDynamic, 100 }
|
||||
};
|
||||
/// <summary>
|
||||
/// Maximum number of descriptor sets allowed
|
||||
|
|
|
@ -155,7 +155,7 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::pair<Handle<SHVkImageView>, Handle<SHVkSampler>>> const& imageViewsAndSamplers) noexcept
|
||||
void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> const& imageViewsAndSamplers) noexcept
|
||||
{
|
||||
// Find the target writeDescSet
|
||||
BindingAndSetHash writeHash = binding;
|
||||
|
@ -170,9 +170,10 @@ namespace SHADE
|
|||
for (uint32_t i = 0; i < imageViewsAndSamplers.size(); ++i)
|
||||
{
|
||||
// write sampler and image view
|
||||
auto& ivs = imageViewsAndSamplers[i];
|
||||
writeInfo.descImageInfos[i].imageView = ivs.first->GetImageView();
|
||||
writeInfo.descImageInfos[i].sampler = ivs.second->GetVkSampler();
|
||||
auto& [view, sampler, layout] = imageViewsAndSamplers[i];
|
||||
writeInfo.descImageInfos[i].imageView = view->GetImageView();
|
||||
writeInfo.descImageInfos[i].sampler = sampler->GetVkSampler();
|
||||
writeInfo.descImageInfos[i].imageLayout = layout;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
|
||||
// Project Includes
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
#include "Resource/Handle.h"
|
||||
|
@ -63,7 +65,7 @@ namespace SHADE
|
|||
void UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept;
|
||||
void UpdateDescriptorSetBuffer(uint32_t set, uint32_t binding) noexcept;
|
||||
|
||||
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::pair<Handle<SHVkImageView>, Handle<SHVkSampler>>> const& imageViewsAndSamplers) noexcept;
|
||||
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> const& imageViewsAndSamplers) noexcept;
|
||||
void ModifyWriteDescBuffer (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
|
||||
#include "Graphics/Images/SHVkImageView.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "Graphics/Images/SHVkSampler.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -85,6 +86,17 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
uint32_t SHVkLogicalDevice::ComputeAlignedBufferSize(uint32_t originalSize, size_t alignmentSize) const noexcept
|
||||
{
|
||||
uint32_t alignedSize = originalSize;
|
||||
//uint32_t minBuffer
|
||||
if (alignmentSize > 0)
|
||||
{
|
||||
alignedSize = (alignedSize + alignmentSize - 1) & ~(alignmentSize - 1);
|
||||
}
|
||||
return alignedSize;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -176,6 +188,7 @@ namespace SHADE
|
|||
// point and lines fill mode
|
||||
features.fillModeNonSolid = true;
|
||||
features.samplerAnisotropy = VK_TRUE;
|
||||
features.multiDrawIndirect = true;
|
||||
|
||||
// for wide lines
|
||||
features.wideLines = true;
|
||||
|
@ -288,13 +301,12 @@ namespace SHADE
|
|||
|
||||
uint32_t SHVkLogicalDevice::PadUBOSize(uint32_t originalSize) const noexcept
|
||||
{
|
||||
uint32_t alignedSize = originalSize;
|
||||
//uint32_t minBuffer
|
||||
if (uboBufferMemoryAlignment > 0)
|
||||
{
|
||||
alignedSize = (alignedSize + uboBufferMemoryAlignment - 1) & ~(uboBufferMemoryAlignment - 1);
|
||||
}
|
||||
return alignedSize;
|
||||
return ComputeAlignedBufferSize(originalSize, uboBufferMemoryAlignment);
|
||||
}
|
||||
|
||||
uint32_t SHVkLogicalDevice::PadSSBOSize(uint32_t originalSize) const noexcept
|
||||
{
|
||||
return ComputeAlignedBufferSize(originalSize, ssboBufferMemoryAlignment);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -499,6 +511,11 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
Handle<SHVkSampler> SHVkLogicalDevice::CreateSampler(const SHVkSamplerParams& params) noexcept
|
||||
{
|
||||
return SHVkInstance::GetResourceManager().Create <SHVkSampler>(GetHandle(), params);
|
||||
}
|
||||
|
||||
Handle<SHVkRenderpass> SHVkLogicalDevice::CreateRenderpass(std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept
|
||||
{
|
||||
return SHVkInstance::GetResourceManager().Create <SHVkRenderpass>(GetHandle(), vkDescriptions, subpasses);
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
||||
#include "Graphics/Images/SHVkImage.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -41,6 +40,8 @@ namespace SHADE
|
|||
class SHShaderBlockInterface;
|
||||
class SHVkDescriptorSetGroup;
|
||||
class SHSubpass;
|
||||
class SHVkSampler;
|
||||
struct SHVkSamplerParams;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
@ -102,6 +103,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
void InitializeVMA (void) noexcept;
|
||||
void InitializeQueues (std::initializer_list<SHQueueParams> queueCreateParams) noexcept;
|
||||
uint32_t ComputeAlignedBufferSize(uint32_t originalSize, size_t typeSize) const noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -121,7 +123,8 @@ namespace SHADE
|
|||
// Miscellaneous functions
|
||||
void WaitIdle (void) noexcept;
|
||||
uint32_t FindMemoryType (uint32_t typeFilter, vk::MemoryPropertyFlags properties);
|
||||
uint32_t PadUBOSize (uint32_t originalSize) const noexcept;
|
||||
uint32_t PadUBOSize(uint32_t originalSize) const noexcept;
|
||||
uint32_t PadSSBOSize(uint32_t originalSize) const noexcept;
|
||||
|
||||
// creation functions
|
||||
Handle<SHVkSurface> CreateSurface (HWND const& windowHandle) const noexcept;
|
||||
|
@ -178,6 +181,7 @@ namespace SHADE
|
|||
Handle<SHVkRenderpass> const& renderpassHdl,
|
||||
Handle<SHSubpass> subpass
|
||||
) noexcept;
|
||||
Handle<SHVkSampler> CreateSampler (const SHVkSamplerParams& params) noexcept;
|
||||
|
||||
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;
|
||||
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::span<vk::SubpassDescription> const spDescs, std::span<vk::SubpassDependency> const spDeps) noexcept;
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHVkImage::PrepStagingBuffer(void* data, uint32_t srcSize) noexcept
|
||||
void SHVkImage::PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept
|
||||
{
|
||||
// For creation of buffer
|
||||
vk::BufferCreateInfo bufferInfo{};
|
||||
|
@ -70,7 +70,7 @@ namespace SHADE
|
|||
vmaMapMemory(*vmaAllocator, stagingAlloc, &stagingBufferMappedPtr);
|
||||
|
||||
if (stagingBufferMappedPtr)
|
||||
std::memcpy(static_cast<uint8_t*>(stagingBufferMappedPtr), static_cast<uint8_t*>(data), srcSize);
|
||||
std::memcpy(static_cast<uint8_t*>(stagingBufferMappedPtr), static_cast<const uint8_t*>(data), srcSize);
|
||||
|
||||
const VkDeviceSize offsets = 0;
|
||||
const VkDeviceSize sizes = srcSize;
|
||||
|
@ -82,7 +82,7 @@ namespace SHADE
|
|||
SHVkImage::SHVkImage(
|
||||
VmaAllocator const* allocator,
|
||||
SHImageCreateParams const& imageDetails,
|
||||
unsigned char* data,
|
||||
const unsigned char* data,
|
||||
uint32_t dataSize,
|
||||
std::span<uint32_t> inMipOffsets,
|
||||
VmaMemoryUsage memUsage,
|
||||
|
|
|
@ -107,7 +107,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void PrepStagingBuffer(void* data, uint32_t srcSize) noexcept;
|
||||
void PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept;
|
||||
|
||||
|
||||
public:
|
||||
|
@ -119,7 +119,7 @@ namespace SHADE
|
|||
SHVkImage(
|
||||
VmaAllocator const* allocator,
|
||||
SHImageCreateParams const& imageDetails,
|
||||
unsigned char* data,
|
||||
const unsigned char* data,
|
||||
uint32_t dataSize,
|
||||
std::span<uint32_t> inMipOffsets,
|
||||
VmaMemoryUsage memUsage,
|
||||
|
|
|
@ -1,12 +1,62 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHVkSampler.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Sep 26, 2022
|
||||
\brief Contains definitions for all of the functions of the SHVkSampler class.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHVkSampler.h"
|
||||
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
vk::Sampler SHVkSampler::GetVkSampler(void) const noexcept
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHVkSampler::SHVkSampler(Handle<SHVkLogicalDevice> logicalDevice, const SHVkSamplerParams& params) noexcept
|
||||
: device { logicalDevice }
|
||||
{
|
||||
return vkSampler;
|
||||
const vk::SamplerCreateInfo SAMPLER_CREATE_INFO
|
||||
{
|
||||
.magFilter = params.magFilter,
|
||||
.minFilter = params.minFilter,
|
||||
.mipmapMode = params.mipmapMode,
|
||||
.addressModeU = params.addressMode,
|
||||
.addressModeV = params.addressMode,
|
||||
.addressModeW = params.addressMode,
|
||||
.minLod = params.minLod,
|
||||
.maxLod = params.maxLod
|
||||
};
|
||||
|
||||
// Create the sampler
|
||||
vkSampler = device->GetVkLogicalDevice().createSampler(SAMPLER_CREATE_INFO);
|
||||
}
|
||||
|
||||
SHVkSampler::SHVkSampler(SHVkSampler&& rhs) noexcept
|
||||
: vkSampler { rhs.vkSampler }
|
||||
{
|
||||
rhs.vkSampler = nullptr;
|
||||
}
|
||||
|
||||
SHVkSampler::~SHVkSampler() noexcept
|
||||
{
|
||||
if (vkSampler)
|
||||
device->GetVkLogicalDevice().destroySampler();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Overloaded Operators */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHADE::SHVkSampler& SHVkSampler::operator=(SHVkSampler&& rhs) noexcept
|
||||
{
|
||||
vkSampler = rhs.vkSampler;
|
||||
rhs.vkSampler = nullptr;
|
||||
return *this;
|
||||
}
|
||||
}
|
|
@ -1,28 +1,80 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHVkSampler.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Sep 26, 2022
|
||||
\brief Contains definitions of the SHVkSampler class.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
// STL Includes
|
||||
#include <vector>
|
||||
// Project Includes
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
#include "Resource/Handle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHVkLogicalDevice;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*************************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Holds parameters for constructing the SHVkSampler.
|
||||
*/
|
||||
/*************************************************************************************/
|
||||
struct SHVkSamplerParams
|
||||
{
|
||||
vk::Filter minFilter;
|
||||
vk::Filter maxFilter;
|
||||
//vk::Filter maxFilter;
|
||||
vk::Filter minFilter = vk::Filter::eLinear;
|
||||
vk::Filter magFilter = vk::Filter::eLinear;
|
||||
vk::SamplerAddressMode addressMode = vk::SamplerAddressMode::eClampToEdge;
|
||||
vk::SamplerMipmapMode mipmapMode = vk::SamplerMipmapMode::eLinear;
|
||||
float minLod = 0;
|
||||
float maxLod = 0;
|
||||
};
|
||||
|
||||
/*************************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Wrapper for a VkSampler.
|
||||
*/
|
||||
/*************************************************************************************/
|
||||
class SHVkSampler
|
||||
{
|
||||
private:
|
||||
//! The vulkan sampler handler
|
||||
vk::Sampler vkSampler;
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHVkSampler(Handle<SHVkLogicalDevice> logicalDevice, const SHVkSamplerParams& params = {}) noexcept;
|
||||
SHVkSampler(SHVkSampler&& rhs) noexcept;
|
||||
~SHVkSampler() noexcept;
|
||||
|
||||
public:
|
||||
SHVkSampler () noexcept;
|
||||
SHVkSampler (SHVkSampler&& rhs) noexcept;
|
||||
SHVkSampler&& operator=(SHVkSampler&& rhs) noexcept;
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Overloaded Operators */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHVkSampler& operator=(SHVkSampler&& rhs) noexcept;
|
||||
|
||||
vk::Sampler GetVkSampler (void) const noexcept;
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
vk::Sampler GetVkSampler(void) const noexcept { return vkSampler; }
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
vk::Sampler vkSampler; //! The Vulkan sampler handler
|
||||
Handle<SHVkLogicalDevice> device; //! Stored device for deallocating the object
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,11 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/Pipeline/SHVkPipeline.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -120,7 +123,7 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex)
|
||||
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||
{
|
||||
|
@ -154,21 +157,17 @@ namespace SHADE
|
|||
if (!matBufferDirty[frameIndex])
|
||||
return;
|
||||
|
||||
// Build CPI Buffer
|
||||
// Build CPU Buffer
|
||||
char* propsCurrPtr = matPropsData.get();
|
||||
for (auto& subBatch : subBatches)
|
||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
||||
{
|
||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||
propsCurrPtr += singleMatPropSize;
|
||||
propsCurrPtr += singleMatPropAlignedSize;
|
||||
}
|
||||
|
||||
// Transfer to GPU
|
||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||
(
|
||||
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||
vk::BufferUsageFlagBits::eStorageBuffer
|
||||
);
|
||||
rebuildMaterialBuffers(frameIndex, descPool);
|
||||
|
||||
// This frame is updated
|
||||
matBufferDirty[frameIndex] = false;
|
||||
|
@ -207,7 +206,7 @@ namespace SHADE
|
|||
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
|
||||
}
|
||||
|
||||
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, uint32_t frameIndex)
|
||||
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
||||
{
|
||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||
{
|
||||
|
@ -215,6 +214,9 @@ namespace SHADE
|
|||
return;
|
||||
}
|
||||
|
||||
// Save logical device
|
||||
device = _device;
|
||||
|
||||
// No need to build as there are no changes
|
||||
if (!isDirty[frameIndex])
|
||||
return;
|
||||
|
@ -247,7 +249,8 @@ namespace SHADE
|
|||
if (!EMPTY_MAT_PROPS)
|
||||
{
|
||||
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
||||
matPropTotalBytes = drawData.size() * singleMatPropSize;
|
||||
singleMatPropAlignedSize = device->PadSSBOSize(singleMatPropSize);
|
||||
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
||||
if (matPropsDataSize < matPropTotalBytes)
|
||||
{
|
||||
matPropsData.reset(new char[matPropTotalBytes]);
|
||||
|
@ -267,7 +270,7 @@ namespace SHADE
|
|||
.instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()),
|
||||
.firstIndex = subBatch.Mesh->FirstIndex,
|
||||
.vertexOffset = subBatch.Mesh->FirstVertex,
|
||||
.firstInstance = nextInstanceIndex
|
||||
.firstInstance = nextInstanceIndex++
|
||||
});
|
||||
|
||||
// Fill in buffers (CPU)
|
||||
|
@ -289,7 +292,7 @@ namespace SHADE
|
|||
if (!EMPTY_MAT_PROPS)
|
||||
{
|
||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||
propsCurrPtr += singleMatPropSize;
|
||||
propsCurrPtr += singleMatPropAlignedSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,30 +307,21 @@ namespace SHADE
|
|||
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
|
||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||
(
|
||||
_device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
|
||||
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
|
||||
BuffUsage::eIndirectBuffer
|
||||
);
|
||||
// - Transform Buffer
|
||||
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
|
||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||
(
|
||||
_device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
||||
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
||||
BuffUsage::eVertexBuffer
|
||||
);
|
||||
// - Material Properties Buffer
|
||||
if (matPropsData)
|
||||
{
|
||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||
(
|
||||
_device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||
BuffUsage::eStorageBuffer
|
||||
);
|
||||
}
|
||||
rebuildMaterialBuffers(frameIndex, descPool);
|
||||
|
||||
// Mark this frame as no longer dirty
|
||||
isDirty[frameIndex] = false;
|
||||
|
||||
// Save logical device
|
||||
this->device = _device;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -341,8 +335,20 @@ namespace SHADE
|
|||
return;
|
||||
}
|
||||
|
||||
// Bind all required objects before drawing
|
||||
static std::array<uint32_t, 1> dynamicOffset { 0 };
|
||||
cmdBuffer->BindPipeline(pipeline);
|
||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
||||
if (matPropsDescSet[frameIndex])
|
||||
{
|
||||
cmdBuffer->BindDescriptorSet
|
||||
(
|
||||
matPropsDescSet[frameIndex],
|
||||
vk::PipelineBindPoint::eGraphics,
|
||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||
dynamicOffset
|
||||
);
|
||||
}
|
||||
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
||||
}
|
||||
|
||||
|
@ -355,4 +361,39 @@ namespace SHADE
|
|||
dirt = true;
|
||||
isCPUBuffersDirty = true;
|
||||
}
|
||||
|
||||
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
if (matPropsData)
|
||||
{
|
||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||
(
|
||||
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||
vk::BufferUsageFlagBits::eStorageBuffer
|
||||
);
|
||||
|
||||
if (!matPropsDescSet[frameIndex])
|
||||
{
|
||||
matPropsDescSet[frameIndex] = descPool->Allocate
|
||||
(
|
||||
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
|
||||
{ 0 }
|
||||
);
|
||||
}
|
||||
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
||||
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
|
||||
(
|
||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
||||
bufferList,
|
||||
0, matPropsDataSize
|
||||
);
|
||||
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
||||
(
|
||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ namespace SHADE
|
|||
class SHRenderable;
|
||||
class SHVkLogicalDevice;
|
||||
class SHMaterialInstance;
|
||||
class SHVkDescriptorSetGroup;
|
||||
class SHVkDescriptorPool;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -74,9 +76,9 @@ namespace SHADE
|
|||
void Add(const SHRenderable* renderable);
|
||||
void Remove(const SHRenderable* renderable);
|
||||
void Clear();
|
||||
void UpdateMaterialBuffer(uint32_t frameIndex);
|
||||
void UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -84,34 +86,44 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; };
|
||||
|
||||
private:
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Type Definition */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
using TripleBool = std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||
using TripleBuffer = std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||
using TripleDescSet = std::array<Handle<SHVkDescriptorSetGroup>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
// Resources
|
||||
Handle<SHVkLogicalDevice> device;
|
||||
Handle<SHVkLogicalDevice> device;
|
||||
// Batch Properties
|
||||
Handle<SHVkPipeline> pipeline;
|
||||
Handle<SHVkPipeline> pipeline;
|
||||
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
|
||||
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> matBufferDirty;
|
||||
TripleBool matBufferDirty;
|
||||
// Batch Tree
|
||||
std::vector<SHSubBatch> subBatches;
|
||||
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> isDirty;
|
||||
std::vector<SHSubBatch> subBatches;
|
||||
TripleBool isDirty;
|
||||
// CPU Buffers
|
||||
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
||||
std::vector<SHMatrix> transformData;
|
||||
std::unique_ptr<char> matPropsData;
|
||||
Byte matPropsDataSize = 0;
|
||||
Byte singleMatPropSize = 0;
|
||||
bool isCPUBuffersDirty = true;
|
||||
std::vector<vk::DrawIndexedIndirectCommand> drawData;
|
||||
std::vector<SHMatrix> transformData;
|
||||
std::unique_ptr<char> matPropsData;
|
||||
Byte matPropsDataSize = 0;
|
||||
Byte singleMatPropAlignedSize = 0;
|
||||
Byte singleMatPropSize = 0;
|
||||
bool isCPUBuffersDirty = true;
|
||||
// GPU Buffers
|
||||
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer;
|
||||
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> transformDataBuffer;
|
||||
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> matPropsBuffer;
|
||||
TripleBuffer drawDataBuffer;
|
||||
TripleBuffer transformDataBuffer;
|
||||
TripleBuffer matPropsBuffer;
|
||||
TripleDescSet matPropsDescSet;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void setAllDirtyFlags();
|
||||
void rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -91,12 +91,12 @@ namespace SHADE
|
|||
(*superBatch)->Remove(renderable);
|
||||
}
|
||||
|
||||
void SHBatcher::FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex)
|
||||
void SHBatcher::FinaliseBatches(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
||||
{
|
||||
// Build SuperBatches
|
||||
for (auto& batch : superBatches)
|
||||
{
|
||||
batch->Build(device, frameIndex);
|
||||
batch->Build(device, descPool, frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,11 +109,11 @@ namespace SHADE
|
|||
superBatches.clear();
|
||||
}
|
||||
|
||||
void SHBatcher::UpdateBuffers(uint32_t frameIndex)
|
||||
void SHBatcher::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
for (auto& batch : superBatches)
|
||||
{
|
||||
batch->UpdateBuffers(frameIndex);
|
||||
batch->UpdateBuffers(frameIndex, descPool);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace SHADE
|
|||
class SHSuperBatch;
|
||||
class SHVkLogicalDevice;
|
||||
class SHVkCommandBuffer;
|
||||
class SHVkDescriptorPool;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -51,9 +52,9 @@ namespace SHADE
|
|||
void PrepareBatches();
|
||||
void AddToBatch(SHRenderable const* renderable);
|
||||
void RemoveFromBatch(SHRenderable const* renderable);
|
||||
void FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
|
||||
void FinaliseBatches(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex);
|
||||
void ClearBatches();
|
||||
void UpdateBuffers(uint32_t frameIndex);
|
||||
void UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
void RegisterSuperBatch(Handle<SHSuperBatch> superBatch);
|
||||
void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch);
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "SHBatch.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -78,21 +79,21 @@ namespace SHADE
|
|||
batches.clear();
|
||||
}
|
||||
|
||||
void SHSuperBatch::UpdateBuffers(uint32_t frameIndex)
|
||||
void SHSuperBatch::UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
for (auto& batch : batches)
|
||||
{
|
||||
batch.UpdateMaterialBuffer(frameIndex);
|
||||
batch.UpdateMaterialBuffer(frameIndex, descPool);
|
||||
batch.UpdateTransformBuffer(frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept
|
||||
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
||||
{
|
||||
// Build all batches
|
||||
for (auto& batch : batches)
|
||||
{
|
||||
batch.Build(device, frameIndex);
|
||||
batch.Build(device, descPool, frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,8 +55,8 @@ namespace SHADE
|
|||
void Add(const SHRenderable* renderable) noexcept;
|
||||
void Remove(const SHRenderable* renderable) noexcept;
|
||||
void Clear() noexcept;
|
||||
void UpdateBuffers(uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept;
|
||||
void UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -7,7 +7,22 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHGraphicsGlobalData::globalDescSetLayouts;
|
||||
Handle<SHVkDescriptorSetGroup> SHGraphicsGlobalData::globalDescSets;
|
||||
SHVertexInputState SHGraphicsGlobalData::defaultVertexInputState;
|
||||
Handle<SHVkPipelineLayout> SHGraphicsGlobalData::dummyPipelineLayout;
|
||||
|
||||
void SHGraphicsGlobalData::InitHighFrequencyGlobalData(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHGraphicsGlobalData::InitDescSetLayouts(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||
{
|
||||
SHVkDescriptorSetLayout::Binding genericDataBinding
|
||||
|
@ -87,18 +102,18 @@ namespace SHADE
|
|||
InitDefaultVertexInputState();
|
||||
}
|
||||
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& SHGraphicsGlobalData::GetDescSetLayouts(void) const noexcept
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& SHGraphicsGlobalData::GetDescSetLayouts(void) noexcept
|
||||
{
|
||||
return globalDescSetLayouts;
|
||||
}
|
||||
|
||||
|
||||
SHVertexInputState const& SHGraphicsGlobalData::GetDefaultViState(void) const noexcept
|
||||
SHVertexInputState const& SHGraphicsGlobalData::GetDefaultViState(void) noexcept
|
||||
{
|
||||
return defaultVertexInputState;
|
||||
}
|
||||
|
||||
Handle<SHVkPipelineLayout> SHGraphicsGlobalData::GetDummyPipelineLayout(void) const noexcept
|
||||
Handle<SHVkPipelineLayout> SHGraphicsGlobalData::GetDummyPipelineLayout(void) noexcept
|
||||
{
|
||||
return dummyPipelineLayout;
|
||||
}
|
||||
|
|
|
@ -15,31 +15,38 @@ namespace SHADE
|
|||
{
|
||||
private:
|
||||
//! Global descriptor set layouts. Used to allocate descriptor sets
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> globalDescSetLayouts;
|
||||
static std::vector<Handle<SHVkDescriptorSetLayout>> globalDescSetLayouts;
|
||||
|
||||
//! Global Descriptor sets
|
||||
Handle<SHVkDescriptorSetGroup> globalDescSets;
|
||||
static Handle<SHVkDescriptorSetGroup> globalDescSets;
|
||||
|
||||
//! Default vertex input state (used by everything).
|
||||
SHVertexInputState defaultVertexInputState;
|
||||
static SHVertexInputState defaultVertexInputState;
|
||||
|
||||
//! Since we want to bind global data but can't do so without a pipeline layout,
|
||||
//! we create a dummy pipeline layout to use it for binding.
|
||||
Handle<SHVkPipelineLayout> dummyPipelineLayout;
|
||||
static Handle<SHVkPipelineLayout> dummyPipelineLayout;
|
||||
|
||||
static void InitHighFrequencyGlobalData (void) noexcept;
|
||||
static void InitDescSetLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
static void InitDefaultVertexInputState (void) noexcept;
|
||||
|
||||
void InitDescSetLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
void InitDefaultVertexInputState(void) noexcept;
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHGraphicsGlobalData() = delete;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void Init (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
static void Init (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescSetLayouts (void) const noexcept;
|
||||
SHVertexInputState const& GetDefaultViState (void) const noexcept;
|
||||
Handle<SHVkPipelineLayout> GetDummyPipelineLayout (void) const noexcept;
|
||||
static std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescSetLayouts (void) noexcept;
|
||||
static SHVertexInputState const& GetDefaultViState (void) noexcept;
|
||||
static Handle<SHVkPipelineLayout> GetDummyPipelineLayout (void) noexcept;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,21 +23,39 @@ namespace SHADE
|
|||
{
|
||||
SHVec3 view = target - pos; view = SHVec3::Normalise(view);
|
||||
SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right);
|
||||
const SHVec3 UP = SHVec3::Cross(right, view);
|
||||
const SHVec3 UP = SHVec3::Cross(view, right);
|
||||
|
||||
//viewMatrix = SHMatrix::Identity;
|
||||
//viewMatrix(0, 0) = UP[0];
|
||||
//viewMatrix(1, 0) = UP[1];
|
||||
//viewMatrix(2, 0) = UP[2];
|
||||
//viewMatrix(0, 1) = right[0];
|
||||
//viewMatrix(1, 1) = right[1];
|
||||
//viewMatrix(2, 1) = right[2];
|
||||
//viewMatrix(0, 2) = view[0];
|
||||
//viewMatrix(1, 2) = view[1];
|
||||
//viewMatrix(2, 2) = view[2];
|
||||
//viewMatrix(3, 0) = -UP.Dot(pos);
|
||||
//viewMatrix(3, 1) = -right.Dot(pos);
|
||||
//viewMatrix(3, 2) = -view.Dot(pos);
|
||||
|
||||
viewMatrix = SHMatrix::Identity;
|
||||
viewMatrix(0, 0) = UP[0];
|
||||
viewMatrix(1, 0) = UP[1];
|
||||
viewMatrix(2, 0) = UP[2];
|
||||
viewMatrix(0, 1) = right[0];
|
||||
viewMatrix(1, 1) = right[1];
|
||||
viewMatrix(2, 1) = right[2];
|
||||
viewMatrix(0, 2) = view[0];
|
||||
viewMatrix(1, 2) = view[1];
|
||||
viewMatrix(2, 2) = view[2];
|
||||
viewMatrix(3, 0) = -UP.Dot(pos);
|
||||
viewMatrix(3, 1) = -right.Dot(pos);
|
||||
viewMatrix(3, 2) = -view.Dot(pos);
|
||||
viewMatrix(0, 0) = right[0];
|
||||
viewMatrix(0, 1) = right[1];
|
||||
viewMatrix(0, 2) = right[2];
|
||||
|
||||
viewMatrix(1, 0) = UP[0];
|
||||
viewMatrix(1, 1) = UP[1];
|
||||
viewMatrix(1, 2) = UP[2];
|
||||
|
||||
viewMatrix(2, 0) = view[0];
|
||||
viewMatrix(2, 1) = view[1];
|
||||
viewMatrix(2, 2) = view[2];
|
||||
|
||||
viewMatrix(0, 3) = -right.Dot(pos);
|
||||
viewMatrix(1, 3) = -UP.Dot(pos);
|
||||
viewMatrix(2, 3) = -view.Dot(pos);
|
||||
|
||||
|
||||
isDirty = true;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "SHGraphicsConstants.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
|
||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||
#include "Graphics/Images/SHVkSampler.h"
|
||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -91,8 +93,10 @@ namespace SHADE
|
|||
descPool = device->CreateDescriptorPools();
|
||||
|
||||
// Create generic command buffer
|
||||
transferCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::TRANSFER, SH_CMD_POOL_RESET::POOL_BASED, true);
|
||||
transferCmdBuffer = transferCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
||||
//transferCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
|
||||
graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
|
||||
transferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
||||
graphicsTexCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
||||
|
||||
|
||||
|
||||
|
@ -106,8 +110,7 @@ namespace SHADE
|
|||
- Global data
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
globalData = resourceManager.Create<SHGraphicsGlobalData>();
|
||||
globalData->Init(device);
|
||||
SHGraphicsGlobalData::Init(device);
|
||||
|
||||
// Set Up Cameras
|
||||
screenCamera = resourceManager.Create<SHCamera>();
|
||||
|
@ -115,7 +118,7 @@ namespace SHADE
|
|||
screenCamera->SetOrthographic(static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.01f, 100.0f);
|
||||
worldCamera = resourceManager.Create<SHCamera>();
|
||||
//worldCamera->SetLookAt(SHVec3(1.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f));
|
||||
worldCamera->SetLookAt(SHVec3(0.0f, 5.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f));
|
||||
worldCamera->SetLookAt(SHVec3(0.0f, 0.0f, 0.0f), SHVec3(0.0f, 0.0f, -2.0f), SHVec3(0.0f, 1.0f, 0.0f));
|
||||
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
|
||||
|
||||
// Create Default Viewport
|
||||
|
@ -131,18 +134,20 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Initialize world render graph
|
||||
worldRenderGraph->Init(device, swapchain, globalData);
|
||||
worldRenderGraph->Init(device, swapchain);
|
||||
worldRenderGraph->AddResource("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
//worldRenderGraph->AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
|
||||
//worldRenderGraph->AddResource("Normals", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
|
||||
//worldRenderGraph->AddResource("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
|
||||
worldRenderGraph->AddResource("Scene", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eB8G8R8A8Unorm);
|
||||
//worldRenderGraph->AddResource("Scene", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eB8G8R8A8Unorm);
|
||||
worldRenderGraph->AddResource("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second);
|
||||
auto node = worldRenderGraph->AddNode("G-Buffer", { /*"Composite", "Position", */"Present" }, {}); // no predecessors
|
||||
auto node = worldRenderGraph->AddNode("G-Buffer", { /*"Composite", "Position", */"Depth Buffer", "Present" }, {}); // no predecessors
|
||||
|
||||
//First subpass to write to G-Buffer
|
||||
auto gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
|
||||
//gBufferWriteSubpass->AddColorOutput("Scene");
|
||||
gBufferWriteSubpass->AddColorOutput("Present");
|
||||
gBufferWriteSubpass->AddDepthOutput ("Depth Buffer", SH_ATT_DESC_TYPE::DEPTH_STENCIL);
|
||||
//writeSubpass->AddColorOutput("Normals");
|
||||
|
||||
// //Second subpass to read from G-Buffer
|
||||
|
@ -171,7 +176,7 @@ namespace SHADE
|
|||
debugWorldRenderer->SetCamera(worldCamera);*/
|
||||
|
||||
// Add world renderer to default viewport
|
||||
worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, globalData->GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
|
||||
worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
|
||||
worldRenderer->SetCamera(worldCamera);
|
||||
|
||||
|
||||
|
@ -184,8 +189,8 @@ namespace SHADE
|
|||
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
|
||||
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
|
||||
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
|
||||
//triVS->Reflect();
|
||||
//triFS->Reflect();
|
||||
cubeVS->Reflect();
|
||||
cubeFS->Reflect();
|
||||
|
||||
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
|
||||
}
|
||||
|
@ -224,6 +229,9 @@ namespace SHADE
|
|||
|
||||
renderContext.ResetFence();
|
||||
|
||||
// Bind textures
|
||||
|
||||
|
||||
// For every viewport
|
||||
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
|
||||
{
|
||||
|
@ -241,7 +249,7 @@ namespace SHADE
|
|||
// Begin recording the command buffer
|
||||
currentCmdBuffer->BeginRecording();
|
||||
|
||||
currentCmdBuffer->ForceSetPipelineLayout(globalData->GetDummyPipelineLayout());
|
||||
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout());
|
||||
|
||||
// Bind all the buffers required for meshes
|
||||
for (auto& [buffer, bindingPoint] : MESH_DATA)
|
||||
|
@ -252,11 +260,26 @@ namespace SHADE
|
|||
currentCmdBuffer->BindIndexBuffer(buffer, 0);
|
||||
}
|
||||
|
||||
|
||||
// Bind textures
|
||||
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
|
||||
if (textureDescSet)
|
||||
{
|
||||
std::array<uint32_t, 1> texDynamicOffset {0};
|
||||
currentCmdBuffer->BindDescriptorSet
|
||||
(
|
||||
textureDescSet,
|
||||
vk::PipelineBindPoint::eGraphics,
|
||||
0,
|
||||
texDynamicOffset
|
||||
);
|
||||
}
|
||||
|
||||
// bind camera data
|
||||
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
||||
|
||||
// Draw first
|
||||
renderers[renIndex]->Draw(frameIndex);
|
||||
renderers[renIndex]->Draw(frameIndex, descPool);
|
||||
|
||||
// End the command buffer recording
|
||||
currentCmdBuffer->EndRecording();
|
||||
|
@ -309,7 +332,7 @@ namespace SHADE
|
|||
for (auto vp : viewports)
|
||||
for (auto renderer : vp->GetRenderers())
|
||||
{
|
||||
renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame());
|
||||
renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame(), descPool);
|
||||
}
|
||||
|
||||
// Resize
|
||||
|
@ -455,7 +478,35 @@ namespace SHADE
|
|||
transferCmdBuffer->BeginRecording();
|
||||
meshLibrary.BuildBuffers(device, transferCmdBuffer);
|
||||
transferCmdBuffer->EndRecording();
|
||||
transferQueue->SubmitCommandBuffer({ transferCmdBuffer });
|
||||
graphicsQueue->SubmitCommandBuffer({ transferCmdBuffer });
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Texture Registration Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHTexture> SHGraphicsSystem::Add(const SHTextureAsset& texAsset)
|
||||
{
|
||||
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams { .maxLod = static_cast<float>(texAsset.mipOffsets.size()) });
|
||||
return texLibrary.Add(texAsset, sampler);
|
||||
}
|
||||
|
||||
SHADE::Handle<SHADE::SHTexture> SHGraphicsSystem::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets)
|
||||
{
|
||||
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams{ .maxLod = static_cast<float>(mipOffsets.size()) });
|
||||
return texLibrary.Add(pixelCount, pixelData, width, height, format, mipOffsets, sampler);
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::Remove(Handle<SHTexture> tex)
|
||||
{
|
||||
texLibrary.Remove(tex);
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::BuildTextures()
|
||||
{
|
||||
texLibrary.BuildTextures
|
||||
(
|
||||
device, graphicsTexCmdBuffer, graphicsQueue, descPool
|
||||
);
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
|
||||
|
@ -493,9 +544,13 @@ namespace SHADE
|
|||
oldSuperBatch->Remove(&renderable);
|
||||
}
|
||||
|
||||
// Add to new SuperBatch
|
||||
Handle<SHSuperBatch> newSuperBatch = renderable.GetMaterial()->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||
newSuperBatch->Add(&renderable);
|
||||
// Add to new SuperBatch if there is a material
|
||||
Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
|
||||
if (newMatInstance)
|
||||
{
|
||||
Handle<SHSuperBatch> newSuperBatch = newMatInstance->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||
newSuperBatch->Add(&renderable);
|
||||
}
|
||||
|
||||
// Unset change flag
|
||||
renderable.ResetChangedFlag();
|
||||
|
|
|
@ -29,6 +29,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h"
|
||||
#include "SHMeshLibrary.h"
|
||||
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
|
||||
#include "../Textures/SHTextureLibrary.h"
|
||||
#include "../Textures/SHVkSamplerCache.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -188,6 +190,62 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void BuildMeshBuffers();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Texture Registration Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/*******************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Adds a texture to the Texture Library. But this does not mean that the
|
||||
textures have been added yet. A call to "BuildTextures()" is required to
|
||||
transfer all textures into the GPU.
|
||||
|
||||
\param pixelCount
|
||||
Number of pixels in this Mesh.
|
||||
\param positions
|
||||
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
|
||||
positions.
|
||||
\param format
|
||||
Format of the texture loaded in.
|
||||
|
||||
\return
|
||||
Handle to the created Texture. This is not valid to be used until a call to
|
||||
BuildImages().
|
||||
|
||||
*/
|
||||
/*******************************************************************************/
|
||||
Handle<SHTexture> Add(const SHTextureAsset& texAsset);
|
||||
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets);
|
||||
/*******************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Removes a mesh from the Texture Library. But this does not mean that the
|
||||
textures have been removed yet. A call to "BuildTextures()" is required to
|
||||
finalise all changes.
|
||||
|
||||
\param mesh
|
||||
Handle to the Texture to remove.
|
||||
|
||||
*/
|
||||
/*******************************************************************************/
|
||||
void Remove(Handle<SHTexture> tex);
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Finalises all changes to the Texture Library into the GPU buffers.
|
||||
|
||||
\param cmdBuffer
|
||||
Command buffer used to set up transfers of data in the GPU memory. This
|
||||
call must be preceded by calls to cmdBuffer's BeginRecording() and ended
|
||||
with EndRecording(). Do recall to also submit the cmdBuffer to a transfer
|
||||
queue.
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void BuildTextures();
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Setters */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -220,19 +278,20 @@ namespace SHADE
|
|||
Handle<SHVkQueue> graphicsQueue;
|
||||
Handle<SHVkQueue> transferQueue;
|
||||
Handle<SHVkDescriptorPool> descPool;
|
||||
Handle<SHVkCommandPool> graphicsCmdPool;
|
||||
Handle<SHVkCommandPool> transferCmdPool;
|
||||
Handle<SHVkCommandBuffer> transferCmdBuffer;
|
||||
Handle<SHVkCommandBuffer> graphicsTexCmdBuffer;
|
||||
SHRenderContext renderContext;
|
||||
std::array<Handle<SHVkSemaphore>, 2> graphSemaphores;
|
||||
// Not Owned Resources
|
||||
SHWindow* window = nullptr;
|
||||
|
||||
// global data (descriptor sets as well)
|
||||
Handle<SHGraphicsGlobalData> globalData;
|
||||
|
||||
// Middle End Resources
|
||||
ResourceManager resourceManager;
|
||||
SHMeshLibrary meshLibrary;
|
||||
SHTextureLibrary texLibrary;
|
||||
SHSamplerCache samplerCache;
|
||||
SHMaterialInstanceCache materialInstanceCache;
|
||||
// Viewports
|
||||
Handle<SHViewport> defaultViewport; // Whole screen
|
||||
|
|
|
@ -40,8 +40,6 @@ namespace SHADE
|
|||
|
||||
void SHMaterialInstance::ExportProperties(void* dest)
|
||||
{
|
||||
assert(dataStore != nullptr);
|
||||
|
||||
if (!baseMaterial)
|
||||
throw std::runtime_error("[SHMaterialInstance] Attempted to set export a Material Instance with no base Material!");
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
// Project Includes
|
||||
#include "Resource/Handle.h"
|
||||
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -34,7 +35,7 @@ namespace SHADE
|
|||
a SHRenderable.
|
||||
*/
|
||||
/***********************************************************************************/
|
||||
class SHMaterialInstance
|
||||
class SH_API SHMaterialInstance
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Get offset and modify the memory directly
|
||||
T* dataPtr = dataStore.get() + od.StoredDataOffset;
|
||||
T* dataPtr = reinterpret_cast<T*>(dataStore.get() + od.StoredDataOffset);
|
||||
*dataPtr = value;
|
||||
|
||||
// Save the override data information
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace SHADE
|
|||
if (!material)
|
||||
{
|
||||
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||
material = gfxSystem->AddOrGetBaseMaterialInstance(sharedMaterial->GetBaseMaterial());
|
||||
material = gfxSystem->AddMaterialInstanceCopy(sharedMaterial);
|
||||
}
|
||||
|
||||
return material;
|
||||
|
|
|
@ -60,9 +60,9 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Drawing Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHRenderer::Draw(uint32_t frameIndex) noexcept
|
||||
void SHRenderer::Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||
{
|
||||
renderGraph->Execute(frameIndex, commandBuffers[frameIndex]);
|
||||
renderGraph->Execute(frameIndex, commandBuffers[frameIndex], descPool);
|
||||
}
|
||||
|
||||
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
/* Drawing Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void Draw(uint32_t frameIndex) noexcept;
|
||||
void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void UpdateDataAndBind (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
void UpdateCameraDataToBuffer (void) noexcept;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace SHADE
|
|||
SHPipelineLayoutParams params
|
||||
{
|
||||
.shaderModules = {vsFsPair.first, vsFsPair.second},
|
||||
.globalDescSetLayouts = globalData->GetDescSetLayouts()
|
||||
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
|
||||
};
|
||||
|
||||
// Create the pipeline layout
|
||||
|
@ -19,7 +19,7 @@ namespace SHADE
|
|||
|
||||
// Create the pipeline and configure the default vertex input state
|
||||
auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass);
|
||||
newPipeline->GetPipelineState().SetVertexInputState(globalData->GetDefaultViState());
|
||||
newPipeline->GetPipelineState().SetVertexInputState(SHGraphicsGlobalData::GetDefaultViState());
|
||||
|
||||
// Actually construct the pipeline
|
||||
newPipeline->ConstructPipeline();
|
||||
|
@ -30,10 +30,9 @@ namespace SHADE
|
|||
return newPipeline;
|
||||
}
|
||||
|
||||
void SHPipelineLibrary::Init(Handle<SHVkLogicalDevice> device, Handle<SHGraphicsGlobalData> inGlobalData) noexcept
|
||||
void SHPipelineLibrary::Init(Handle<SHVkLogicalDevice> device) noexcept
|
||||
{
|
||||
logicalDevice = device;
|
||||
globalData = inGlobalData;
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> SHPipelineLibrary::GetDrawPipline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
|
||||
|
|
|
@ -25,13 +25,8 @@ namespace SHADE
|
|||
//! a map of pipelines that are hashed using a pair of shader module handles
|
||||
std::unordered_map<std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>>, Handle<SHVkPipeline>> pipelines;
|
||||
|
||||
// Global data
|
||||
Handle<SHGraphicsGlobalData> globalData;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
void Init (Handle<SHVkLogicalDevice> device, Handle<SHGraphicsGlobalData> inGlobalData) noexcept;
|
||||
void Init (Handle<SHVkLogicalDevice> device) noexcept;
|
||||
|
||||
// Draw pipeline functions. used only when creating pipelines for drawing using a vertex and fragment shader
|
||||
Handle<SHVkPipeline> CreateDrawPipeline (
|
||||
|
|
|
@ -20,18 +20,36 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/Commands/SHVkCommandBuffer.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
#include "Tools/SHLogger.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
#include "Graphics/Images/SHVkImage.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
|
||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHTexture> SHTextureLibrary::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, SHTexture::TextureFormat format, uint32_t mipLevels)
|
||||
Handle<SHTexture> SHTextureLibrary::Add(const SHTextureAsset& texAsset, Handle<SHVkSampler> sampler)
|
||||
{
|
||||
return Add
|
||||
(
|
||||
texAsset.numBytes,
|
||||
texAsset.pixelData,
|
||||
texAsset.width, texAsset.height,
|
||||
texAsset.format,
|
||||
texAsset.mipOffsets,
|
||||
sampler
|
||||
);
|
||||
}
|
||||
|
||||
Handle<SHTexture> SHTextureLibrary::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets, Handle<SHVkSampler> sampler)
|
||||
{
|
||||
isDirty = true;
|
||||
|
||||
auto handle = resourceManager.Create<SHTexture>();
|
||||
addJobs.emplace_back(AddJob { pixelCount, pixelData, format, mipLevels });
|
||||
addJobs.emplace_back(AddJob { pixelCount, pixelData, format, sampler, mipOffsets, width, height, handle });
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
@ -44,22 +62,48 @@ namespace SHADE
|
|||
isDirty = true;
|
||||
}
|
||||
|
||||
void SHTextureLibrary::BuildImages(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> descLayout)
|
||||
void SHTextureLibrary::BuildTextures(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
// Don't do anything if there are no updates
|
||||
if (!isDirty)
|
||||
return;
|
||||
|
||||
/* Remove Textures */
|
||||
std::vector<vk::ImageMemoryBarrier> pipelineBarriers(addJobs.size());
|
||||
// TODO
|
||||
|
||||
/* Add Textures */
|
||||
// Transition
|
||||
// Load Textures - Transitions
|
||||
std::vector<vk::ImageMemoryBarrier> pipelineBarriers(addJobs.size());
|
||||
for (int i = 0; auto& job : addJobs)
|
||||
{
|
||||
job.Image = resourceManager.Create<SHVkImage>();
|
||||
job.Image = resourceManager.Create<SHVkImage>
|
||||
(
|
||||
&device->GetVMAAllocator(),
|
||||
SHImageCreateParams
|
||||
{
|
||||
.imageType = vk::ImageType::e2D,
|
||||
.width = job.Width,
|
||||
.height = job.Height,
|
||||
.depth = 1,
|
||||
.levels = static_cast<uint8_t>(job.MipOffsets.size()),
|
||||
.arrayLayers = 1,
|
||||
.imageFormat = job.TextureFormat,
|
||||
.usageFlags = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst,
|
||||
.createFlags = {}
|
||||
},
|
||||
job.PixelData,
|
||||
job.PixelCount,
|
||||
job.MipOffsets,
|
||||
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
|
||||
VmaAllocationCreateFlagBits {}
|
||||
);
|
||||
job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, pipelineBarriers[i]);
|
||||
++i;
|
||||
}
|
||||
vk::PipelineStageFlagBits srcStage = vk::PipelineStageFlagBits::eTopOfPipe;
|
||||
vk::PipelineStageFlagBits dstStage = vk::PipelineStageFlagBits::eTopOfPipe;
|
||||
preparePipelineBarriers(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, srcStage, dstStage, pipelineBarriers);
|
||||
cmdBuffer->BeginRecording();
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers);
|
||||
|
||||
// Copy
|
||||
|
@ -73,13 +117,16 @@ namespace SHADE
|
|||
{
|
||||
// Transition
|
||||
job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, pipelineBarriers[i]);
|
||||
++i;
|
||||
}
|
||||
preparePipelineBarriers(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, srcStage, dstStage, pipelineBarriers);
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers);
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, {}, {}, pipelineBarriers);
|
||||
|
||||
// Execute Commands
|
||||
cmdBuffer->EndRecording();
|
||||
graphicsQueue->SubmitCommandBuffer({ cmdBuffer });
|
||||
device->WaitIdle();
|
||||
graphicsQueue->GetVkQueue().waitIdle();
|
||||
|
||||
// Create Image View
|
||||
for (auto& job : addJobs)
|
||||
|
@ -90,16 +137,45 @@ namespace SHADE
|
|||
.format = job.TextureFormat,
|
||||
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = job.MipLevels,
|
||||
.mipLevelCount = static_cast<uint32_t>(job.MipOffsets.size()),
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 0
|
||||
.layerCount = 1
|
||||
};
|
||||
job.Handle->ImageView = job.Image->CreateImageView(device, job.Image, DETAILS);
|
||||
job.TextureHandle->ImageView = job.Image->CreateImageView(device, job.Image, DETAILS);
|
||||
}
|
||||
|
||||
// Build Descriptor
|
||||
Handle<SHVkDescriptorSetGroup> descSetGroup = descPool->Allocate({ descLayout }, { 1 });
|
||||
// Add Textures
|
||||
for (auto& job : addJobs)
|
||||
{
|
||||
texOrder.emplace_back(job.TextureHandle);
|
||||
combinedImageSamplers.emplace_back(std::make_tuple(job.TextureHandle->ImageView, job.Sampler, vk::ImageLayout::eShaderReadOnlyOptimal));
|
||||
job.TextureHandle->TextureArrayIndex = texOrder.size() - 1;
|
||||
}
|
||||
addJobs.clear();
|
||||
|
||||
/* Build Descriptor Set with all the Textures only if there are textures */
|
||||
if (!texOrder.empty())
|
||||
{
|
||||
if (!texDescriptors)
|
||||
{
|
||||
texDescriptors = descPool->Allocate
|
||||
(
|
||||
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS] },
|
||||
{ static_cast<uint32_t>(texOrder.size()) }
|
||||
);
|
||||
}
|
||||
texDescriptors->ModifyWriteDescImage
|
||||
(
|
||||
SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,
|
||||
SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA,
|
||||
combinedImageSamplers
|
||||
);
|
||||
texDescriptors->UpdateDescriptorSetImages
|
||||
(
|
||||
SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,
|
||||
SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA
|
||||
);
|
||||
}
|
||||
|
||||
isDirty = false;
|
||||
}
|
||||
|
@ -139,4 +215,65 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
vk::Format SHTextureLibrary::ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
|
||||
return vk::Format::eBc1RgbaUnormBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
|
||||
return vk::Format::eBc1RgbaSrgbBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::BC5_SNorm:
|
||||
return isLinear ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_SNorm:
|
||||
return vk::Format::eR8G8B8A8Snorm;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm:
|
||||
case tinyddsloader::DDSFile::DXGIFormat::B8G8R8X8_UNorm_SRGB:
|
||||
return isLinear ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8Srgb;
|
||||
default:
|
||||
throw std::runtime_error("Unsupported DDS format.");
|
||||
}
|
||||
|
||||
//switch (format)
|
||||
//{
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm:
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::R8G8B8A8_UNorm_SRGB:
|
||||
// return (isLinear) ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR8G8B8A8Srgb;
|
||||
//
|
||||
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm:
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::B8G8R8A8_UNorm_SRGB:
|
||||
// return (isLinear) ? vk::Format::eB8G8R8A8Unorm : vk::Format::eB8G8R8A8Srgb;
|
||||
//
|
||||
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm:
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC1_UNorm_SRGB:
|
||||
// return (isLinear) ? vk::Format::eBc1RgbaUnormBlock : vk::Format::eBc1RgbaSrgbBlock;
|
||||
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm:
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC2_UNorm_SRGB:
|
||||
// return (isLinear) ? vk::Format::eBc2UnormBlock : vk::Format::eBc2SrgbBlock;
|
||||
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm:
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC3_UNorm_SRGB:
|
||||
// return (isLinear) ? vk::Format::eBc3UnormBlock : vk::Format::eBc3SrgbBlock;
|
||||
|
||||
//case tinyddsloader::DDSFile::DXGIFormat::BC5_UNorm:
|
||||
// return (isLinear) ? vk::Format::eBc5UnormBlock : vk::Format::eBc5SnormBlock;
|
||||
//
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
|
||||
// STL Includes
|
||||
#include <vector>
|
||||
// External Dependencies
|
||||
#include "tinyddsloader.h"
|
||||
// Project Includes
|
||||
#include "Resource/Handle.h"
|
||||
#include "Resource/ResourceLibrary.h"
|
||||
|
@ -33,6 +35,9 @@ namespace SHADE
|
|||
class SHVkQueue;
|
||||
class SHVkDescriptorPool;
|
||||
class SHVkDescriptorSetLayout;
|
||||
class SHVkDescriptorSetGroup;
|
||||
class SHVkSampler;
|
||||
class SHTextureAsset;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -43,7 +48,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
using PixelChannel = float;
|
||||
using PixelChannel = unsigned char;
|
||||
using TextureFormat = vk::Format; // TODO: Change
|
||||
using Index = uint32_t;
|
||||
|
||||
|
@ -71,7 +76,7 @@ namespace SHADE
|
|||
|
||||
\brief
|
||||
Adds a texture to the Texture Library. But this does not mean that the
|
||||
textures have been added yet. A call to "BuildImages()" is required to
|
||||
textures have been added yet. A call to "BuildTextures()" is required to
|
||||
transfer all textures into the GPU.
|
||||
|
||||
\param pixelCount
|
||||
|
@ -88,13 +93,15 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/*******************************************************************************/
|
||||
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, SHTexture::TextureFormat format, uint32_t mipLevels);
|
||||
|
||||
Handle<SHTexture> Add(const SHTextureAsset& texAsset, Handle<SHVkSampler> sampler);
|
||||
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets, Handle<SHVkSampler> sampler);
|
||||
/*******************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Removes a mesh from the Texture Library. But this does not mean that the
|
||||
textures have been removed yet. A call to "BuildImages()" is required to
|
||||
textures have been removed yet. A call to "BuildTextures()" is required to
|
||||
finalise all changes.
|
||||
|
||||
\param mesh
|
||||
|
@ -118,12 +125,12 @@ namespace SHADE
|
|||
queue.
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void BuildImages(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> descLayout);
|
||||
void BuildTextures(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHVkBuffer> GetTextureBuffer() const noexcept { return texStorageBuffer; }
|
||||
Handle<SHVkDescriptorSetGroup> GetTextureDescriptorSetGroup() const noexcept { return texDescriptors; }
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -134,9 +141,12 @@ namespace SHADE
|
|||
uint32_t PixelCount = 0;
|
||||
const SHTexture::PixelChannel* PixelData = nullptr;
|
||||
SHTexture::TextureFormat TextureFormat = {};
|
||||
uint32_t MipLevels = 0;
|
||||
Handle<SHVkSampler> Sampler;
|
||||
std::vector<uint32_t> MipOffsets;
|
||||
uint32_t Width;
|
||||
uint32_t Height;
|
||||
Handle<SHTexture> TextureHandle;
|
||||
Handle<SHVkImage> Image;
|
||||
Handle<SHTexture> Handle;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -149,9 +159,9 @@ namespace SHADE
|
|||
ResourceManager resourceManager;
|
||||
std::vector<Handle<SHTexture>> texOrder;
|
||||
// CPU Storage
|
||||
std::vector<SHTexture::PixelChannel> texStorage;
|
||||
std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> combinedImageSamplers;
|
||||
// GPU Storage
|
||||
Handle<SHVkBuffer> texStorageBuffer{};
|
||||
Handle<SHVkDescriptorSetGroup> texDescriptors;
|
||||
// Flags
|
||||
bool isDirty = true;
|
||||
|
||||
|
@ -159,5 +169,6 @@ namespace SHADE
|
|||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void preparePipelineBarriers(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::PipelineStageFlagBits& srcStage, vk::PipelineStageFlagBits& dstStage, std::vector<vk::ImageMemoryBarrier>& barriers);
|
||||
vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHVkSamplerCache.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 16, 2022
|
||||
\brief Contains the implementation for the SHVkSamplerCache class.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHVkSamplerCache.h"
|
||||
|
||||
// Standard Library
|
||||
#include <functional>
|
||||
// Project Header
|
||||
#include "Graphics/Images/SHVkSampler.h"
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Utility Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void SHSamplerCache::Clear()
|
||||
{
|
||||
samplersMap.clear();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHVkSampler> SHSamplerCache::GetSampler(Handle<SHVkLogicalDevice> device, const SHVkSamplerParams& params)
|
||||
{
|
||||
// Get the hash to check if it was cached
|
||||
const RawSamplerHash HASH = calcHash
|
||||
(
|
||||
params.minFilter,
|
||||
params.magFilter,
|
||||
params.addressMode,
|
||||
params.mipmapMode,
|
||||
params.minLod,
|
||||
params.maxLod
|
||||
);
|
||||
|
||||
// Check if it was cached
|
||||
auto sampler = samplersMap.find(HASH);
|
||||
if (sampler == samplersMap.end())
|
||||
{
|
||||
const auto BUILD_RESULT = samplersMap.emplace(HASH, device->CreateSampler(params));
|
||||
sampler = BUILD_RESULT.first;
|
||||
}
|
||||
|
||||
return sampler->second;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHSamplerCache::RawSamplerHash SHSamplerCache::calcHash(vk::Filter minFilter, vk::Filter magFilter, vk::SamplerAddressMode addressMode, vk::SamplerMipmapMode mipmapMode, float minLod, float maxLod)
|
||||
{
|
||||
static auto charHasher = std::hash<uint8_t>{};
|
||||
static auto floatHasher = std::hash<float>{};
|
||||
|
||||
const RawSamplerHash H1 = charHasher(static_cast<uint8_t>(minFilter));
|
||||
const RawSamplerHash H2 = charHasher(static_cast<uint8_t>(magFilter));
|
||||
const RawSamplerHash H3 = charHasher(static_cast<uint8_t>(addressMode));
|
||||
const RawSamplerHash H4 = charHasher(static_cast<uint8_t>(mipmapMode));
|
||||
const RawSamplerHash H5 = floatHasher(minLod);
|
||||
const RawSamplerHash H6 = floatHasher(maxLod);
|
||||
|
||||
return H1 ^ (H2 << 1) ^ (H3 << 2) ^ (H4 << 3) ^ (H5 << 4) ^ (H6 << 5);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHSamplerCache.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Mar 16, 2022
|
||||
\brief Contains the interface for the SHSamplerCache class.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
// Standard Libraries
|
||||
#include <unordered_map>
|
||||
// External Dependencies
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
// Project Includes
|
||||
#include "Resource/Handle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHVkLogicalDevice;
|
||||
class SHVkSampler;
|
||||
struct SHVkSamplerParams;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*************************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Class that is responsible for caching and providing Samplers to the user for
|
||||
sampling textures.
|
||||
*/
|
||||
/*************************************************************************************/
|
||||
class SHSamplerCache
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Utility Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Clears the cache, destroying all created samplers.
|
||||
/// </summary>
|
||||
void Clear();
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Retrieves a Vulkan Sampler of the specified type. If this was retrieved
|
||||
/// before, a cached copy of the Vulkan Sampler will be provided.
|
||||
/// </summary>
|
||||
/// <param name="device">Logical device to create the sampler with if needed.</param>
|
||||
/// <param name="params">Describes the parameters for the sampler.</param>
|
||||
/// <returns>Handle to the SHVkSampler object specified.</returns>
|
||||
Handle<SHVkSampler> GetSampler(Handle<SHVkLogicalDevice> device, const SHVkSamplerParams& params);
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
using RawSamplerHash = size_t;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
// Resources
|
||||
std::unordered_map<RawSamplerHash, Handle<SHVkSampler>> samplersMap;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
static RawSamplerHash calcHash(vk::Filter minFilter, vk::Filter magFilter, vk::SamplerAddressMode addressMode, vk::SamplerMipmapMode mipmapMode, float minLod, float maxLod);
|
||||
};
|
||||
}
|
|
@ -216,10 +216,13 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
void SHVkPipelineLayout::PrepareVkDescriptorSetLayouts(void) noexcept
|
||||
{
|
||||
descriptorSetLayoutsPipeline.reserve(descriptorSetLayoutsAllocate.size() + descriptorSetLayoutsGlobal.size());
|
||||
|
||||
// Settle allocate layouts first
|
||||
vkDescriptorSetLayoutsAllocate.reserve(descriptorSetLayoutsAllocate.size());
|
||||
for (auto const& layout : descriptorSetLayoutsAllocate)
|
||||
{
|
||||
descriptorSetLayoutsPipeline.emplace_back(layout);
|
||||
vkDescriptorSetLayoutsAllocate.emplace_back(layout->GetVkHandle());
|
||||
}
|
||||
|
||||
|
@ -228,7 +231,10 @@ namespace SHADE
|
|||
|
||||
// First we insert the global layouts
|
||||
for (auto const& layout : descriptorSetLayoutsGlobal)
|
||||
{
|
||||
descriptorSetLayoutsPipeline.emplace_back(layout);
|
||||
vkDescriptorSetLayoutsPipeline.emplace_back(layout->GetVkHandle());
|
||||
}
|
||||
|
||||
// Then we append layouts for allocation at the back of the vector
|
||||
std::copy(vkDescriptorSetLayoutsAllocate.begin(), vkDescriptorSetLayoutsAllocate.end(), std::back_inserter(vkDescriptorSetLayoutsPipeline));
|
||||
|
@ -435,6 +441,16 @@ namespace SHADE
|
|||
return {};
|
||||
}
|
||||
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsPipeline(void) const noexcept
|
||||
{
|
||||
return descriptorSetLayoutsPipeline;
|
||||
}
|
||||
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHVkPipelineLayout::GetDescriptorSetLayoutsAllocate(void) const noexcept
|
||||
{
|
||||
return descriptorSetLayoutsAllocate;
|
||||
}
|
||||
|
||||
SHVkPipelineLayout& SHVkPipelineLayout::operator=(SHVkPipelineLayout&& rhs) noexcept
|
||||
{
|
||||
if (&rhs == this)
|
||||
|
|
|
@ -42,6 +42,9 @@ namespace SHADE
|
|||
//! We want to store this also because we need to allocate later
|
||||
std::vector<vk::DescriptorSetLayout> vkDescriptorSetLayoutsAllocate;
|
||||
|
||||
//! Store for descriptor set group creation
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> descriptorSetLayoutsPipeline;
|
||||
|
||||
//! Store for pipeline layout recreation
|
||||
std::vector<vk::DescriptorSetLayout> vkDescriptorSetLayoutsPipeline;
|
||||
|
||||
|
@ -71,10 +74,12 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
std::vector<Handle<SHVkShaderModule>> const& GetShaderModules (void) const noexcept;
|
||||
vk::PipelineLayout GetVkPipelineLayout (void) const noexcept;
|
||||
SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept;
|
||||
Handle<SHShaderBlockInterface> GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept;
|
||||
std::vector<Handle<SHVkShaderModule>> const& GetShaderModules (void) const noexcept;
|
||||
vk::PipelineLayout GetVkPipelineLayout (void) const noexcept;
|
||||
SHPushConstantInterface const& GetPushConstantInterface (void) const noexcept;
|
||||
Handle<SHShaderBlockInterface> GetShaderBlockInterface (uint32_t set, uint32_t binding, vk::ShaderStageFlagBits shaderStage) const noexcept;
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> GetDescriptorSetLayoutsPipeline(void) const noexcept;
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> GetDescriptorSetLayoutsAllocate(void) const noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
// Used for attachment description creation for renderpass node
|
||||
enum class SH_ATT_DESC_TYPE
|
||||
{
|
||||
COLOR,
|
||||
COLOR_PRESENT,
|
||||
DEPTH,
|
||||
STENCIL,
|
||||
DEPTH_STENCIL,
|
||||
};
|
||||
}
|
|
@ -11,655 +11,7 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Non-default ctor for the resource. Using the type of the resource, we
|
||||
decide whether or not we create a resource or link with a swapchain
|
||||
resource (image).
|
||||
|
||||
\param logicalDevice
|
||||
Logical device required to create an image resource if the type is NOT
|
||||
SH_ATT_DESC_TYPE::COLOR_PRESENT.
|
||||
|
||||
\param swapchain
|
||||
Swapchain required to get swapchain image if the type IS
|
||||
SH_ATT_DESC_TYPE::COLOR_PRESENT.
|
||||
|
||||
\param type
|
||||
Type of the image resource.
|
||||
|
||||
\param format
|
||||
Format of the image resource.
|
||||
|
||||
\param w
|
||||
Width of the image resource.
|
||||
|
||||
\param h
|
||||
Height of the image resource.
|
||||
|
||||
\param levels
|
||||
Number of mipmap levels of the image resource.
|
||||
|
||||
\param createFlags
|
||||
Create flags used when an image resource needs to be created.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept
|
||||
: resourceType{ type }
|
||||
, resourceFormat{ format }
|
||||
, images{}
|
||||
, imageViews{}
|
||||
, width{ w }
|
||||
, height{ h }
|
||||
, mipLevels{ levels }
|
||||
, resourceName{ name }
|
||||
{
|
||||
// If the resource type is an arbitrary image and not swapchain image
|
||||
if (type != SH_ATT_DESC_TYPE::COLOR_PRESENT)
|
||||
{
|
||||
vk::ImageAspectFlags imageAspectFlags;
|
||||
vk::ImageUsageFlags usage = {};
|
||||
|
||||
// Check the resource type and set image usage flags and image aspect flags accordingly
|
||||
switch (resourceType)
|
||||
{
|
||||
case SH_ATT_DESC_TYPE::COLOR:
|
||||
usage |= vk::ImageUsageFlagBits::eColorAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::DEPTH:
|
||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::STENCIL:
|
||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::DEPTH_STENCIL:
|
||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
|
||||
break;
|
||||
}
|
||||
|
||||
// The resource is not a swapchain image, just use the first slot of the vector
|
||||
images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
|
||||
|
||||
// prepare image view details
|
||||
SHImageViewDetails viewDetails
|
||||
{
|
||||
.viewType = vk::ImageViewType::e2D,
|
||||
.format = images[0]->GetImageFormat(),
|
||||
.imageAspectFlags = imageAspectFlags,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = mipLevels,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
};
|
||||
|
||||
// just 1 image view created
|
||||
imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
|
||||
}
|
||||
else // if swapchain image resource
|
||||
{
|
||||
// Prepare image view details
|
||||
SHImageViewDetails viewDetails
|
||||
{
|
||||
.viewType = vk::ImageViewType::e2D,
|
||||
.format = swapchain->GetSurfaceFormatKHR().format,
|
||||
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
};
|
||||
|
||||
// We want an image handle for every swapchain image
|
||||
images.resize(swapchain->GetNumImages());
|
||||
imageViews.resize(swapchain->GetNumImages());
|
||||
|
||||
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
||||
{
|
||||
images[i] = swapchain->GetSwapchainImage(i);
|
||||
imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Move ctor for resource.
|
||||
|
||||
\param rhs
|
||||
The other resource.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource::SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept
|
||||
: resourceName{ std::move(rhs.resourceName) }
|
||||
, resourceType{ std::move(rhs.resourceType) }
|
||||
, images{ std::move(rhs.images) }
|
||||
, imageViews{ std::move(rhs.imageViews) }
|
||||
, resourceFormat{ std::move(rhs.resourceFormat) }
|
||||
, width{ rhs.width }
|
||||
, height{ rhs.height }
|
||||
, mipLevels{ rhs.mipLevels }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Move assignment operator.
|
||||
|
||||
\param rhs
|
||||
The other resource.
|
||||
|
||||
\return
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource& SHRenderGraphResource::operator=(SHRenderGraphResource&& rhs) noexcept
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
resourceName = std::move(rhs.resourceName);
|
||||
resourceType = std::move(rhs.resourceType);
|
||||
images = std::move(rhs.images);
|
||||
imageViews = std::move(rhs.imageViews);
|
||||
resourceFormat = std::move(rhs.resourceFormat);
|
||||
width = rhs.width;
|
||||
height = rhs.height;
|
||||
mipLevels = rhs.mipLevels;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Destructor for resource.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource::~SHRenderGraphResource(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\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.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHSubpass::SHSubpass(ResourceManager& rm, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
|
||||
: resourceAttachmentMapping{ mapping }
|
||||
, ptrToResources{ resources }
|
||||
, parentNode{ parent }
|
||||
, subpassIndex{ index }
|
||||
, superBatch{}
|
||||
, colorReferences{}
|
||||
, depthReferences{}
|
||||
, inputReferences{}
|
||||
{
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Move constructor for subpass.
|
||||
|
||||
\param rhs
|
||||
The subpass the move from.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHSubpass::SHSubpass(SHSubpass&& rhs) noexcept
|
||||
: subpassIndex{ std::move(rhs.subpassIndex) }
|
||||
, parentNode{ std::move(rhs.parentNode) }
|
||||
, superBatch{ std::move(rhs.superBatch) }
|
||||
, colorReferences{ std::move(rhs.colorReferences) }
|
||||
, depthReferences{ std::move(rhs.depthReferences) }
|
||||
, inputReferences{ std::move(rhs.inputReferences) }
|
||||
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
|
||||
, ptrToResources{ rhs.ptrToResources }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Move assignment operator for subpass.
|
||||
|
||||
\param rhs
|
||||
subpass to move from.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHSubpass& SHSubpass::operator=(SHSubpass&& rhs) noexcept
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
subpassIndex = std::move(rhs.subpassIndex);
|
||||
parentNode = std::move(rhs.parentNode);
|
||||
superBatch = std::move(rhs.superBatch);
|
||||
colorReferences = std::move(rhs.colorReferences);
|
||||
depthReferences = std::move(rhs.depthReferences);
|
||||
inputReferences = std::move(rhs.inputReferences);
|
||||
resourceAttachmentMapping = rhs.resourceAttachmentMapping;
|
||||
ptrToResources = rhs.ptrToResources;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
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 SHSubpass::AddColorOutput(std::string resourceToReference) noexcept
|
||||
{
|
||||
colorReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Adds a depth 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.
|
||||
|
||||
\param attachmentDescriptionType
|
||||
Depending on the type of the resource, initialize the image layout
|
||||
appropriately.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType) noexcept
|
||||
{
|
||||
vk::ImageLayout imageLayout;
|
||||
switch (attachmentDescriptionType)
|
||||
{
|
||||
case SH_ATT_DESC_TYPE::DEPTH:
|
||||
imageLayout = vk::ImageLayout::eDepthAttachmentOptimal;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::STENCIL:
|
||||
imageLayout = vk::ImageLayout::eStencilAttachmentOptimal;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::DEPTH_STENCIL:
|
||||
imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
|
||||
break;
|
||||
default:
|
||||
//Invalid
|
||||
return;
|
||||
}
|
||||
depthReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), imageLayout });
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Adds a input 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 SHSubpass::AddInput(std::string resourceToReference) noexcept
|
||||
{
|
||||
inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
|
||||
}
|
||||
|
||||
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
// Ensure correct transforms are provided
|
||||
superBatch->UpdateBuffers(frameIndex);
|
||||
|
||||
// Draw all the batches
|
||||
superBatch->Draw(commandBuffer, frameIndex);
|
||||
|
||||
// Draw all the exterior draw calls
|
||||
for (auto& drawCall : exteriorDrawCalls)
|
||||
{
|
||||
drawCall(commandBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
|
||||
{
|
||||
exteriorDrawCalls.push_back(newDrawCall);
|
||||
}
|
||||
|
||||
void SHSubpass::Init(ResourceManager& resourceManager) noexcept
|
||||
{
|
||||
superBatch = resourceManager.Create<SHSuperBatch>(GetHandle());
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Getter for parent renderpass.
|
||||
|
||||
\return
|
||||
Returns the parent renderpass the subpass belongs to.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHRenderGraphNode> const& SHSubpass::GetParentNode(void) const noexcept
|
||||
{
|
||||
return parentNode;
|
||||
}
|
||||
|
||||
SHADE::SHSubPassIndex SHSubpass::GetIndex() const noexcept
|
||||
{
|
||||
return subpassIndex;
|
||||
}
|
||||
|
||||
Handle<SHSuperBatch> SHSubpass::GetSuperBatch(void) const noexcept
|
||||
{
|
||||
return superBatch;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Creates a renderpass for the node. Uses subpass and attachment
|
||||
descriptions already configured beforehand in the render graph.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::CreateRenderpass(void) noexcept
|
||||
{
|
||||
renderpass = logicalDeviceHdl->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Creates a framebuffer from the images used in the renderpass.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::CreateFramebuffer(void) noexcept
|
||||
{
|
||||
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
||||
{
|
||||
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
||||
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
for (uint32_t j = 0; j < attResources.size(); ++j)
|
||||
{
|
||||
uint32_t imageViewIndex = (attResources[j]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) ? i : 0;
|
||||
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
||||
|
||||
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
||||
if (fbWidth > attResources[j]->width)
|
||||
fbWidth = attResources[j]->width;
|
||||
if (fbHeight > attResources[j]->height)
|
||||
fbHeight = attResources[j]->height;
|
||||
}
|
||||
|
||||
|
||||
framebuffers[i] = logicalDeviceHdl->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Render Graph node constructor. Note that we do not create the renderpass
|
||||
yet. This is because layouts of attachment descriptions facilitate image
|
||||
transitions and we cannot know guarantee layouts until we've seen all
|
||||
renderpasses and their subpasses in the graph.
|
||||
|
||||
\param swapchain
|
||||
Swapchain required to query number of images as parameters for number
|
||||
of framebuffers to create.
|
||||
|
||||
\param attachmentDescriptionTypes
|
||||
|
||||
|
||||
\return
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphNode::SHRenderGraphNode(ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources, Handle<SHGraphicsGlobalData> globalData) noexcept
|
||||
: logicalDeviceHdl{ logicalDevice }
|
||||
, renderpass{}
|
||||
, framebuffers{}
|
||||
, prereqNodes{ std::move(predecessors) }
|
||||
, attachmentDescriptions{}
|
||||
, resourceAttachmentMapping{}
|
||||
, attResources{ std::move(attRes) }
|
||||
, subpasses{}
|
||||
, executed{ false }
|
||||
, configured{ false }
|
||||
, resourceManager{ rm }
|
||||
, ptrToResources{ resources }
|
||||
{
|
||||
// pipeline library initialization
|
||||
pipelineLibrary.Init(logicalDeviceHdl, globalData);
|
||||
|
||||
attachmentDescriptions.resize(attResources.size());
|
||||
|
||||
bool containsSwapchainImage = false;
|
||||
for (uint32_t i = 0; i < attResources.size(); ++i)
|
||||
{
|
||||
// As mentioned above we don't initialize much here because it's dependent on how other renderpasses are configured.
|
||||
vk::AttachmentDescription& newDesc = attachmentDescriptions[i];
|
||||
newDesc.samples = vk::SampleCountFlagBits::e1;
|
||||
|
||||
// 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::eStore;
|
||||
|
||||
newDesc.stencilLoadOp = vk::AttachmentLoadOp::eClear;
|
||||
newDesc.stencilStoreOp = vk::AttachmentStoreOp::eStore;
|
||||
|
||||
newDesc.format = attResources[i]->resourceFormat;
|
||||
|
||||
if (attResources[i]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT)
|
||||
containsSwapchainImage = true;
|
||||
|
||||
resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i);
|
||||
}
|
||||
|
||||
if (!containsSwapchainImage)
|
||||
framebuffers.resize(1);
|
||||
else
|
||||
framebuffers.resize(swapchain->GetNumImages());
|
||||
|
||||
// At this point, we could configure framebuffers if we had the renderpass object but we don't so their creation has to be
|
||||
// deferred to when renderpasses are also created.
|
||||
}
|
||||
|
||||
SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept
|
||||
: resourceManager{ rhs.resourceManager }
|
||||
, logicalDeviceHdl{ rhs.logicalDeviceHdl }
|
||||
, renderpass{ rhs.renderpass }
|
||||
, framebuffers{ std::move(rhs.framebuffers) }
|
||||
, prereqNodes{ std::move(rhs.prereqNodes) }
|
||||
, attachmentDescriptions{ std::move(rhs.attachmentDescriptions) }
|
||||
, attResources{ std::move(rhs.attResources) }
|
||||
, subpasses{ std::move(rhs.subpasses) }
|
||||
, resourceAttachmentMapping{ std::move(rhs.resourceAttachmentMapping) }
|
||||
, subpassIndexing{ std::move(rhs.subpassIndexing) }
|
||||
, configured{ rhs.configured }
|
||||
, executed{ rhs.executed }
|
||||
, ptrToResources{ rhs.ptrToResources }
|
||||
, pipelineLibrary{ std::move(rhs.pipelineLibrary) }
|
||||
, batcher { std::move(rhs.batcher) }
|
||||
|
||||
{
|
||||
rhs.renderpass = {};
|
||||
}
|
||||
|
||||
SHRenderGraphNode& SHRenderGraphNode::operator=(SHRenderGraphNode&& rhs) noexcept
|
||||
{
|
||||
if (&rhs == this)
|
||||
return *this;
|
||||
|
||||
resourceManager = rhs.resourceManager;
|
||||
logicalDeviceHdl = rhs.logicalDeviceHdl;
|
||||
renderpass = rhs.renderpass;
|
||||
framebuffers = std::move(rhs.framebuffers);
|
||||
prereqNodes = std::move(rhs.prereqNodes);
|
||||
attachmentDescriptions = std::move(rhs.attachmentDescriptions);
|
||||
attResources = std::move(rhs.attResources);
|
||||
subpasses = std::move(rhs.subpasses);
|
||||
resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
|
||||
subpassIndexing = std::move(rhs.subpassIndexing);
|
||||
ptrToResources = std::move(rhs.ptrToResources);
|
||||
pipelineLibrary = std::move(rhs.pipelineLibrary);
|
||||
batcher = std::move(rhs.batcher);
|
||||
|
||||
rhs.renderpass = {};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\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<SHSubpass> SHRenderGraphNode::AddSubpass(std::string subpassName) noexcept
|
||||
{
|
||||
// if subpass already exists, don't add.
|
||||
if (subpassIndexing.contains(subpassName))
|
||||
{
|
||||
SHLOG_ERROR("Subpass already exists.");
|
||||
return{};
|
||||
}
|
||||
|
||||
// Add subpass to container and create mapping for it
|
||||
subpasses.emplace_back(resourceManager.Create<SHSubpass>(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
|
||||
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
|
||||
Handle<SHSubpass> subpass = subpasses.back();
|
||||
subpass->Init(resourceManager);
|
||||
|
||||
// Register the SuperBatch
|
||||
batcher.RegisterSuperBatch(subpass->GetSuperBatch());
|
||||
|
||||
return subpass;
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& 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, frameIndex);
|
||||
|
||||
// Go to next subpass if not last subpass
|
||||
if (i != subpasses.size() - 1)
|
||||
commandBuffer->NextSubpass();
|
||||
}
|
||||
|
||||
commandBuffer->EndRenderpass();
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
|
||||
{
|
||||
// verify subpass exists
|
||||
if (subpass->GetIndex() >= subpasses.size())
|
||||
{
|
||||
SHLOG_ERROR("Subpass index passed in is not valid. RenderGraphNode does not have that many passes. ");
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(vsFsPair);
|
||||
if (!pipeline)
|
||||
{
|
||||
pipeline = pipelineLibrary.CreateDrawPipeline
|
||||
(
|
||||
vsFsPair,
|
||||
renderpass,
|
||||
subpass
|
||||
);
|
||||
}
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex)
|
||||
{
|
||||
batcher.FinaliseBatches(logicalDeviceHdl, frameIndex);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Get the renderpass from the node.
|
||||
|
||||
\return
|
||||
Handle to the renderpass.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHVkRenderpass> SHRenderGraphNode::GetRenderpass(void) const noexcept
|
||||
{
|
||||
return renderpass;
|
||||
}
|
||||
|
||||
Handle<SHSubpass> SHRenderGraphNode::GetSubpass(std::string_view subpassName) const noexcept
|
||||
{
|
||||
return subpasses[subpassIndexing.at(subpassName.data())];
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
@ -779,7 +131,7 @@ namespace SHADE
|
|||
attDesc.loadOp = vk::AttachmentLoadOp::eLoad;
|
||||
predAttDesc.storeOp = vk::AttachmentStoreOp::eStore;
|
||||
|
||||
// TODO: Stecil load and store
|
||||
// TODO: Stencil load and store
|
||||
|
||||
// When an image is done being used in a renderpass, the image layout will end up being the finalLayout
|
||||
// value of the attachment description. We want this to carry over to the next renderpass; specifically
|
||||
|
@ -976,11 +328,10 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, Handle<SHGraphicsGlobalData> inGlobalData) noexcept
|
||||
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept
|
||||
{
|
||||
logicalDeviceHdl = logicalDevice;
|
||||
swapchainHdl = swapchain;
|
||||
globalData = inGlobalData;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -1012,7 +363,6 @@ namespace SHADE
|
|||
, nodes{ std::move(rhs.nodes) }
|
||||
, graphResources{ std::move(rhs.graphResources) }
|
||||
, resourceManager{ std::move(rhs.resourceManager) }
|
||||
, globalData{ rhs.globalData }
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -1028,7 +378,6 @@ namespace SHADE
|
|||
nodes = std::move(rhs.nodes);
|
||||
graphResources = std::move(rhs.graphResources);
|
||||
resourceManager = std::move(rhs.resourceManager);
|
||||
globalData = rhs.globalData;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -1086,7 +435,7 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
nodes.emplace_back(resourceManager.Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(resources), std::move(predecessors), &graphResources, globalData));
|
||||
nodes.emplace_back(resourceManager.Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(resources), std::move(predecessors), &graphResources));
|
||||
nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
|
||||
return nodes.at(nodeIndexing[nodeName]);
|
||||
}
|
||||
|
@ -1114,20 +463,20 @@ namespace SHADE
|
|||
|
||||
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
|
||||
// better way to manage these
|
||||
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer) noexcept
|
||||
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||
{
|
||||
// TODO: DON'T HARDCODE THIS
|
||||
cmdBuffer->SetViewportScissor(1920.0f, 1080.0f, 1920, 1080);
|
||||
|
||||
for (auto& node : nodes)
|
||||
node->Execute(cmdBuffer, frameIndex);
|
||||
node->Execute(cmdBuffer, descPool, frameIndex);
|
||||
}
|
||||
|
||||
void SHRenderGraph::FinaliseBatch(uint32_t frameIndex)
|
||||
void SHRenderGraph::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
node->FinaliseBatch(frameIndex);
|
||||
node->FinaliseBatch(frameIndex, descPool);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,12 @@
|
|||
#include "Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h"
|
||||
#include "Graphics/MiddleEnd/Batching/SHSuperBatch.h"
|
||||
#include "../MiddleEnd/Batching/SHBatcher.h"
|
||||
#include "SHRenderGraphNode.h"
|
||||
#include "SHSubpass.h"
|
||||
#include "SHRenderGraphResource.h"
|
||||
#include "SHRenderGraphNode.h"
|
||||
#include "SHSubpass.h"
|
||||
#include "SHAttachmentDescriptionType.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -24,223 +30,6 @@ namespace SHADE
|
|||
class SHRenderGraphNode;
|
||||
class SHGraphicsGlobalData;
|
||||
|
||||
// Used for attachment description creation for renderpass node
|
||||
enum class SH_ATT_DESC_TYPE
|
||||
{
|
||||
COLOR,
|
||||
COLOR_PRESENT,
|
||||
DEPTH,
|
||||
STENCIL,
|
||||
DEPTH_STENCIL,
|
||||
};
|
||||
|
||||
|
||||
class SH_API SHRenderGraphResource
|
||||
{
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
//! Name of the resource
|
||||
std::string resourceName;
|
||||
|
||||
//! Used for initializing image layouts
|
||||
SH_ATT_DESC_TYPE resourceType;
|
||||
|
||||
//! The resource itself (this is a vector because if the resource happens
|
||||
//! to be a swapchain image, then we need however many frames in flight).
|
||||
//! However when it's not a swapchain image, we want this container to be size 1
|
||||
//! because writing to these images will not interfere with images in the previous
|
||||
//! frame, unlike the swapchain image.
|
||||
std::vector<Handle<SHVkImage>> images;
|
||||
|
||||
//! Views to resources (vector because same rationale as images. see above).
|
||||
std::vector<Handle<SHVkImageView>> imageViews;
|
||||
|
||||
//! Image format
|
||||
vk::Format resourceFormat;
|
||||
|
||||
//! width of the resource
|
||||
uint32_t width;
|
||||
|
||||
//! Height of the resource
|
||||
uint32_t height;
|
||||
|
||||
//! Number of mipmap levels
|
||||
uint8_t mipLevels;
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept;
|
||||
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
|
||||
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
|
||||
~SHRenderGraphResource(void) noexcept;
|
||||
|
||||
friend class SHRenderGraphNode;
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
|
||||
class SH_API SHSubpass : public ISelfHandle<SHSubpass>
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
/*---------------------------------------------------------------------*/
|
||||
//! The index of the subpass in the render graph
|
||||
uint32_t subpassIndex;
|
||||
|
||||
//! The parent renderpass that this subpass belongs to
|
||||
Handle<SHRenderGraphNode> parentNode;
|
||||
|
||||
//!
|
||||
Handle<SHSuperBatch> superBatch;
|
||||
|
||||
//! Color attachments
|
||||
std::vector<vk::AttachmentReference> colorReferences;
|
||||
|
||||
//! Depth attachments
|
||||
std::vector<vk::AttachmentReference> depthReferences;
|
||||
|
||||
//! Input attachments
|
||||
std::vector<vk::AttachmentReference> inputReferences;
|
||||
|
||||
//! For getting attachment reference indices using handles
|
||||
std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
|
||||
|
||||
//! Pointer to resources in the render graph (for getting handle IDs)
|
||||
std::unordered_map<std::string, Handle<SHRenderGraphResource>> 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<std::function<void(Handle<SHVkCommandBuffer>&)>> exteriorDrawCalls;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHSubpass(ResourceManager& rm, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> 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<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
|
||||
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
|
||||
|
||||
void Init (ResourceManager& resourceManager) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* GETTERS AND SETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHRenderGraphNode> const& GetParentNode(void) const noexcept;
|
||||
SHSubPassIndex GetIndex() const noexcept;
|
||||
Handle<SHSuperBatch> GetSuperBatch (void) const noexcept;
|
||||
|
||||
|
||||
friend class SHRenderGraphNode;
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode>
|
||||
{
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
ResourceManager& resourceManager;
|
||||
|
||||
//! For Vulkan object creation
|
||||
Handle<SHVkLogicalDevice> logicalDeviceHdl;
|
||||
|
||||
//! Each node will have a renderpass and each renderpass will have its own subpasses.
|
||||
//! These subpasses will execute sequentially.
|
||||
Handle<SHVkRenderpass> renderpass;
|
||||
|
||||
//! Framebuffers used in this renderpass. If renderpass contains usage of a swapchain image
|
||||
//! used for presenting, then we cannot use just 1 framebuffer, we need to have 1 for however many frames in flight.
|
||||
std::vector<Handle<SHVkFramebuffer>> framebuffers;
|
||||
|
||||
//! Nodes that must finish execution before this node is executed will be in this container
|
||||
std::vector<Handle<SHRenderGraphNode>> prereqNodes;
|
||||
|
||||
//! Container of Attachment descriptions
|
||||
std::vector<vk::AttachmentDescription> attachmentDescriptions;
|
||||
|
||||
//! Resources used in this renderpass
|
||||
std::vector<Handle<SHRenderGraphResource>> attResources;
|
||||
|
||||
//! Vector of subpasses
|
||||
std::vector<Handle<SHSubpass>> subpasses;
|
||||
|
||||
//! Descriptions to pass to renderpass for renderpass creation. We want to keep this here because
|
||||
std::vector<vk::SubpassDescription> spDescs;
|
||||
|
||||
//! Subpass dependencies for renderpass creation
|
||||
std::vector<vk::SubpassDependency> spDeps;
|
||||
|
||||
//! For indexing resources fast
|
||||
std::unordered_map<uint64_t, uint32_t> resourceAttachmentMapping;
|
||||
|
||||
//! For indexing subpasses
|
||||
std::map<std::string, uint32_t> subpassIndexing;
|
||||
|
||||
//! Pointer to resources in the render graph (for getting handle IDs)
|
||||
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
|
||||
|
||||
//! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass
|
||||
SHPipelineLibrary pipelineLibrary;
|
||||
|
||||
//! Whether or not the node has finished execution
|
||||
bool executed;
|
||||
|
||||
//! Whether or not the node has been configured already or not
|
||||
bool configured;
|
||||
|
||||
SHBatcher batcher;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void CreateRenderpass (void) noexcept;
|
||||
void CreateFramebuffer(void) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHRenderGraphNode (ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources, Handle<SHGraphicsGlobalData> globalData) noexcept;
|
||||
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
|
||||
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHSubpass> AddSubpass (std::string subpassName) noexcept;
|
||||
// TODO: RemoveSubpass()
|
||||
void Execute (Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
|
||||
Handle<SHVkPipeline> GetOrCreatePipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHVkRenderpass> GetRenderpass (void) const noexcept;
|
||||
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
class SH_API SHRenderGraph
|
||||
{
|
||||
|
@ -273,9 +62,6 @@ namespace SHADE
|
|||
//! Resource library for graph handles
|
||||
ResourceManager resourceManager;
|
||||
|
||||
//! Handle to global data
|
||||
Handle<SHGraphicsGlobalData> globalData;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
|
@ -288,12 +74,12 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, Handle<SHGraphicsGlobalData> inGlobalData) noexcept;
|
||||
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept;
|
||||
void AddResource (std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageCreateFlagBits createFlags = {});
|
||||
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<std::string> resourceNames, std::initializer_list<std::string> predecessorNodes) noexcept;
|
||||
void Generate (void) noexcept;
|
||||
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex);
|
||||
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHRenderGraphNode.h"
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
#include "Graphics/Images/SHVkImageView.h"
|
||||
#include "Graphics/Swapchain/SHVkSwapchain.h"
|
||||
#include "SHRenderGraphResource.h"
|
||||
#include "SHSubpass.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Creates a renderpass for the node. Uses subpass and attachment
|
||||
descriptions already configured beforehand in the render graph.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::CreateRenderpass(void) noexcept
|
||||
{
|
||||
renderpass = logicalDeviceHdl->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Creates a framebuffer from the images used in the renderpass.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::CreateFramebuffer(void) noexcept
|
||||
{
|
||||
for (uint32_t i = 0; i < framebuffers.size(); ++i)
|
||||
{
|
||||
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
|
||||
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
for (uint32_t j = 0; j < attResources.size(); ++j)
|
||||
{
|
||||
uint32_t imageViewIndex = (attResources[j]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) ? i : 0;
|
||||
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
|
||||
|
||||
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
|
||||
if (fbWidth > attResources[j]->width)
|
||||
fbWidth = attResources[j]->width;
|
||||
if (fbHeight > attResources[j]->height)
|
||||
fbHeight = attResources[j]->height;
|
||||
}
|
||||
|
||||
|
||||
framebuffers[i] = logicalDeviceHdl->CreateFramebuffer(renderpass, imageViews, fbWidth, fbHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Render Graph node constructor. Note that we do not create the renderpass
|
||||
yet. This is because layouts of attachment descriptions facilitate image
|
||||
transitions and we cannot know guarantee layouts until we've seen all
|
||||
renderpasses and their subpasses in the graph.
|
||||
|
||||
\param swapchain
|
||||
Swapchain required to query number of images as parameters for number
|
||||
of framebuffers to create.
|
||||
|
||||
\param attachmentDescriptionTypes
|
||||
|
||||
|
||||
\return
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphNode::SHRenderGraphNode(ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
|
||||
: logicalDeviceHdl{ logicalDevice }
|
||||
, renderpass{}
|
||||
, framebuffers{}
|
||||
, prereqNodes{ std::move(predecessors) }
|
||||
, attachmentDescriptions{}
|
||||
, resourceAttachmentMapping{}
|
||||
, attResources{ std::move(attRes) }
|
||||
, subpasses{}
|
||||
, executed{ false }
|
||||
, configured{ false }
|
||||
, resourceManager{ rm }
|
||||
, ptrToResources{ resources }
|
||||
{
|
||||
// pipeline library initialization
|
||||
pipelineLibrary.Init(logicalDeviceHdl);
|
||||
|
||||
attachmentDescriptions.resize(attResources.size());
|
||||
|
||||
bool containsSwapchainImage = false;
|
||||
for (uint32_t i = 0; i < attResources.size(); ++i)
|
||||
{
|
||||
// As mentioned above we don't initialize much here because it's dependent on how other renderpasses are configured.
|
||||
vk::AttachmentDescription& newDesc = attachmentDescriptions[i];
|
||||
newDesc.samples = vk::SampleCountFlagBits::e1;
|
||||
|
||||
// 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::eStore;
|
||||
|
||||
newDesc.stencilLoadOp = vk::AttachmentLoadOp::eClear;
|
||||
newDesc.stencilStoreOp = vk::AttachmentStoreOp::eStore;
|
||||
|
||||
newDesc.format = attResources[i]->resourceFormat;
|
||||
|
||||
if (attResources[i]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT)
|
||||
containsSwapchainImage = true;
|
||||
|
||||
resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i);
|
||||
}
|
||||
|
||||
if (!containsSwapchainImage)
|
||||
framebuffers.resize(1);
|
||||
else
|
||||
framebuffers.resize(swapchain->GetNumImages());
|
||||
|
||||
// At this point, we could configure framebuffers if we had the renderpass object but we don't so their creation has to be
|
||||
// deferred to when renderpasses are also created.
|
||||
}
|
||||
|
||||
SHRenderGraphNode::SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept
|
||||
: resourceManager{ rhs.resourceManager }
|
||||
, logicalDeviceHdl{ rhs.logicalDeviceHdl }
|
||||
, renderpass{ rhs.renderpass }
|
||||
, framebuffers{ std::move(rhs.framebuffers) }
|
||||
, prereqNodes{ std::move(rhs.prereqNodes) }
|
||||
, attachmentDescriptions{ std::move(rhs.attachmentDescriptions) }
|
||||
, attResources{ std::move(rhs.attResources) }
|
||||
, subpasses{ std::move(rhs.subpasses) }
|
||||
, resourceAttachmentMapping{ std::move(rhs.resourceAttachmentMapping) }
|
||||
, subpassIndexing{ std::move(rhs.subpassIndexing) }
|
||||
, configured{ rhs.configured }
|
||||
, executed{ rhs.executed }
|
||||
, ptrToResources{ rhs.ptrToResources }
|
||||
, pipelineLibrary{ std::move(rhs.pipelineLibrary) }
|
||||
, batcher{ std::move(rhs.batcher) }
|
||||
|
||||
{
|
||||
rhs.renderpass = {};
|
||||
}
|
||||
|
||||
SHRenderGraphNode& SHRenderGraphNode::operator=(SHRenderGraphNode&& rhs) noexcept
|
||||
{
|
||||
if (&rhs == this)
|
||||
return *this;
|
||||
|
||||
resourceManager = rhs.resourceManager;
|
||||
logicalDeviceHdl = rhs.logicalDeviceHdl;
|
||||
renderpass = rhs.renderpass;
|
||||
framebuffers = std::move(rhs.framebuffers);
|
||||
prereqNodes = std::move(rhs.prereqNodes);
|
||||
attachmentDescriptions = std::move(rhs.attachmentDescriptions);
|
||||
attResources = std::move(rhs.attResources);
|
||||
subpasses = std::move(rhs.subpasses);
|
||||
resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
|
||||
subpassIndexing = std::move(rhs.subpassIndexing);
|
||||
ptrToResources = std::move(rhs.ptrToResources);
|
||||
pipelineLibrary = std::move(rhs.pipelineLibrary);
|
||||
batcher = std::move(rhs.batcher);
|
||||
|
||||
rhs.renderpass = {};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\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<SHSubpass> SHRenderGraphNode::AddSubpass(std::string subpassName) noexcept
|
||||
{
|
||||
// if subpass already exists, don't add.
|
||||
if (subpassIndexing.contains(subpassName))
|
||||
{
|
||||
SHLOG_ERROR("Subpass already exists.");
|
||||
return{};
|
||||
}
|
||||
|
||||
// Add subpass to container and create mapping for it
|
||||
subpasses.emplace_back(resourceManager.Create<SHSubpass>(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
|
||||
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
|
||||
Handle<SHSubpass> subpass = subpasses.back();
|
||||
subpass->Init(resourceManager);
|
||||
|
||||
// Register the SuperBatch
|
||||
batcher.RegisterSuperBatch(subpass->GetSuperBatch());
|
||||
|
||||
return subpass;
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, 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, descPool, frameIndex);
|
||||
|
||||
// Go to next subpass if not last subpass
|
||||
if (i != subpasses.size() - 1)
|
||||
commandBuffer->NextSubpass();
|
||||
}
|
||||
|
||||
commandBuffer->EndRenderpass();
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
|
||||
{
|
||||
// verify subpass exists
|
||||
if (subpass->GetIndex() >= subpasses.size())
|
||||
{
|
||||
SHLOG_ERROR("Subpass index passed in is not valid. RenderGraphNode does not have that many passes. ");
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(vsFsPair);
|
||||
if (!pipeline)
|
||||
{
|
||||
pipeline = pipelineLibrary.CreateDrawPipeline
|
||||
(
|
||||
vsFsPair,
|
||||
renderpass,
|
||||
subpass
|
||||
);
|
||||
}
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||
{
|
||||
batcher.FinaliseBatches(logicalDeviceHdl, descPool, frameIndex);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Get the renderpass from the node.
|
||||
|
||||
\return
|
||||
Handle to the renderpass.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHVkRenderpass> SHRenderGraphNode::GetRenderpass(void) const noexcept
|
||||
{
|
||||
return renderpass;
|
||||
}
|
||||
|
||||
Handle<SHSubpass> SHRenderGraphNode::GetSubpass(std::string_view subpassName) const noexcept
|
||||
{
|
||||
return subpasses[subpassIndexing.at(subpassName.data())];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "SHAttachmentDescriptionType.h"
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
#include "SH_API.h"
|
||||
#include "Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h"
|
||||
#include "Graphics/MiddleEnd/Batching/SHBatcher.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class ResourceManager;
|
||||
class SHVkFramebuffer;
|
||||
class SHRenderGraphResource;
|
||||
class SHVkLogicalDevice;
|
||||
class SHVkRenderpass;
|
||||
class SHVkDescriptorPool;
|
||||
|
||||
class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode>
|
||||
{
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
ResourceManager& resourceManager;
|
||||
|
||||
//! For Vulkan object creation
|
||||
Handle<SHVkLogicalDevice> logicalDeviceHdl;
|
||||
|
||||
//! Each node will have a renderpass and each renderpass will have its own subpasses.
|
||||
//! These subpasses will execute sequentially.
|
||||
Handle<SHVkRenderpass> renderpass;
|
||||
|
||||
//! Framebuffers used in this renderpass. If renderpass contains usage of a swapchain image
|
||||
//! used for presenting, then we cannot use just 1 framebuffer, we need to have 1 for however many frames in flight.
|
||||
std::vector<Handle<SHVkFramebuffer>> framebuffers;
|
||||
|
||||
//! Nodes that must finish execution before this node is executed will be in this container
|
||||
std::vector<Handle<SHRenderGraphNode>> prereqNodes;
|
||||
|
||||
//! Container of Attachment descriptions
|
||||
std::vector<vk::AttachmentDescription> attachmentDescriptions;
|
||||
|
||||
//! Resources used in this renderpass
|
||||
std::vector<Handle<SHRenderGraphResource>> attResources;
|
||||
|
||||
//! Vector of subpasses
|
||||
std::vector<Handle<SHSubpass>> subpasses;
|
||||
|
||||
//! Descriptions to pass to renderpass for renderpass creation. We want to keep this here because
|
||||
std::vector<vk::SubpassDescription> spDescs;
|
||||
|
||||
//! Subpass dependencies for renderpass creation
|
||||
std::vector<vk::SubpassDependency> spDeps;
|
||||
|
||||
//! For indexing resources fast
|
||||
std::unordered_map<uint64_t, uint32_t> resourceAttachmentMapping;
|
||||
|
||||
//! For indexing subpasses
|
||||
std::map<std::string, uint32_t> subpassIndexing;
|
||||
|
||||
//! Pointer to resources in the render graph (for getting handle IDs)
|
||||
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
|
||||
|
||||
//! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass
|
||||
SHPipelineLibrary pipelineLibrary;
|
||||
|
||||
//! Whether or not the node has finished execution
|
||||
bool executed;
|
||||
|
||||
//! Whether or not the node has been configured already or not
|
||||
bool configured;
|
||||
|
||||
SHBatcher batcher;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void CreateRenderpass(void) noexcept;
|
||||
void CreateFramebuffer(void) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHRenderGraphNode(ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept;
|
||||
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
|
||||
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept;
|
||||
// TODO: RemoveSubpass()
|
||||
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHVkRenderpass> GetRenderpass(void) const noexcept;
|
||||
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHRenderGraphResource.h"
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
#include "Graphics/Swapchain/SHVkSwapchain.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Non-default ctor for the resource. Using the type of the resource, we
|
||||
decide whether or not we create a resource or link with a swapchain
|
||||
resource (image).
|
||||
|
||||
\param logicalDevice
|
||||
Logical device required to create an image resource if the type is NOT
|
||||
SH_ATT_DESC_TYPE::COLOR_PRESENT.
|
||||
|
||||
\param swapchain
|
||||
Swapchain required to get swapchain image if the type IS
|
||||
SH_ATT_DESC_TYPE::COLOR_PRESENT.
|
||||
|
||||
\param type
|
||||
Type of the image resource.
|
||||
|
||||
\param format
|
||||
Format of the image resource.
|
||||
|
||||
\param w
|
||||
Width of the image resource.
|
||||
|
||||
\param h
|
||||
Height of the image resource.
|
||||
|
||||
\param levels
|
||||
Number of mipmap levels of the image resource.
|
||||
|
||||
\param createFlags
|
||||
Create flags used when an image resource needs to be created.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept
|
||||
: resourceType{ type }
|
||||
, resourceFormat{ format }
|
||||
, images{}
|
||||
, imageViews{}
|
||||
, width{ w }
|
||||
, height{ h }
|
||||
, mipLevels{ levels }
|
||||
, resourceName{ name }
|
||||
{
|
||||
// If the resource type is an arbitrary image and not swapchain image
|
||||
if (type != SH_ATT_DESC_TYPE::COLOR_PRESENT)
|
||||
{
|
||||
vk::ImageAspectFlags imageAspectFlags;
|
||||
vk::ImageUsageFlags usage = {};
|
||||
|
||||
// Check the resource type and set image usage flags and image aspect flags accordingly
|
||||
switch (resourceType)
|
||||
{
|
||||
case SH_ATT_DESC_TYPE::COLOR:
|
||||
usage |= vk::ImageUsageFlagBits::eColorAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::DEPTH:
|
||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::STENCIL:
|
||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
|
||||
break;
|
||||
case SH_ATT_DESC_TYPE::DEPTH_STENCIL:
|
||||
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
|
||||
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
|
||||
break;
|
||||
}
|
||||
|
||||
// The resource is not a swapchain image, just use the first slot of the vector
|
||||
images.push_back(logicalDevice->CreateImage(width, height, mipLevels, resourceFormat, usage, createFlags));
|
||||
|
||||
// prepare image view details
|
||||
SHImageViewDetails viewDetails
|
||||
{
|
||||
.viewType = vk::ImageViewType::e2D,
|
||||
.format = images[0]->GetImageFormat(),
|
||||
.imageAspectFlags = imageAspectFlags,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = mipLevels,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
};
|
||||
|
||||
// just 1 image view created
|
||||
imageViews.push_back(images[0]->CreateImageView(logicalDevice, images[0], viewDetails));
|
||||
}
|
||||
else // if swapchain image resource
|
||||
{
|
||||
// Prepare image view details
|
||||
SHImageViewDetails viewDetails
|
||||
{
|
||||
.viewType = vk::ImageViewType::e2D,
|
||||
.format = swapchain->GetSurfaceFormatKHR().format,
|
||||
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
};
|
||||
|
||||
// We want an image handle for every swapchain image
|
||||
images.resize(swapchain->GetNumImages());
|
||||
imageViews.resize(swapchain->GetNumImages());
|
||||
|
||||
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
|
||||
{
|
||||
images[i] = swapchain->GetSwapchainImage(i);
|
||||
imageViews[i] = images[i]->CreateImageView(logicalDevice, images[i], viewDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Move ctor for resource.
|
||||
|
||||
\param rhs
|
||||
The other resource.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource::SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept
|
||||
: resourceName{ std::move(rhs.resourceName) }
|
||||
, resourceType{ std::move(rhs.resourceType) }
|
||||
, images{ std::move(rhs.images) }
|
||||
, imageViews{ std::move(rhs.imageViews) }
|
||||
, resourceFormat{ std::move(rhs.resourceFormat) }
|
||||
, width{ rhs.width }
|
||||
, height{ rhs.height }
|
||||
, mipLevels{ rhs.mipLevels }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Move assignment operator.
|
||||
|
||||
\param rhs
|
||||
The other resource.
|
||||
|
||||
\return
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource& SHRenderGraphResource::operator=(SHRenderGraphResource&& rhs) noexcept
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
resourceName = std::move(rhs.resourceName);
|
||||
resourceType = std::move(rhs.resourceType);
|
||||
images = std::move(rhs.images);
|
||||
imageViews = std::move(rhs.imageViews);
|
||||
resourceFormat = std::move(rhs.resourceFormat);
|
||||
width = rhs.width;
|
||||
height = rhs.height;
|
||||
mipLevels = rhs.mipLevels;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Destructor for resource.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
SHRenderGraphResource::~SHRenderGraphResource(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue