This commit is contained in:
Brandon Mak 2022-09-17 22:28:03 +08:00
parent a85df55fc9
commit 3766a10edd
32 changed files with 2131 additions and 328 deletions

View File

@ -2,7 +2,7 @@
#include "SBApplication.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#define SHEDITOR
//#define SHEDITOR
#ifdef SHEDITOR
#include "Editor/SHEditor.h"
//#include "Scenes/SBEditorScene.h"
@ -76,7 +76,9 @@ namespace Sandbox
#endif
graphicsSystem->Run(1.0f);
graphicsSystem->EndRender();
}
SHADE::SHSystemManager::RunRoutines(false, 0.016f);
}
}

View File

@ -255,7 +255,7 @@ namespace SHADE
*/
/***************************************************************************/
void SHVkCommandBuffer::SetviewportScissor(float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX /*= 0.0f*/, float vpY /*= 0.0f*/, int32_t sX /*= 0.0f*/, int32_t sY /*= 0.0f*/, float vpMinDepth /*= 0.0f*/, float vpMaxDepth /*= 1.0f*/) noexcept
void SHVkCommandBuffer::SetViewportScissor(float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX /*= 0.0f*/, float vpY /*= 0.0f*/, int32_t sX /*= 0.0f*/, int32_t sY /*= 0.0f*/, float vpMinDepth /*= 0.0f*/, float vpMaxDepth /*= 1.0f*/) noexcept
{
vk::Viewport dynamicViewport
{

View File

@ -104,7 +104,7 @@ namespace SHADE
void NextSubpass (void) noexcept;
// Dynamic State
void SetviewportScissor (float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX = 0.0f, float vpY = 0.0f, int32_t sX = 0.0f, int32_t sY = 0.0f, float vpMinDepth = 0.0f, float vpMaxDepth = 1.0f) noexcept;
void SetViewportScissor (float vpWidth, float vpHeight, uint32_t sWidth, uint32_t sHeight, float vpX = 0.0f, float vpY = 0.0f, int32_t sX = 0.0f, int32_t sY = 0.0f, float vpMinDepth = 0.0f, float vpMaxDepth = 1.0f) noexcept;
// Binding Commands
void BindPipeline (Handle<SHVkPipeline> const& pipelineHdl) noexcept;

View File

@ -234,7 +234,7 @@ namespace SHADE
return SHVkInstance::GetResourceManager().Create<SHVkImageView>(inLogicalDeviceHdl, parent, createParams);
}
void SHVkImage::TransferToDeviceResource(Handle<SHVkCommandBuffer> const& cmdBufferHdl) noexcept
void SHVkImage::TransferToDeviceResource(void) noexcept
{
// prepare copy regions
std::vector<vk::BufferImageCopy> copyRegions{mipOffsets.size()};
@ -252,6 +252,7 @@ namespace SHADE
copyRegions[i].imageExtent = vk::Extent3D{ width >> i, height >> i, 1 };
}
//PrepareImageTransition();
}
/***************************************************************************/

View File

@ -135,7 +135,7 @@ namespace SHADE
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
Handle<SHVkImageView> CreateImageView (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept;
void TransferToDeviceResource (Handle<SHVkCommandBuffer> const& cmdBufferHdl) noexcept;
void TransferToDeviceResource (void) noexcept;
void PrepareImageTransition (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept;
/*-----------------------------------------------------------------------*/

View File

@ -0,0 +1,151 @@
/************************************************************************************//*!
\file SHCamera.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 21, 2022
\brief
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 "SHCamera.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* View Set Functions */
/*---------------------------------------------------------------------------------*/
void SHCamera::SetLookAt(const SHVec3& pos, const SHVec3& target, const SHVec3& up)
{
const SHVec3 VIEW = (target - pos).Normalized();
const SHVec3 RIGHT = SHVec3::Cross(VIEW, up).Normalized();
const SHVec3 UP = SHVec3::Cross(RIGHT, VIEW);
viewMatrix = SHMatrix::Identity;
viewMatrix(0, 0) = RIGHT[0];
viewMatrix(1, 0) = RIGHT[1];
viewMatrix(2, 0) = RIGHT[2];
viewMatrix(0, 1) = UP[0];
viewMatrix(1, 1) = UP[1];
viewMatrix(2, 1) = UP[2];
viewMatrix(0, 2) = -VIEW[0];
viewMatrix(1, 2) = -VIEW[1];
viewMatrix(2, 2) = -VIEW[2];
viewMatrix(3, 0) = -RIGHT.Dot(pos);
viewMatrix(3, 1) = -UP.Dot(pos);
viewMatrix(3, 2) = VIEW.Dot(pos);
isDirty = true;
}
/*---------------------------------------------------------------------------------*/
/* Projection Set Functions */
/*---------------------------------------------------------------------------------*/
void SHCamera::SetPerspective(float fov, float width, float height, float zNear, float zFar)
{
const float ASPECT_RATIO = width / height;
const float TAN_HALF_FOV = tan(fov * 0.5f);
projMatrix = SHMatrix::Identity;
projMatrix(0, 0) = 1.0f / (ASPECT_RATIO * TAN_HALF_FOV);
projMatrix(1, 1) = 1.0f / TAN_HALF_FOV;
projMatrix(2, 2) = zFar / (zFar - zNear);
projMatrix(2, 3) = 1.0f;
projMatrix(3, 2) = -(zFar * zNear) / (zFar - zNear);
isDirty = true;
}
void SHCamera::SetOrthographic(float width, float height, float zNear, float zFar)
{
const float R = width * 0.5f;
const float L = -R;
const float T = height * 0.5f;
const float B = -T;
projMatrix = SHMatrix::Identity;
projMatrix(0, 0) = 2.0f / (R - L);
projMatrix(1, 1) = 2.0f / (B - T);
projMatrix(2, 2) = 1.0f / (zFar - zNear);
projMatrix(3, 0) = -(R + L) / (R - L);
projMatrix(3, 1) = -(B + T) / (B - T);
projMatrix(3, 2) = -zNear / (zFar - zNear);
isDirty = true;
}
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
SHMathMat4f SHCamera::GetViewMatrix() const
{
return viewMatrix;
}
SHMathMat4f SHCamera::GetProjectionMatrix() const
{
return projMatrix;
}
SHMathMat4f SHCamera::GetViewProjectionMatrix()
{
updateMatrices();
return vpMatrix;
}
SHMathMat4f SHCamera::GetInverseViewMatrix() const
{
return inverseVpMatrix;
}
SHMathMat4f SHCamera::GetInverseProjectionMatrix() const
{
return inverseProjMatrix;
}
SHMathMat4f SHCamera::GetInverseViewProjectionMatrix()
{
updateMatrices();
return inverseViewMatrix;
}
/*---------------------------------------------------------------------------------*/
/* Mapping Functions */
/*---------------------------------------------------------------------------------*/
SHVec3 SHCamera::ScreenToWorld(const SHVec3& vec) const
{
return multiplyHomogenous(inverseVpMatrix, vec);
}
SHVec3 SHCamera::WorldToScreen(const SHVec3& vec) const
{
return multiplyHomogenous(vpMatrix, vec);
}
SHVec3 SHCamera::CameraToWorld(const SHVec3& vec) const
{
return multiplyHomogenous(inverseViewMatrix, vec);
}
SHVec3 SHCamera::WorldToCamera(const SHVec3& vec) const
{
return multiplyHomogenous(viewMatrix, vec);
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
void SHCamera::updateMatrices()
{
if (isDirty)
{
vpMatrix = viewMatrix * projMatrix;
inverseVpMatrix = vpMatrix;
inverseVpMatrix.Inverse();
}
}
SHVec3 SHCamera::multiplyHomogenous(const SHMathMat4f& mat, const SHVec3& vec)
{
const SHVec4 HOMO_VEC = { vec[0], vec[1], vec[2], 1.0f };
const SHVec4 RESULT = mat * HOMO_VEC;
return SHVec3 { RESULT[0], RESULT[1], RESULT[2] };
}
}

View File

@ -0,0 +1,80 @@
/************************************************************************************//*!
\file SHCamera.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 21, 2022
\brief
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
// Project Includes
#include "Math/SHMath.h"
namespace SHADE
{
/***********************************************************************************/
/*!
\brief
Object that manages the view and projection transformations for rendering
a 3D scene.
*/
/***********************************************************************************/
class SHCamera
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------*/
/* View Set Functions */
/*-----------------------------------------------------------------------------*/
void SetLookAt(const SHVec3& pos, const SHVec3& target, const SHVec3& up);
/*-----------------------------------------------------------------------------*/
/* Projection Set Functions */
/*-----------------------------------------------------------------------------*/
void SetPerspective(float fov, float width, float height, float zNear, float zFar);
void SetOrthographic(float width, float height, float zNear, float zFar);
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
SHMatrix GetViewMatrix() const;
SHMatrix GetProjectionMatrix() const;
SHMatrix GetViewProjectionMatrix();
SHMatrix GetInverseViewMatrix() const;
SHMatrix GetInverseProjectionMatrix() const;
SHMatrix GetInverseViewProjectionMatrix();
/*-----------------------------------------------------------------------------*/
/* Mapping Functions */
/*-----------------------------------------------------------------------------*/
SHVec3 ScreenToWorld(const SHVec3& vec) const;
SHVec3 WorldToScreen(const SHVec3& vec) const;
SHVec3 CameraToWorld(const SHVec3& vec) const;
SHVec3 WorldToCamera(const SHVec3& vec) const;
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
SHMatrix viewMatrix;
SHMatrix projMatrix;
SHMatrix vpMatrix;
SHMatrix inverseViewMatrix;
SHMatrix inverseProjMatrix;
SHMatrix inverseVpMatrix;
bool isDirty;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
void updateMatrices();
static SHVec3 multiplyHomogenous(const SHMatrix& mat, const SHMatrix& vec);
};
}

View File

@ -0,0 +1,82 @@
/************************************************************************************//*!
\file SHGraphicsSystem.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 8, 2022
\brief Contains definition of constants that relate to the SHGraphicsSystem.
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 <cstdint>
namespace SHADE
{
/***********************************************************************************/
/*!
\brief
Contains definition of constants related to the Graphics System.
*/
/***********************************************************************************/
struct SHGraphicsConstants
{
public:
struct DescriptorSetIndex
{
/***************************************************************************/
/*!
\brief
DescriptorSet Index for static global values like generic data, and
texture samplers
*/
/***************************************************************************/
static constexpr uint32_t STATIC_GLOBALS = 0;
/***************************************************************************/
/*!
\brief
DescriptorSet Index for dynamic global values like lights.
*/
/***************************************************************************/
static constexpr uint32_t DYNAMIC_GLOBALS = 1;
/***************************************************************************/
/*!
\brief
DescriptorSet Index for high frequency changing global values like
camera matrices.
*/
/***************************************************************************/
static constexpr uint32_t HIGH_FREQUENCY_GLOBALS = 2;
/***************************************************************************/
/*!
\brief
DescriptorSet Index for per-instance/material changing values.
*/
/***************************************************************************/
static constexpr uint32_t PER_INSTANCE = 3;
};
struct DescriptorSetBindings
{
/***************************************************************************/
/*!
\brief
DescriptorSet binding for per instance material values.
*/
/***************************************************************************/
static constexpr uint32_t BATCHED_PER_INST_DATA = 0;
};
/*******************************************************************************/
/*!
\brief
Number of frame buffers used by the Graphics System.
*/
/*******************************************************************************/
static constexpr int NUM_FRAME_BUFFERS = 3;
};
}

View File

@ -3,14 +3,14 @@
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 21, 2022
\brief
\brief
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
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 "SHpch.h"
#include "SHGraphicsSystem.h"
#include "Graphics/Instance/SHVkInstance.h"
@ -19,251 +19,370 @@ of DigiPen Institute of Technology is prohibited.
//#include "SHRenderer.h"
#include "Graphics/Windowing/SHWindow.h"
#include "Graphics/MiddleEnd/PerFrame/SHPerFrameData.h"
#include "Graphics/MiddleEnd/Interface/SHViewport.h"
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
void SHGraphicsSystem::Init(void)
{
// Set Up Instance
SHVkInstance::Init(true, true, true);
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
void SHGraphicsSystem::Init(void)
{
/*-----------------------------------------------------------------------*/
/* BACKEND BOILERPLATE */
/*-----------------------------------------------------------------------*/
// Set Up Instance
SHVkInstance::Init(true, true, true);
// Get Physical Device and Construct Logical Device
// TODO: Provide configuration for these options
physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST);
device = SHVkInstance::CreateLogicalDevice({ SHQueueParams(SH_Q_FAM::GRAPHICS, SH_QUEUE_SELECT::DEDICATED), SHQueueParams(SH_Q_FAM::TRANSFER, SH_QUEUE_SELECT::DEDICATED) }, physicalDevice);
// Get Physical Device and Construct Logical Device
// TODO: Provide configuration for these options
physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST);
device = SHVkInstance::CreateLogicalDevice({ SHQueueParams(SH_Q_FAM::GRAPHICS, SH_QUEUE_SELECT::DEDICATED), SHQueueParams(SH_Q_FAM::TRANSFER, SH_QUEUE_SELECT::DEDICATED) }, physicalDevice);
// Construct surface
surface = device->CreateSurface(window->GetHWND());
// Construct surface
surface = device->CreateSurface(window->GetHWND());
// Construct Swapchain
auto windowDims = window->GetWindowSize();
swapchain = device->CreateSwapchain(surface, windowDims.first, windowDims.second, SHSwapchainParams
{
.surfaceImageFormats {vk::Format::eB8G8R8A8Unorm, vk::Format::eR8G8B8A8Unorm, vk::Format::eB8G8R8Unorm, vk::Format::eR8G8B8Unorm},
.depthFormats {vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint},
.presentModes {vk::PresentModeKHR::eFifo, vk::PresentModeKHR::eMailbox, vk::PresentModeKHR::eImmediate},
.vsyncOn = false, // TODO: Set to true when shipping game
});
// Construct Swapchain
auto windowDims = window->GetWindowSize();
swapchain = device->CreateSwapchain(surface, windowDims.first, windowDims.second, SHSwapchainParams
{
.surfaceImageFormats {vk::Format::eB8G8R8A8Unorm, vk::Format::eR8G8B8A8Unorm, vk::Format::eB8G8R8Unorm, vk::Format::eR8G8B8Unorm},
.depthFormats {vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint},
.presentModes {vk::PresentModeKHR::eFifo, vk::PresentModeKHR::eMailbox, vk::PresentModeKHR::eImmediate},
.vsyncOn = false, // TODO: Set to true when shipping game
});
window->RegisterWindowSizeCallback([&]([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height)
{
renderContext.SetIsResized(true);
});
// Register callback to notify render context upon a window resize
window->RegisterWindowSizeCallback([&]([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height)
{
renderContext.SetIsResized(true);
});
// Create graphics queue
graphicsQueue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0);
// Create graphics queue
graphicsQueue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0);
// Create Render Context
renderContext.Init
(
device,
SHPerFrameDataParams
{
.swapchainHdl = swapchain,
.numThreads = 1,
.cmdPoolQueueFamilyType = SH_Q_FAM::GRAPHICS,
.cmdPoolResetMode = SH_CMD_POOL_RESET::POOL_BASED,
.cmdBufferTransient = true,
}
);
// Create Frame and Command Buffers
for (int i = 0; i < NUM_FRAME_BUFFERS; ++i)
{
//frameBuffers[i] = device->CreateFramebuffer(renderPass, { renderContext.GetFrameData(i).swapchainImageViewHdl }, windowDims[0], windowDims[1]);
SHPerFrameData& frameData = renderContext.GetFrameData(i);
// Create Render Context
renderContext.Init
(
device,
SHPerFrameDataParams
{
.swapchainHdl = swapchain,
.numThreads = 1,
.cmdPoolQueueFamilyType = SH_Q_FAM::GRAPHICS,
.cmdPoolResetMode = SH_CMD_POOL_RESET::POOL_BASED,
.cmdBufferTransient = true,
}
);
if (frameData.cmdPoolHdls.empty())
throw std::runtime_error("No command pools available!");
// Create a descriptor pool
descPool = device->CreateDescriptorPools();
Handle<SHVkCommandPool> commandPool = frameData.cmdPoolHdls[0];
//commandBuffers[i] = commandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); // works
}
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);
/*-----------------------------------------------------------------------*/
/* RENDERGRAPH TESTING */
/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* MIDDLE END SETUP
- Viewports
- Renderer
- Render graph in renderers
- Render graph command buffer semaphores
- Default vertex input state
/*-----------------------------------------------------------------------*/
// Set Up Cameras
screenCamera = resourceManager.Create<SHCamera>();
screenCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f));
screenCamera->SetOrthographic(windowDims.first, windowDims.second, 0.01f, 100.0f);
worldCamera = resourceManager.Create<SHCamera>();
worldCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f));
worldCamera->SetPerspective(90.0f, windowDims.first, windowDims.second, 0.0f, 100.0f);
renderGraph.Init(device, swapchain);
renderGraph.AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
renderGraph.AddResource("Normals", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
renderGraph.AddResource("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
renderGraph.AddResource("Downscale", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
renderGraph.AddResource("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second);
auto node = renderGraph.AddNode("G-Buffer", { "Composite", "Position", "Normals", "Present" }, {}); // no predecessors
// First subpass to write to G-Buffer
// Create Default Viewport
defaultViewport = AddViewport(vk::Viewport(0, 0, window->GetWindowSize().first, window->GetWindowSize().second, 0.0f, 1.0f));
// Create Debug Renderers
debugScreenRenderer = defaultViewport->AddRenderer(resourceManager);
debugScreenRenderer->SetCamera(screenCamera);
debugWorldRenderer = defaultViewport->AddRenderer(resourceManager);
debugWorldRenderer->SetCamera(worldCamera);
// Add world renderer to default viewport
worldRenderer = defaultViewport->AddRenderer(resourceManager);
worldRenderer->SetCamera(worldCamera);
// Get render graph from default viewport world renderer
auto worldRenderGraph = worldRenderer->GetRenderGraph();
// Initialize world render graph
worldRenderGraph->Init(device, swapchain);
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("Present", SH_ATT_DESC_TYPE::COLOR_PRESENT, windowDims.first, windowDims.second);
auto node = worldRenderGraph->AddNode("G-Buffer", { "Composite", "Position", "Normals", "Present" }, {}); // no predecessors
//First subpass to write to G-Buffer
auto writeSubpass = node->AddSubpass("G-Buffer Write");
writeSubpass->AddColorOutput("Position");
//writeSubpass->AddColorOutput("Present");
writeSubpass->AddColorOutput("Normals");
// Second subpass to read from G-Buffer
//auto compositeSubpass = node->AddSubpass("G-Buffer Composite");
// compositeSubpass->AddColorOutput("Composite");
// compositeSubpass->AddInput("Normals");
// compositeSubpass->AddInput("Position");
//Second subpass to read from G-Buffer
auto compositeSubpass = node->AddSubpass("G-Buffer Composite");
compositeSubpass->AddColorOutput("Present"); // TODO: This should be "Composite" and then composite will write to swapchain image "Present"
compositeSubpass->AddInput("Normals");
compositeSubpass->AddInput("Position");
auto imguiNode = renderGraph.AddNode("ImGui Node", { "Present" }, {}); // no predecessors
auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
imguiSubpass->AddColorOutput("Present");
auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {});
auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
imguiSubpass->AddColorOutput("Present");
//auto compositeNode = renderGraph.AddNode("Bloom", { "Composite", "Downscale", "Present" }, { "G-Buffer" });
//auto bloomSubpass = compositeNode->AddSubpass("Downsample");
//bloomSubpass->AddInput("Composite");
//bloomSubpass->AddColorOutput("Downscale");
//bloomSubpass->AddColorOutput("Present");
worldRenderGraph->Generate();
renderGraph.Generate();
// Create Semaphore
for (auto& semaHandle : graphSemaphores)
{
semaHandle = device->CreateSemaphore();
}
ConfigureDefaultVertexInputState();
//pipelineLibrary.Init(device, &defaultVertexInputState, );
}
/*-----------------------------------------------------------------------*/
/* RENDERGRAPH END TESTING */
/*-----------------------------------------------------------------------*/
}
void SHGraphicsSystem::Run(float dt) noexcept
/***************************************************************************/
/*!
\brief
Main render loop. Loops through viewports -> renderers -> invoke render
graphs sequentially using semaphores.
\param dt
\return
*/
/***************************************************************************/
void SHGraphicsSystem::Run(double dt) noexcept
{
// Frame data for the current frame
auto const& frameData = renderContext.GetCurrentFrameData();
renderGraph.Execute(renderContext.GetCurrentFrame());
// semaphore index. This is for render graphs to have semaphores to signal that the next render graph will use to wait on.
bool semIndex = 0;
graphicsQueue->SubmitCommandBuffer({ renderGraph.GetCommandBuffer(renderContext.GetCurrentFrame()) },
{ frameData.semRenderFinishHdl },
{ frameData.semImgAvailableHdl },
vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests);
// For every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
{
auto const& renderers = viewports[vpIndex]->GetRenderers();
// For every renderer
for (int renIndex = 0; renIndex < static_cast<int>(renderers.size()); ++renIndex)
{
// Draw first
renderers[renIndex]->Draw(renderContext.GetCurrentFrame());
// get render graph
auto rg = renderers[renIndex]->GetRenderGraph();
// submit a command buffer from the current render graph and make it wait for the previous render graph before submitting it to GPU.
graphicsQueue->SubmitCommandBuffer
(
{ rg->GetCommandBuffer(renderContext.GetCurrentFrame()) },
{ (vpIndex == viewports.size() - 1 && renIndex == renderers.size() - 1) ? frameData.semRenderFinishHdl : graphSemaphores[!semIndex]},
{ (vpIndex == 0 && renIndex == 0) ? frameData.semImgAvailableHdl : graphSemaphores[semIndex]},
{}
);
semIndex = !semIndex;
}
}
}
void SHGraphicsSystem::Exit(void)
{
//renderPass.Free();
renderContext.Destroy();
graphicsQueue.Free();
swapchain.Free();
surface.Free();
device.Free();
{
renderContext.Destroy();
graphicsQueue.Free();
swapchain.Free();
surface.Free();
device.Free();
SHVkInstance::Destroy();
}
SHVkInstance::Destroy();
}
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
/***************************************************************************/
/*!
\brief
Checks for window resize and acquire next image in swapchain.
*/
/***************************************************************************/
void SHGraphicsSystem::BeginRender()
{
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
/***************************************************************************/
/*!
\brief
Checks for window resize and acquire next image in swapchain.
*/
/***************************************************************************/
void SHGraphicsSystem::BeginRender()
{
auto windowDims = window->GetWindowSize();
if (renderContext.GetResizeAndReset())
{
{
device->WaitIdle();
// Resize the swapchain
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
}
}
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
// #BackEndTest: For for the fence initialized by queue submit
renderContext.WaitForFence();
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
// #BackEndTest: Acquire the next image in the swapchain available
renderContext.AcquireNextIamge();
// #BackEndTest: For for the fence initialized by queue submit
renderContext.WaitForFence();
// #BackEndTest: Get the current frame from frame manager
auto& currFrameData = renderContext.GetCurrentFrameData();
// #BackEndTest: Acquire the next image in the swapchain available
renderContext.AcquireNextIamge();
// #BackEndTest: Reset command pool
if (currFrameData.cmdPoolHdls.empty())
throw std::runtime_error("No command pools available!");
currFrameData.cmdPoolHdls[0]->Reset();
// #BackEndTest: Get the current frame from frame manager
auto& currFrameData = renderContext.GetCurrentFrameData();
}
// #BackEndTest: Reset command pool
if (currFrameData.cmdPoolHdls.empty())
throw std::runtime_error("No command pools available!");
currFrameData.cmdPoolHdls[0]->Reset();
/***************************************************************************/
/*!
\brief
Check if need to resize and advance the frame in the render context.
*/
/***************************************************************************/
void SHGraphicsSystem::EndRender()
{
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
auto& currFrameData = renderContext.GetCurrentFrameData();
}
// #BackEndTest: Prepare to present current image
vk::PresentInfoKHR presentInfo{};
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &currFrameData.semRenderFinishHdl->GetVkSem();
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &swapchain->GetVkSwapchain();
presentInfo.pImageIndices = &CURR_FRAME_IDX;
/***************************************************************************/
/*!
// #BackEndTest: queues an image for presentation
if (auto result = graphicsQueue->Present(swapchain, {currFrameData.semRenderFinishHdl}, CURR_FRAME_IDX); result != vk::Result::eSuccess)
{
// If swapchain is incompatible/outdated
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR)
{
\brief
Check if need to resize and advance the frame in the render context.
*/
/***************************************************************************/
void SHGraphicsSystem::EndRender()
{
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
auto& currFrameData = renderContext.GetCurrentFrameData();
// #BackEndTest: Prepare to present current image
vk::PresentInfoKHR presentInfo{};
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &currFrameData.semRenderFinishHdl->GetVkSem();
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &swapchain->GetVkSwapchain();
presentInfo.pImageIndices = &CURR_FRAME_IDX;
// #BackEndTest: queues an image for presentation
if (auto result = graphicsQueue->Present(swapchain, { currFrameData.semRenderFinishHdl }, CURR_FRAME_IDX); result != vk::Result::eSuccess)
{
// If swapchain is incompatible/outdated
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR)
{
auto windowDims = window->GetWindowSize();
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
}
}
// #BackEndTest: Cycle frame count
renderContext.AdvanceFrame();
}
//Handle<SHRenderer> SHGraphicsSystem::AddRenderer()
//{
// return Handle<SHRenderer>();
//}
//void SHGraphicsSystem::RemoveRenderer(Handle<SHRenderer> renderer)
//{
//}
Handle<SHScreenSegment> SHGraphicsSystem::AddSegment(const VkViewport& viewport, Handle<SHVkImage> imageToUse)
{
return Handle<SHScreenSegment>();
}
void SHGraphicsSystem::RemoveSegment(Handle<SHScreenSegment> segment)
{
}
}
}
// #BackEndTest: Cycle frame count
renderContext.AdvanceFrame();
}
Handle<SHViewport> SHGraphicsSystem::AddViewport(const vk::Viewport& viewport)
{
// Create the viewport
auto vp = SHVkInstance::GetResourceManager().Create<SHViewport>(device, viewport);
viewports.emplace_back(vp);
return vp;
}
void SHGraphicsSystem::RemoveViewport(Handle<SHViewport> viewport)
{
// Check if the viewport exists
auto iter = std::find(viewports.begin(), viewports.end(), viewport);
if (iter == viewports.end())
throw std::invalid_argument("Attempted to remove viewport that does not belong to this Graphics System.");
// Remove
viewport.Free();
viewports.erase(iter);
}
Handle<SHMaterial> SHGraphicsSystem::AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader)
{
// Retrieve pipeline from pipeline storage or create if unavailable
auto shaderPair = std::make_pair(vertShader, fragShader);
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(shaderPair);
if (!pipeline)
{
pipeline = pipelineLibrary.CreateDrawPipeline
(
shaderPair,
);
}
// Create material
auto mat = resourceManager.Create<SHMaterial>();
mat->SetPipeline(pipeline);
return mat;
}
void SHGraphicsSystem::RemoveMaterial(Handle<SHMaterial> material)
{
resourceManager.Free(material);
}
Handle<SHMaterialInstance> SHGraphicsSystem::AddMaterialInstance(Handle<SHMaterial> material)
{
return resourceManager.Create<SHMaterialInstance>(material);
}
void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance)
{
resourceManager.Free(materialInstance);
}
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
{
window = wind;
window = wind;
}
SHRenderGraph const& SHGraphicsSystem::GetRenderGraph(void) const noexcept
void SHGraphicsSystem::ConfigureDefaultVertexInputState(void) noexcept
{
return renderGraph;
defaultVertexInputState.AddBinding(false, false, {SHVertexAttribute(SHAttribFormat::FLOAT_3D)}); // positions at binding 0
defaultVertexInputState.AddBinding(false, false, {SHVertexAttribute(SHAttribFormat::FLOAT_2D)}); // UVs at binding 1
defaultVertexInputState.AddBinding(false, false, {SHVertexAttribute(SHAttribFormat::FLOAT_3D)}); // Normals at binding 2
defaultVertexInputState.AddBinding(false, false, {SHVertexAttribute(SHAttribFormat::FLOAT_3D)}); // Tangents at binding 3
defaultVertexInputState.AddBinding(true, true, {SHVertexAttribute(SHAttribFormat::MAT_4D)}); // Transform at binding 4 - 7 (4 slots)
}
void SHGraphicsSystem::SHGraphicsSystemRoutine::Execute(double dt) noexcept
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
}
void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->Run(dt);
}
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
}
}

View File

@ -3,11 +3,11 @@
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 21, 2022
\brief
\brief
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
@ -24,138 +24,161 @@ of DigiPen Institute of Technology is prohibited.
#include "ECS_Base/System/SHSystem.h"
#include "ECS_Base/System/SHSystemRoutine.h"
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
#include "Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkPhysicalDevice;
class SHVkLogicalDevice;
class SHVkSurface;
class SHVkSwapchain;
class SHScreenSegment;
//class SHRenderer;
class SHWindow;
class SHVkImage;
class SHVkFramebuffer;
class SHVkCommandBuffer;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Represents an axis aligned box on the screen to render to along with the
specified Image to render to that spot.
*/
/***********************************************************************************/
struct SHScreenSegment
{
VkViewport Viewport;
Handle<SHVkImage> ImageToUse;
};
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkPhysicalDevice;
class SHVkLogicalDevice;
class SHVkSurface;
class SHVkSwapchain;
class SHScreenSegment;
class SHWindow;
class SHVkImage;
class SHVkFramebuffer;
class SHVkCommandBuffer;
class SHRenderer;
class SHViewport;
class SHCamera;
class SHVkShaderModule;
/***********************************************************************************/
/*!
\brief
Manages the lifecycle and provides an interface for rendering multiple objects to
portions of the screen.
*/
/***********************************************************************************/
class SH_API SHGraphicsSystem : public SHSystem
{
public:
class SH_API SHGraphicsSystemRoutine : public SHSystemRoutine
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Manages the lifecycle and provides an interface for rendering multiple objects to
portions of the screen.
*/
/***********************************************************************************/
class SH_API SHGraphicsSystem : public SHSystem
{
public:
class SH_API BeginRoutine final : public SHSystemRoutine
{
public:
virtual void Execute(double dt) noexcept override;
public:
virtual void Execute(double dt) noexcept override final;
};
class SH_API RenderRoutine final : public SHSystemRoutine
{
public:
virtual void Execute(double dt) noexcept override final;
};
class SH_API EndRoutine final : public SHSystemRoutine
{
public:
virtual void Execute(double dt) noexcept override final;
};
public:
/*-----------------------------------------------------------------------------*/
/* Constants */
/*-----------------------------------------------------------------------------*/
static constexpr int NUM_FRAME_BUFFERS = 3;
public:
/*-----------------------------------------------------------------------------*/
/* Constants */
/*-----------------------------------------------------------------------------*/
static constexpr int NUM_FRAME_BUFFERS = 3;
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHGraphicsSystem (void) = default;
~SHGraphicsSystem(void) noexcept = default;
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHGraphicsSystem(void) = default;
~SHGraphicsSystem(void) noexcept = default;
/*-----------------------------------------------------------------------------*/
/* SHSystem overrides */
/*-----------------------------------------------------------------------------*/
virtual void Init(void) override;
void Run (float dt) noexcept;
virtual void Exit(void) override;
/*-----------------------------------------------------------------------------*/
/* SHSystem overrides */
/*-----------------------------------------------------------------------------*/
virtual void Init(void) override final;
void Run(double dt) noexcept;
virtual void Exit(void) override final;
/*-----------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*-----------------------------------------------------------------------------*/
void BeginRender();
void EndRender();
/*-----------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*-----------------------------------------------------------------------------*/
void BeginRender();
void EndRender();
/*-----------------------------------------------------------------------------*/
/* Renderers Registration Functions */
/*-----------------------------------------------------------------------------*/
//Handle<SHRenderer> AddRenderer();
//void RemoveRenderer(Handle<SHRenderer> renderer);
/*-----------------------------------------------------------------------------*/
/* Viewport Registration Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHViewport> AddViewport(const vk::Viewport& viewport);
void RemoveViewport(Handle<SHViewport> viewport);
/*-----------------------------------------------------------------------------*/
/* Viewport Registration Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHScreenSegment> AddSegment(const VkViewport& viewport, Handle<SHVkImage> imageToUse);
void RemoveSegment(Handle<SHScreenSegment> segment);
/*-----------------------------------------------------------------------------*/
/* Material Creation Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHMaterial> AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader);
void RemoveMaterial(Handle<SHMaterial> material);;
Handle<SHMaterialInstance> AddMaterialInstance(Handle<SHMaterial> material);
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
/*-----------------------------------------------------------------------------*/
/* Setters */
/*-----------------------------------------------------------------------------*/
void SetWindow (SHWindow* wind) noexcept;
/*-----------------------------------------------------------------------------*/
/* Setters */
/*-----------------------------------------------------------------------------*/
void SetWindow(SHWindow* wind) noexcept;
/*-----------------------------------------------------------------------------*/
/* Getters (Temporary) */
/*-----------------------------------------------------------------------------*/
Handle<SHVkLogicalDevice> GetDevice() const { return device; }
Handle<SHVkSwapchain> GetSwapchain() const { return swapchain; }
Handle<SHVkSurface> GetSurface() const { return surface; }
Handle<SHVkPhysicalDevice> GetPhysicalDevice() const {return physicalDevice;}
/*-----------------------------------------------------------------------------*/
/* Getters (Temporary) */
/*-----------------------------------------------------------------------------*/
Handle<SHVkLogicalDevice> GetDevice() const { return device; }
Handle<SHVkSwapchain> GetSwapchain() const { return swapchain; }
Handle<SHVkSurface> GetSurface() const { return surface; }
Handle<SHVkPhysicalDevice> GetPhysicalDevice() const { return physicalDevice; }
Handle<SHVkQueue> GetQueue() const { return graphicsQueue; }
Handle<SHVkDescriptorPool> GetDescriptorPool() const { return descPool; }
SHRenderGraph const& GetRenderGraph (void) const noexcept;
//SHRenderGraph const& GetRenderGraph(void) const noexcept;
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
//Handle<SHVkRenderpass> GetRenderPass() const { return renderPass; }
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Owned Resources
Handle<SHVkPhysicalDevice> physicalDevice;
Handle<SHVkLogicalDevice> device;
Handle<SHVkSurface> surface;
Handle<SHVkSwapchain> swapchain;
Handle<SHVkQueue> graphicsQueue;
Handle<SHVkDescriptorPool> descPool;
//Handle<SHVkRenderpass> renderPass; // Potentially bring out?
std::vector<SHScreenSegment> screenSegments;
SHRenderContext renderContext;
//std::array<Handle<SHVkFramebuffer>, NUM_FRAME_BUFFERS> frameBuffers;
//std::array<Handle<SHVkCommandBuffer>, NUM_FRAME_BUFFERS> commandBuffers;
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Owned Vulkan Resources
Handle<SHVkPhysicalDevice> physicalDevice;
Handle<SHVkLogicalDevice> device;
Handle<SHVkSurface> surface;
Handle<SHVkSwapchain> swapchain;
Handle<SHVkQueue> graphicsQueue;
Handle<SHVkDescriptorPool> descPool;
Handle<SHVkCommandPool> transferCmdPool;
Handle<SHVkCommandBuffer> transferCmdBuffer;
SHRenderContext renderContext;
std::array<Handle<SHVkSemaphore>, 2> graphSemaphores;
// Not Owned Resources
SHWindow* window;
// Renderers
//Handle<SHRenderer> debugWorldRenderer;
//Handle<SHRenderer> debugScreenRenderer;
//std::vector<SHRenderer> renderers;
SHRenderGraph renderGraph;
// Not Owned Resources
SHWindow* window;
friend SHGraphicsSystemRoutine;
};
SHPipelineLibrary pipelineLibrary;
std::vector<SHVkDescriptorSetLayout> globalDescSetLayouts;
// Middle End Resources
ResourceManager resourceManager;
// Viewports
Handle<SHViewport> defaultViewport; // Whole screen
std::vector<Handle<SHViewport>> viewports; // Additional viewports
// Debug Renderers
Handle<SHRenderer> debugWorldRenderer;
Handle<SHRenderer> debugScreenRenderer;
// Temp Cameras
Handle<SHCamera> worldCamera;
Handle<SHCamera> screenCamera;
// Temp renderers
Handle<SHRenderer> worldRenderer;
SHVertexInputState defaultVertexInputState;
/*-----------------------------------------------------------------------------*/
/* Private member functions */
/*-----------------------------------------------------------------------------*/
void ConfigureDefaultVertexInputState (void) noexcept;
};
}

View File

@ -0,0 +1,67 @@
#include "SHpch.h"
#include "SHMaterial.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "SHGraphicsConstants.h"
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Pipeline Functions */
/*---------------------------------------------------------------------------------*/
void SHMaterial::SetPipeline(Handle<SHVkPipeline> _pipeline)
{
pipeline = _pipeline;
// Set up properties based on the pipeline
if (!pipeline)
{
// Clear memory and all that
propMemory.reset();
return;
}
// Allocate memory for properties
propMemorySize = getShaderBlockInterface()->GetBytesRequired();
propMemory.reset(new char[propMemorySize]);
ResetProperties();
}
Handle<SHVkPipeline> SHMaterial::GetPipeline() const
{
return pipeline;
}
/*---------------------------------------------------------------------------------*/
/* Property Functions */
/*---------------------------------------------------------------------------------*/
void SHMaterial::ResetProperties()
{
// Reset all the properties to default values
memset(propMemory.get(), 0, propMemorySize);
}
void SHMaterial::ExportProperties(void* dest) const noexcept
{
memcpy(dest, propMemory.get(), propMemorySize);
}
size_t SHMaterial::GetPropertiesMemorySize() const noexcept
{
return getShaderBlockInterface()->GetBytesRequired();
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterial::getShaderBlockInterface() const noexcept
{
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
(
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
vk::ShaderStageFlagBits::eFragment
);
}
}

View File

@ -0,0 +1,75 @@
/************************************************************************************//*!
\file SHMaterial.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 2022
\brief Contains the class definition of SHMaterial.
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 <unordered_map>
// Project Includes
#include "Resource/Handle.h"
#include "SHCommonTypes.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkPipeline;
class SHShaderBlockInterface;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Describes a Pipeline along with it's associated properties for this instance.
*/
/***********************************************************************************/
class SHMaterial
{
public:
/*-----------------------------------------------------------------------------*/
/* Pipeline Functions */
/*-----------------------------------------------------------------------------*/
void SetPipeline(Handle<SHVkPipeline> _pipeline);
Handle<SHVkPipeline> GetPipeline() const;
/*-----------------------------------------------------------------------------*/
/* Property Functions */
/*-----------------------------------------------------------------------------*/
template<typename T>
void SetProperty(const std::string& key, const T& value);
template<typename T>
T& GetProperty(const std::string& key);
template<typename T>
const T& GetProperty(const std::string& key) const;
void ResetProperties();
void ExportProperties(void* dest) const noexcept;
Byte GetPropertiesMemorySize() const noexcept;
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Handle<SHVkPipeline> pipeline;
std::unique_ptr<char> propMemory;
Byte propMemorySize;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> getShaderBlockInterface() const noexcept;
};
}
#include "SHMaterial.hpp"

View File

@ -0,0 +1,59 @@
/************************************************************************************//*!
\file SHMaterial.hpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 8, 2022
\brief Contains the template function definitions of SHMaterial.
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 "SHMaterial.h"
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Property Functions */
/*---------------------------------------------------------------------------------*/
template<typename T>
void SHMaterial::SetProperty(const std::string& key, const T& value)
{
const auto SHADER_INFO = getShaderBlockInterface();
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
if (PROP_INFO == nullptr)
{
throw std::invalid_argument("Attempted to set an invalid property!");
}
// Get offset and modify the memory directly
T* dataPtr = propMemory.get() + PROP_INFO->offset;
*dataPtr = value;
}
template<typename T>
T& SHMaterial::GetProperty(const std::string& key)
{
const auto SHADER_INFO = getShaderBlockInterface();
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
if (PROP_INFO == nullptr)
{
throw std::invalid_argument("Attempted to set an invalid property!");
}
// Get offset and return the memory directly
T* dataPtr = propMemory.get() + PROP_INFO->offset;
return *dataPtr;
}
template<typename T>
const T& SHMaterial::GetProperty(const std::string& key) const
{
return const_cast<const T&>(const_cast<SHMaterial*>(this)->GetProperty(key));
}
}

View File

@ -0,0 +1,62 @@
/************************************************************************************//*!
\file SHMaterialInstance.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 17, 2022
\brief Contains the definition of functions of SHMaterialInstance.
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 "SHMaterialInstance.h"
#include "Tools/SHLogger.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructor */
/*-----------------------------------------------------------------------------------*/
SHMaterialInstance::SHMaterialInstance(Handle<SHMaterial> material)
: baseMaterial { material }
{}
/*-----------------------------------------------------------------------------------*/
/* Property Functions */
/*-----------------------------------------------------------------------------------*/
void SHMaterialInstance::ResetProperties() noexcept
{
// Reset all the properties to default values
memset(dataStore.get(), 0, dataStoreSize);
overrideData.clear();
dataStore.reset();
}
void SHMaterialInstance::ExportProperties(void* dest) const
{
assert(dataStore != nullptr);
if (!baseMaterial)
throw std::runtime_error("[SHMaterialInstance] Attempted to set export a Material Instance with no base Material!");
// Copy default data from Material
baseMaterial->ExportProperties(dest);
// Follow up with copying our data over
const auto SHADER_INFO = getShaderBlockInterface();
for (const auto& data : overrideData)
{
// Get memory offset to the data
SHShaderBlockInterface::Variable variable = SHADER_INFO->GetVariable(data.Index);
if (variable == nullptr)
{
SHLOG_WARNING("[SHMaterialInstance] Invalid override data indices provided. Skipping.");
continue;
}
const auto DATA_OFFSET = variable->offset;
memcpy_s(dest + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize);
}
}
}

View File

@ -0,0 +1,82 @@
/************************************************************************************//*!
\file SHMaterialInstance.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 17, 2022
\brief Contains the class definition of SHMaterialInstance.
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 <memory>
// Project Includes
#include "Resource/Handle.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHMaterial;
class SHGraphicsSystem;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Describes an instance of a SHMaterial that can be used to describe how to render
a SHRenderable.
*/
/***********************************************************************************/
class SHMaterialInstance
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
struct OverrideData
{
size_t Index;
size_t DataSize;
size_t StoredDataOffset;
};
/*-----------------------------------------------------------------------------*/
/* Constructor */
/*-----------------------------------------------------------------------------*/
SHMaterialInstance(Handle<SHMaterial> material = {});
/*-----------------------------------------------------------------------------*/
/* Property Functions */
/*-----------------------------------------------------------------------------*/
template<typename T>
void SetProperty(const std::string& key, const T& value);
template<typename T>
T& GetProperty(const std::string& key);
template<typename T>
const T& GetProperty(const std::string& key) const;
void ResetProperties() noexcept;
void ExportProperties(void* dest) const;
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHMaterial> GetBaseMaterial() const { return baseMaterial; }
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Handle<SHMaterial> baseMaterial;
std::vector<OverrideData> overrideData;
std::unique_ptr<char> dataStore;
size_t dataStoreSize = 0;
};
}
#include "SHMaterialInstance.hpp"

View File

@ -0,0 +1,85 @@
/************************************************************************************//*!
\file SHMaterialInstance.hpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 17, 2022
\brief Contains the definition of functions templates of SHMaterialInstance.
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 "SHMaterialInstance.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Property Functions */
/*---------------------------------------------------------------------------------*/
template<typename T>
void SHMaterialInstance::SetProperty(const std::string& key, const T& value)
{
const auto SHADER_INFO = getShaderBlockInterface();
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
if (PROP_INFO == nullptr)
{
throw std::invalid_argument("Attempted to set an invalid property!");
}
// Allocate data store if it was empty
if (dataStore == nullptr)
{
dataStoreSize = SHADER_INFO->GetBytesRequired();dataStoreSize
dataStore.reset(new char[dataStoreSize]);
}
OverrideData od;
od.Index = SHADER_INFO.GetVariableIndex(key);
od.DataSize = sizeof(T);
if (overrideData.empty())
{
od.StoredDataOffset = 0;
}
else
{
const OverrideData& lastInsertedData = overrideData.back();
od.StoredDataOffset = lastInsertedData.StoredDataOffset + lastInsertedData.DataSize;
}
// Get offset and modify the memory directly
T* dataPtr = dataStore.get() + od.StoredDataOffset;
*dataPtr = value;
// Save the override data information
overrideData.emplace_back(std::move(od));
}
template<typename T>
T& SHMaterialInstance::GetProperty(const std::string& key)
{
const auto SHADER_INFO = getShaderBlockInterface();
const auto PROP_INFO = SHADER_INFO->GetVariable(key);
if (PROP_INFO == nullptr)
{
throw std::invalid_argument("Attempted to get an invalid property!");
}
// Search Override Data for the property
uint32_t PROP_IDX = SHADER_INFO.GetVariableIndex(key);
auto prop = std::find(overrideData.begin(), overrideData.end(), [&](const OverrideData& data)
{
return PROP_IDX == data.Index;
});
if (prop == overrideData.end())
throw std::invalid_argument("Attempted to get an property that was not set previously!");
// Get offset and return the memory directly
T* dataPtr = dataStore.get() + prop->StoredDataOffset;
return *dataPtr;
}
template<typename T>
const T& SHMaterialInstance::GetProperty(const std::string& key) const
{
return const_cast<const T&>(const_cast<SHMaterialInstance*>(this)->GetProperty(key));
}
}

View File

@ -0,0 +1,201 @@
/************************************************************************************//*!
\file SHMeshLibrary.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 2022
\brief Contains definitions for all of the functions of the classes that deal
with storage and management of vertex and index buffers of meshes.
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 "SHMeshLibrary.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
#include "../../SHVkUtil.h"
namespace SHADE
{
SHADE::Handle<SHADE::SHMesh> SHMeshLibrary::AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices)
{
isDirty = true;
auto handle = meshes.Create();
meshAddJobs.emplace_back( MeshAddJob
{
vertexCount,
positions,
texCoords,
tangents,
normals,
indexCount,
indices,
handle
});
return handle;
}
void SHMeshLibrary::RemoveMesh(Handle<SHMesh> mesh)
{
if (!mesh)
throw std::invalid_argument("Attempted to remove a Mesh that did not belong to the Mesh Library!");
meshRemoveJobs.emplace_back(mesh);
isDirty = true;
}
void SHMeshLibrary::BuildBuffers(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer)
{
// No changes
if (!isDirty)
return;
// Remove
if (!meshRemoveJobs.empty())
{
// - Remove from order list
for (const auto& meshToRemove : meshRemoveJobs)
{
auto searchResult = std::find(meshOrder.begin(), meshOrder.end(), meshToRemove);
// Shouldn't happen, ignore
if (searchResult == meshOrder.end())
continue;
// Remove from mesh list
meshOrder.erase(searchResult);
}
meshRemoveJobs.clear();
// - Shift existing elements in to close up the gaps
int32_t nextVertInsertPoint = 0;
uint32_t nextIdxInsertPoint = 0;
for (auto& mesh : meshOrder)
{
// Check if already in the correct place
if (nextVertInsertPoint != mesh->FirstVertex)
{
/* There's a gap, we need to shift */
// Vertices
vertPosStorage.erase(vertPosStorage.begin() + nextVertInsertPoint, vertPosStorage.begin() + mesh->FirstVertex);
vertTexCoordStorage.erase(vertTexCoordStorage.begin() + nextVertInsertPoint, vertTexCoordStorage.begin() + mesh->FirstVertex);
vertTangentStorage.erase(vertTangentStorage.begin() + nextVertInsertPoint, vertTangentStorage.begin() + mesh->FirstVertex);
vertNormalStorage.erase(vertNormalStorage.begin() + nextVertInsertPoint, vertNormalStorage.begin() + mesh->FirstVertex);
// - Update mesh data
mesh->FirstVertex = nextVertInsertPoint;
// Indices
indexStorage.erase(indexStorage.begin() + nextIdxInsertPoint, indexStorage.begin() + mesh->FirstIndex);
// - Update mesh data
mesh->FirstIndex = nextIdxInsertPoint;
// Prepare for next
nextVertInsertPoint += mesh->VertexCount;
nextIdxInsertPoint += mesh->IndexCount;
}
}
}
// Add
if (!meshAddJobs.empty())
{
// - Compute updated size
size_t newVertElems = vertPosStorage.size();
size_t newIdxElems = indexStorage.size();
for (const auto& addJob : meshAddJobs)
{
newVertElems += addJob.VertexCount;
newIdxElems += addJob.IndexCount;
}
// - Reserve new memory
vertPosStorage .reserve(newVertElems);
vertTexCoordStorage.reserve(newVertElems);
vertTangentStorage .reserve(newVertElems);
vertNormalStorage .reserve(newVertElems);
indexStorage .reserve(newIdxElems);
// - Append new data
for (auto& addJob : meshAddJobs)
{
// Update handle
SHMesh& meshData = *addJob.Handle;
meshData = SHMesh
{
.FirstVertex = static_cast<int32_t>(vertPosStorage.size()),
.VertexCount = static_cast<uint32_t>(addJob.VertexCount),
.FirstIndex = static_cast<uint32_t>(indexStorage.size()),
.IndexCount = static_cast<uint32_t>(addJob.IndexCount),
};
// Copy into storage
vertPosStorage.insert
(
vertPosStorage.end(),
addJob.VertexPositions, addJob.VertexPositions + addJob.VertexCount
);
vertTexCoordStorage.insert
(
vertTexCoordStorage.end(),
addJob.VertexTexCoords, addJob.VertexTexCoords + addJob.VertexCount
);
vertTangentStorage.insert
(
vertTangentStorage.end(),
addJob.VertexTangents, addJob.VertexTangents + addJob.VertexCount
);
vertNormalStorage.insert
(
vertNormalStorage.end(),
addJob.VertexNormals, addJob.VertexNormals + addJob.VertexCount
);
indexStorage.insert
(
indexStorage.end(),
addJob.Indices, addJob.Indices + addJob.IndexCount
);
}
meshAddJobs.clear();
}
// Send to GPU
using BuffUsage = vk::BufferUsageFlagBits;
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertPosBuffer,
vertPosStorage.data(),
static_cast<uint32_t>(vertPosStorage.size()) * sizeof(SHMesh::VertexPosition),
BuffUsage::eVertexBuffer
);
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertTexCoordBuffer,
vertTexCoordStorage.data(),
static_cast<uint32_t>(vertTexCoordStorage.size()) * sizeof(SHMesh::VertexTexCoord),
BuffUsage::eVertexBuffer
);
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertTangentBuffer,
vertTangentStorage.data(),
static_cast<uint32_t>(vertTangentStorage.size()) * sizeof(SHMesh::VertexTangent),
BuffUsage::eVertexBuffer
);
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, vertNormalBuffer,
vertNormalStorage.data(),
static_cast<uint32_t>(vertNormalStorage.size()) * sizeof(SHMesh::VertexNormal),
BuffUsage::eVertexBuffer
);
SHVkUtil::EnsureBufferAndCopyData
(
device, cmdBuffer, indexBuffer,
indexStorage.data(),
static_cast<uint32_t>(indexStorage.size()) * sizeof(SHMesh::Index),
BuffUsage::eIndexBuffer
);
isDirty = false;
}
}

View File

@ -0,0 +1,187 @@
/************************************************************************************//*!
\file SHMeshLibrary.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 2022
\brief Contains definitions for all of the classes that deal with storage and
management of vertex and index buffers of meshes.
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 "Resource/Handle.h"
#include "Resource/ResourceLibrary.h"
#include "SHVertex.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkBuffer;
class SHVkLogicalDevice;
class SHVkCommandBuffer;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Represents a single mesh that is stored in a SHMeshLibrary.
*/
/***********************************************************************************/
class SHMesh
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
using Index = uint32_t;
using VertexPosition = SHMathVec3f;
using VertexTexCoord = SHMathVec2f;
using VertexTangent = SHMathVec3f;
using VertexNormal = SHMathVec3f;
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
int32_t FirstVertex;
uint32_t VertexCount;
uint32_t FirstIndex;
uint32_t IndexCount;
};
/***********************************************************************************/
/*!
\brief
Manages storage for all Meshes in the Graphics System as a single set of Vertex
and Index Buffers.
*/
/***********************************************************************************/
class SHMeshLibrary
{
public:
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/*******************************************************************************/
/*!
\brief
Adds a mesh to the Mesh Library. But this does not mean that the meshes have
been added yet. A call to "BuildBuffers()" is required to transfer all
meshes into the GPU.
\param vertexCount
Number of vertices in this Mesh.
\param positions
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
positions.
\param texCoords
Pointer to the first in a contiguous array of SHMathVec2s that define vertex
texture coordinates.
\param tangents
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
tangents.
\param normals
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
normals.
\param indexCount
Number of indices in this mesh.
\param indices
Pointer to the first in a contiguous array of uint32_ts that define mesh
indicies.
\return
Handle to the created Mesh. This is not valid to be used until a call to
BuildBuffers().
*/
/*******************************************************************************/
Handle<SHMesh> AddMesh(uint32_t vertexCount, const SHMesh::VertexPosition* const positions, const SHMesh::VertexTexCoord* const texCoords, const const SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices);
/*******************************************************************************/
/*!
\brief
Removes a mesh from the MeshLibrary. But this does not mean that the meshes
have been removed yet. A call to "BuildBuffers()" is required to finalise all
changes.
\param mesh
Handle to the mesh to remove.
*/
/*******************************************************************************/
void RemoveMesh(Handle<SHMesh> mesh);
/***************************************************************************/
/*!
\brief
Finalises all changes to the MeshLibrary into the GPU buffers.
\param device
Device used to create and update the 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 BuildBuffers(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer);
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHVkBuffer> GetVertexPositionsBuffer() const noexcept { return vertPosBuffer; }
Handle<SHVkBuffer> GetVertexTexCoordsBuffer() const noexcept { return vertTexCoordBuffer; }
Handle<SHVkBuffer> GetVertexTangentsBuffer() const noexcept { return vertTangentBuffer; }
Handle<SHVkBuffer> GetVertexNormalsBuffer() const noexcept { return vertNormalBuffer; }
Handle<SHVkBuffer> GetIndexBuffer() const { return indexBuffer; }
private:
/*-----------------------------------------------------------------------------*/
/* Type Definition */
/*-----------------------------------------------------------------------------*/
struct MeshAddJob
{
uint32_t VertexCount = 0;
const SHMesh::VertexPosition* VertexPositions = nullptr;
const SHMesh::VertexTexCoord* VertexTexCoords = nullptr;
const SHMesh::VertexTangent * VertexTangents = nullptr;
const SHMesh::VertexNormal * VertexNormals = nullptr;
uint32_t IndexCount = 0;
const SHMesh::Index * Indices = nullptr;
Handle<SHMesh> Handle;
};
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Manipulation Queues
std::vector<MeshAddJob> meshAddJobs;
std::vector<Handle<SHMesh>> meshRemoveJobs;
// Tracking
ResourceLibrary<SHMesh> meshes{};
std::vector<Handle<SHMesh>> meshOrder;
// CPU Storage
std::vector<SHMesh::VertexPosition> vertPosStorage;
std::vector<SHMesh::VertexTexCoord> vertTexCoordStorage;
std::vector<SHMesh::VertexTangent> vertTangentStorage;
std::vector<SHMesh::VertexNormal> vertNormalStorage;
std::vector<SHMesh::Index> indexStorage;
// GPU Storage
Handle<SHVkBuffer> vertPosBuffer{};
Handle<SHVkBuffer> vertTexCoordBuffer{};
Handle<SHVkBuffer> vertTangentBuffer{};
Handle<SHVkBuffer> vertNormalBuffer{};
Handle<SHVkBuffer> indexBuffer {};
// Flags
bool isDirty = true;
};
}

View File

@ -1,2 +1,2 @@
#include "SHPch.h"
#include "SHpch.h"
#include "SHRenderTarget.h"

View File

@ -0,0 +1,49 @@
/************************************************************************************//*!
\file SHRenderable.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 19, 2022
\brief Contains the definition of functions of the SHRenderable Component 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 "SHRenderable.h"
#include "ECS_Base/Managers/SHSystemManager.h"
namespace SHADE
{
void SHRenderable::SetMaterial(Handle<SHMaterialInstance> materialInstance)
{
if (material)
{
material.Free();
material = {};
}
sharedMaterial = materialInstance;
}
Handle<SHMaterialInstance> SHRenderable::GetMaterial() const
{
if (material)
return material;
return sharedMaterial;
}
Handle<SHMaterialInstance> SHRenderable::GetModifiableMaterial()
{
// Create a copy if it wasn't created
if (!material)
{
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
material = gfxSystem->AddMaterialInstance(sharedMaterial->GetBaseMaterial());
}
return material;
}
}

View File

@ -0,0 +1,60 @@
/************************************************************************************//*!
\file SHRenderable.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 19, 2022
\brief Contains the definition of the SHRenderable Component 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
// Project Includes
#include "Resource/Handle.h"
//#include "SHTransform.h"
#include "ECS_Base/Components/SHComponent.h"
#include "Math/SHMatrix.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHMaterialInstance;
class SHMesh;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*************************************************************************************/
/*!
\brief
Represents an object that should be rendered.
*/
/*************************************************************************************/
class SHRenderable : public SHComponent, public ISelfHandle<SHRenderable>
{
public:
/*-------------------------------------------------------------------------------*/
/* Usage Functions */
/*-------------------------------------------------------------------------------*/
void SetMaterial(Handle<SHMaterialInstance> materialInstance);
Handle<SHMaterialInstance> GetMaterial() const;
Handle<SHMaterialInstance> GetModifiableMaterial();
/*-------------------------------------------------------------------------------*/
/* Data Members */
/*-------------------------------------------------------------------------------*/
Handle<SHMesh> Mesh;
SHMatrix TransformMatrix; // TODO: Replace with Transform component
private:
/*-------------------------------------------------------------------------------*/
/* Data Members */
/*-------------------------------------------------------------------------------*/
Handle<SHMaterialInstance> sharedMaterial;
Handle<SHMaterialInstance> material;
};
}

View File

@ -0,0 +1,57 @@
/************************************************************************************//*!
\file SHRenderer.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 21, 2022
\brief
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 "SHRenderer.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "SHViewport.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "SHMaterial.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
SHRenderer::SHRenderer(Handle<SHViewport> viewport, ResourceManager& resourceManager)
: renderGraph{resourceManager.Create<SHRenderGraph> ()}
{
}
SHRenderer::~SHRenderer()
{
}
/*-----------------------------------------------------------------------------*/
/* Camera Registration */
/*-----------------------------------------------------------------------------*/
void SHRenderer::SetCamera(Handle<SHCamera> _camera)
{
camera = _camera;
}
/*---------------------------------------------------------------------------------*/
/* Drawing Functions */
/*---------------------------------------------------------------------------------*/
void SHRenderer::Draw(uint32_t frameIndex) const noexcept
{
renderGraph->Execute(frameIndex);
}
Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept
{
return renderGraph;
}
}

View File

@ -0,0 +1,81 @@
/************************************************************************************//*!
\file SHRenderer.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 21, 2022
\brief
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 <array>
// Project Includes
#include "SHCamera.h"
#include "Resource/Handle.h"
#include "SHGraphicsConstants.h"
#include "Graphics/RenderGraph/SHRenderGraph.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkBuffer;
class SHVkRenderpass;
class SHVkFramebuffer;
class SHMaterial;
class SHVkLogicalDevice;
class SHViewport;
class SHVkImageView;
class SHVkCommandBuffer;
class SHCamera;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Brings together a set of Cameras and objects with various Pipelines to render
them as part of a set. Multiple Renderers can exist to render objects differently
in a separate step.
*/
/***********************************************************************************/
class SHRenderer
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHRenderer(Handle<SHViewport> viewport, ResourceManager& resourceManager);
~SHRenderer();
/*-----------------------------------------------------------------------------*/
/* Camera Registration */
/*-----------------------------------------------------------------------------*/
void SetCamera(Handle<SHCamera> _camera);
/*-----------------------------------------------------------------------------*/
/* Drawing Functions */
/*-----------------------------------------------------------------------------*/
void Draw(uint32_t frameIndex) const noexcept;
/*-----------------------------------------------------------------------------*/
/* Setters and Getters */
/*-----------------------------------------------------------------------------*/
Handle<SHRenderGraph> GetRenderGraph (void) const noexcept;
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Handle<SHCamera> camera;
Handle<SHRenderGraph> renderGraph;
};
}

View File

@ -0,0 +1,74 @@
/************************************************************************************//*!
\file SHViewport.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 27, 2022
\brief
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 "SHViewport.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
#include "Graphics/Instance/SHVkInstance.h"
#include "Tools/SHLogger.h"
#include "SHRenderer.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
SHViewport::SHViewport(Handle<SHVkLogicalDevice> device, const vk::Viewport& viewport)
: device { device }
, viewport { viewport }
{}
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
void SHViewport::SetUp(Handle<SHVkCommandBuffer> commandBuffer)
{
commandBuffer->SetViewportScissor
(
viewport.x,
viewport.y,
static_cast<int32_t>(viewport.width),
static_cast<int32_t>(viewport.height),
viewport.minDepth,
viewport.maxDepth
);
}
/*---------------------------------------------------------------------------------*/
/* Renderer Registration Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHRenderer> SHViewport::AddRenderer(ResourceManager& resourceManager)
{
// Create the renderer
auto renderer = SHVkInstance::GetResourceManager().Create<SHRenderer>(GetHandle(), resourceManager);
// Store
renderers.emplace_back(renderer);
// Return
return renderer;
}
void SHViewport::RemoveRenderer(Handle<SHRenderer> renderer)
{
auto iter = std::find(renderers.begin(), renderers.end(), renderer);
if (iter == renderers.end())
{
SHLOG_WARNING("Attempted to remove a Renderer that does not belong to a viewport!");
return;
}
// Remove it
iter->Free();
renderers.erase(iter);
}
}

View File

@ -0,0 +1,81 @@
/************************************************************************************//*!
\file SHViewport.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 27, 2022
\brief Contains the class definition of SHViewport.
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>
// External Dependencies
#include "Graphics/SHVulkanIncludes.h"
// Project Includes
#include "Resource/Handle.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHRenderer;
class SHVkCommandBuffer;
class SHVkLogicalDevice;
class SHVkImageView;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Brings together a set of Renderers that render to the same segment of an image.
*/
/***********************************************************************************/
class SHViewport : public ISelfHandle<SHViewport>
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHViewport(Handle<SHVkLogicalDevice> device, const vk::Viewport& viewport);
/*-----------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*-----------------------------------------------------------------------------*/
void SetUp(Handle<SHVkCommandBuffer> commandBuffer);
/*-----------------------------------------------------------------------------*/
/* Renderers Registration Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHRenderer> AddRenderer(ResourceManager& resourceManager);
void RemoveRenderer(Handle<SHRenderer> renderer);
/*-----------------------------------------------------------------------------*/
/* Getters */
/*-----------------------------------------------------------------------------*/
float GetX() const { return viewport.x; }
float GetY() const { return viewport.y; }
float GetWidth() const { return viewport.width; }
float GetHeight() const { return viewport.height; }
float GetMinDepth() const { return viewport.minDepth; }
float GetMaxDepth() const { return viewport.maxDepth; }
const std::vector<Handle<SHRenderer>>& GetRenderers() const { return renderers; }
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Handle<SHVkLogicalDevice> device;
vk::Viewport viewport;
std::vector<Handle<SHRenderer>> renderers;
};
}

View File

@ -0,0 +1,52 @@
#include "SHpch.h"
#include "SHPipelineLibrary.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
namespace SHADE
{
Handle<SHVkPipeline> SHPipelineLibrary::CreateDrawPipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, uint32_t subpass, SHVertexInputState const& vertexInput, std::vector<Handle<SHVkDescriptorSetLayout>> const& globalDescSetLayouts) noexcept
{
SHPipelineLayoutParams params
{
.shaderModules = {vsFsPair.first, vsFsPair.second},
.globalDescSetLayouts = globalDescSetLayouts
};
// Create the pipeline layout
auto pipelineLayout = logicalDevice->CreatePipelineLayout(params);
// Create the pipeline and configure the default vertex input state
auto newPipeline = logicalDevice->CreatePipeline(pipelineLayout, nullptr, renderpass, subpass, SH_PIPELINE_TYPE::GRAPHICS);
newPipeline->GetPipelineState().SetVertexInputState(vertexInput);
// Actually construct the pipeline
newPipeline->ConstructPipeline();
// Emplace the new pipeline
pipelines.emplace (vsFsPair, newPipeline);
}
void SHPipelineLibrary::Init(Handle<SHVkLogicalDevice> device, SHVertexInputState const* viState, std::vector<Handle<SHVkDescriptorSetLayout>> const* globalLayouts) noexcept
{
logicalDevice = device;
vertexInputState = viState;
globalDescSetLayouts = globalLayouts;
}
Handle<SHVkPipeline> SHPipelineLibrary::GetDrawPipline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
{
// return the pipeline requested for
if (pipelines.contains(vsFsPair))
return pipelines.at(vsFsPair);
else
return {};
}
bool SHPipelineLibrary::CheckDrawPipelineExistence(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept
{
// Returns if a pipeline exists or not
return pipelines.contains(vsFsPair);
}
}

View File

@ -0,0 +1,57 @@
#pragma once
#include <unordered_map>
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
namespace SHADE
{
class SHVRenderpass;
class SHVkDescriptorSetLayouts;
class SHVkPipeline;
// Pipeline library is a PURELY MIDDLE END SYSTEM. It is responsible for only creating pipelines from shaders and caching
// them so that they don't need to be recreated again.
class SHPipelineLibrary
{
private:
// TOOD: Move this somewhere eventually. Can use for other things
struct SHHandlePairHash
{
template <typename T1, typename T2>
std::size_t operator() (std::pair<T1, T2> const& pair) const
{
return std::hash<T1>()(pair.first.GetId()) ^ std::hash<T2>()(pair.second.GetId());
}
};
//! Logical Device required for creation of pipelines
Handle<SHVkLogicalDevice> logicalDevice;
//! 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>, SHHandlePairHash> pipelines;
//! Default vertex input state for pipeline creation
SHVertexInputState const* vertexInputState;
std::vector<Handle<SHVkDescriptorSetLayout>> const* globalDescSetLayouts;
public:
void Init (Handle<SHVkLogicalDevice> device, SHVertexInputState const* viState, std::vector<Handle<SHVkDescriptorSetLayout>> const* globalLayouts) noexcept;
// Draw pipeline functions. used only when creating pipelines for drawing using a vertex and fragment shader
Handle<SHVkPipeline> CreateDrawPipeline (
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
Handle<SHVkRenderpass> renderpass,
uint32_t subpass,
SHVertexInputState const& vertexInput,
std::vector<Handle<SHVkDescriptorSetLayout>> const& globalDescSetLayouts
) noexcept;
Handle<SHVkPipeline> GetDrawPipline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
bool CheckDrawPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
};
}

View File

@ -23,7 +23,7 @@ namespace SHADE
//! used just for textures or lights for example). In that case, we still
//! want to use the layout to initialize the pipeline layout but we do not
//! want to use it for allocating descriptor sets.
std::vector<Handle<SHVkDescriptorSetLayout>> globalDescSetLayouts = {};
std::vector<Handle<SHVkDescriptorSetLayout>> const& globalDescSetLayouts = {};
};
}

View File

@ -189,7 +189,7 @@ namespace SHADE
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
template <typename T, typename = std::enable_if_t <std::is_same_v<std::remove_reference_t<T>, SHVertexInputState>>>
template <typename T, typename = std::enable_if_t <std::is_same_v<std::decay_t<T>, SHVertexInputState>>>
void SetVertexInputState (T&& state) noexcept;
void SetInputAssemblyState(SHInputAssemblyState const& state) noexcept;
void SetRasterizationState(SHRasterizationState const& state) noexcept;

View File

@ -1035,7 +1035,7 @@ namespace SHADE
auto& cmdBuffer = commandBuffers[frameIndex];
cmdBuffer->BeginRecording();
cmdBuffer->SetviewportScissor(1920.0f, 1080.0f, 1920, 1080);
cmdBuffer->SetViewportScissor(1920.0f, 1080.0f, 1920, 1080);
for (auto& node : nodes)
{

View File

@ -6,30 +6,49 @@ namespace SHADE
void SHShaderBlockInterface::AddVariable(std::string name, Variable&& newVariable) noexcept
{
variables.try_emplace (std::move(name), std::move (newVariable));
// Check if this is already inside
if (variableIndexing.contains(name))
{
SHLOG_WARNING("[SHShaderBlockInterface] Attempted to specify a variable with a duplicate name. This will be ignored.");
return;
}
variableIndexing.emplace_back(std::move(newVariable));
variables.try_emplace (std::move(name), static_cast<uint32_t>(variableIndexing.size() - 1));
}
SHShaderBlockInterface::Variable const* const SHShaderBlockInterface::GetVariable(std::string const& variableName) const noexcept
{
if (variables.contains(variableName))
return &variables.at(variableName);
if (variableIndexing.contains(variableName))
return &variables.at(variableIndexing.at(variableName).second);
return nullptr;
}
SHShaderBlockInterface::SHShaderBlockInterface(void) noexcept
: variables{}
, bytesRequired{ 0 }
SHADE::SHShaderBlockInterface::Variable const* const SHShaderBlockInterface::GetVariable(uint32_t index) const noexcept
{
if (variableIndexing.size() < index)
return &variables.at(index);
return nullptr;
}
uint32_t SHShaderBlockInterface::GetVariableIndex(std::string const& variableName) const noexcept
{
if (!variableIndexing.contains(variableName))
throw std::invalid_argument("Attempted to retrieve index to variable that does not exist!");
return variableIndexing.at(variableName).second;
}
SHShaderBlockInterface::SHShaderBlockInterface(void) noexcept
: bytesRequired{ 0 }
{}
SHShaderBlockInterface::SHShaderBlockInterface(SHShaderBlockInterface&& rhs) noexcept
: variables{ std::move(rhs.variables) }
, bytesRequired {std::move (rhs.bytesRequired)}
{
}
: variables { std::move(rhs.variables) }
, variableIndexing { std::move(rhs.variableIndexing) }
, bytesRequired { std::move (rhs.bytesRequired) }
{}
void SHShaderBlockInterface::SetBytesRequired(uint32_t bytes) noexcept
{
@ -46,16 +65,11 @@ namespace SHADE
{
if (&rhs == this)
return *this;
variables = std::move(rhs.variables);
variableIndexing = std::move(rhs.variableIndexing);
bytesRequired = std::move(rhs.bytesRequired);
return *this;
}
SHShaderBlockInterface::~SHShaderBlockInterface(void) noexcept
{
variables.clear();
}
}

View File

@ -15,8 +15,9 @@ namespace SHADE
};
private:
//! container of variable information
std::unordered_map<std::string, Variable> variables;
//! containers of variable information
std::vector<Variable> variables;
std::unordered_map<std::string, uint32_t> variableIndexing;
//! bytes required by the block (includes padding). This variable is required
uint32_t bytesRequired;
@ -24,12 +25,13 @@ namespace SHADE
public:
void AddVariable (std::string name, Variable&& newVariable) noexcept;
Variable const* const GetVariable (std::string const& variableName) const noexcept;
Variable const* const GetVariable(uint32_t index) const noexcept;
uint32_t GetVariableIndex(std::string const& variableName) const;
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHShaderBlockInterface(void) noexcept;
~SHShaderBlockInterface(void) noexcept;
SHShaderBlockInterface(SHShaderBlockInterface&& rhs) noexcept;
SHShaderBlockInterface& operator=(SHShaderBlockInterface&& rhs) noexcept;