Merge pull request #37 from SHADE-DP/SP3-1-Rendering

This commit is contained in:
XiaoQiDigipen 2022-09-21 19:54:13 +08:00 committed by GitHub
commit de983cdc66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
82 changed files with 4711 additions and 608 deletions

View File

@ -2,9 +2,9 @@
#include "SBApplication.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#define SHEDITOR
//#define SHEDITOR
#ifdef SHEDITOR
//#include "Editor/SHEditor.h"
#include "Editor/SHEditor.h"
//#include "Scenes/SBEditorScene.h"
#endif // SHEDITOR
@ -14,9 +14,18 @@
#include <chrono>
#include <ratio>
#include <ctime>
#define SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN 1
#include <SDL.h>
#include "Scripting/SHScriptEngine.h"
#include "Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h"
#include "Scenes/SBTestScene.h"
using namespace SHADE;
namespace Sandbox
{
@ -32,56 +41,72 @@ namespace Sandbox
// Set working directory
SHADE::SHFileUtilities::SetWorkDirToExecDir();
SDL_Init(SDL_INIT_VIDEO);
SDL_Init(SDL_INIT_EVERYTHING);
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
SHADE::SHSystemManager::CreateSystem<SHADE::SHGraphicsSystem>();
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::SHGraphicsSystemRoutine>(1);
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BatcherDispatcherRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::EndRoutine>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>();
graphicsSystem->SetWindow(&window);
SDL_CreateWindowFrom(window.GetHWND());
sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
//auto [w, h] = window.GetWindowSize();
//SDL_SetWindowSize(sdlWindow, w, h);
SHADE::SHSystemManager::Init();
#ifdef SHEDITOR
//SHADE::SHEditor::Initialize(window.GetHWND());
SHADE::SHEditor::Initialise(sdlWindow);
#else
#endif
// Set up scripting
SHADE::SHScriptEngine::Init();
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
}
void SBApplication::Update(void)
{
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
//TODO: Change true to window is open
while (!window.WindowShouldClose())
{
SHSceneManager::UpdateSceneManager();
SHSceneManager::SceneUpdate(1/60.0f);
//#ifdef SHEDITOR
//SHADE::SHEditor::PreRender();
//#endif
graphicsSystem->BeginRender();
graphicsSystem->Run(1.0f);
//#ifdef SHEDITOR
//SHADE::SHEditor::PreRender();
//SHADE::SHEditor::Update();
#ifdef SHEDITOR
SHADE::SHEditor::PreRender();
//SHADE::SHEditor::Render();
//#endif
#endif
#ifdef SHEDITOR
SHADE::SHEditor::Render();
#endif
graphicsSystem->Run(1.0f);
graphicsSystem->EndRender();
}
SHADE::SHSystemManager::RunRoutines(false, 0.016f);
}
}
void SBApplication::Exit(void)
{
#ifdef SHEDITOR
SHADE::SHEditor::Exit();
#endif
SHSceneManager::Exit();
SHADE::SHScriptEngine::Exit();
SHADE::SHSystemManager::Exit();
SDL_DestroyWindow(sdlWindow);
#ifdef SHEDITOR
#else
#endif
SDL_Quit();
}
}

View File

@ -1,6 +1,13 @@
#include "SBpch.h"
#include "SBTestScene.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
using namespace SHADE;
namespace Sandbox
@ -21,7 +28,20 @@ namespace Sandbox
}
void SBTestScene::Init()
{
SHADE::SHGraphicsSystem* graphicsSystem = static_cast<SHADE::SHGraphicsSystem*>(SHADE::SHSystemManager::GetSystem<SHADE::SHGraphicsSystem>());
// Create temp meshes
const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem);
graphicsSystem->BuildMeshBuffers();
// Create Materials
auto matInst = graphicsSystem->AddMaterialInstance();
// Create entity and add mesh
auto entity = SHADE::SHEntityManager::CreateEntity<SHADE::SHRenderable>();
auto& renderable = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHRenderable>(entity);
renderable.Mesh = CUBE_MESH;
renderable.SetMaterial(matInst);
renderable.TransformMatrix.Translate(0.0f, 0.0f, 2.0f);
}
void SBTestScene::Update(float dt)
{

View File

@ -22,6 +22,8 @@
#include <cassert>
#include <iostream>
#include "SH_API.h"
namespace SHADE
{
enum class OWNERSHIP_TYPE
@ -34,7 +36,7 @@ namespace SHADE
//template<OWNERSHIP_TYPE ownership>
class SHComponentGroup
class SH_API SHComponentGroup
{
public:

View File

@ -11,13 +11,14 @@
#pragma once
#include "../SHECSMacros.h"
#include "SH_API.h"
namespace SHADE
{
class SHSystemManager;
class SHSystem
class SH_API SHSystem
{
private:
SystemID systemID;

View File

@ -7,6 +7,7 @@
#include "SHRoutineStats.h"
#include "SHSystem.h"
#include <string>
#include "SH_API.h"
namespace SHADE
@ -15,7 +16,7 @@ namespace SHADE
class SHSystemManager;
class SHSystemRoutine
class SH_API SHSystemRoutine
{
friend class SHSystemManager;
protected:

View File

@ -0,0 +1,112 @@
#include "SHpch.h"
#include "SHEditor.h"
#include <imgui.h>
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/Instance/SHVkInstance.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
//IMGUI Backend includes
#include <backends/imgui_impl_sdl.h>
#include <backends/imgui_impl_vulkan.h>
namespace SHADE
{
Handle<SHVkCommandPool> SHEditor::imguiCommandPool;
Handle<SHVkCommandBuffer> SHEditor::imguiCommandBuffer;
void SHEditor::Initialise(SDL_Window* sdlWindow)
{
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
ImGui_ImplSDL2_InitForVulkan(sdlWindow);
auto* gfxSystem = reinterpret_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
ImGui_ImplVulkan_InitInfo initInfo{};
initInfo.Instance = SHVkInstance::GetVkInstance();
initInfo.PhysicalDevice = gfxSystem->GetPhysicalDevice()->GetVkPhysicalDevice();
initInfo.Device = gfxSystem->GetDevice()->GetVkLogicalDevice();
initInfo.Queue = gfxSystem->GetQueue()->GetVkQueue();
initInfo.DescriptorPool = gfxSystem->GetDescriptorPool()->GetVkHandle();
initInfo.MinImageCount = initInfo.ImageCount = gfxSystem->GetSwapchain()->GetNumImages();
initInfo.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
imguiCommandPool = gfxSystem->GetDevice()->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
imguiCommandBuffer = imguiCommandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
/*auto renderPass = gfxSystem->GetRenderGraph().GetNode("ImGui Node")->GetRenderpass();
ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass());*/
imguiCommandBuffer->BeginRecording();
ImGui_ImplVulkan_CreateFontsTexture(imguiCommandBuffer->GetVkCommandBuffer());
imguiCommandBuffer->EndRecording();
gfxSystem->GetQueue()->SubmitCommandBuffer({imguiCommandBuffer}, {}, {}, vk::PipelineStageFlagBits::eNone, {});
ImGui_ImplVulkan_DestroyFontUploadObjects();
/*gfxSystem->GetRenderGraph().GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd) {
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
});*/
//ImGuiIO& io = ImGui::GetIO();
//int w, h;
//SDL_GetWindowSize(sdlWindow, &w, &h);
//io.DisplaySize = { static_cast<float>(w),static_cast<float>(h)};
}
void SHEditor::PreRender()
{
NewFrame();
ImGui::ShowDemoWindow();
ImGui::Begin("Your mom");
if (ImGui::Button("OP"))
{
std::cout << "HEHEHEOHEIOHIEOH\n";
}
ImGui::End();
}
void SHEditor::Render()
{
ImGui::Render();
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
}
void SHEditor::Exit()
{
ImGui_ImplVulkan_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
}
void SHEditor::InitBackend()
{
}
void SHEditor::NewFrame()
{
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
}
void SHEditor::EndFrame()
{
}
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "SH_API.h"
#include <SDL.h>
#include "Resource/Handle.h"
namespace SHADE
{
class SHVkCommandBuffer;
class SHVkCommandPool;
class SH_API SHEditor
{
public:
static void Initialise(SDL_Window* sdlWindow);
static void PreRender();
static void Render();
static void Exit();
private:
static void InitBackend();
static void NewFrame();
static void EndFrame();
static Handle<SHVkCommandPool> imguiCommandPool;
static Handle<SHVkCommandBuffer> imguiCommandBuffer;
};
}

View File

@ -33,8 +33,20 @@ namespace SHADE
};
cmdBufferHdl->GetVkCommandBuffer().copyBuffer(stagingBuffer, vkBuffer, 1, &copyRegion);
}
}
// TODO: Need to destroy staging buffer. Obviously not here but after the command has finished executing.
void SHVkBuffer::ResizeNoCopy(uint32_t newSize)
{
Destroy();
vk::Buffer tempBuffer;
std::tie(tempBuffer, std::ignore) = createBuffer(newSize);
vkBuffer = tempBuffer;
}
void SHVkBuffer::ResizeReplace(uint32_t newSize, void* data, uint32_t srcSize)
{
Destroy();
Init(newSize, data, srcSize, bufferUsageFlags, allocCreateInfo.usage, allocCreateInfo.flags);
}
vk::Buffer SHVkBuffer::GetVkBuffer(void) const noexcept
@ -42,6 +54,11 @@ namespace SHADE
return vkBuffer;
}
vk::BufferUsageFlags SHVkBuffer::GetUsageBits(void) const noexcept
{
return bufferUsageFlags;
}
/***************************************************************************/
/*!
@ -195,12 +212,12 @@ namespace SHADE
// results of allocation
VmaAllocation stagingAlloc;
// To get around VMA's usage for C version of vulkan, create a temp first...,
// To get around VMA's usage for C version of Vulkan, create a temp first...,
VkBuffer tempBuffer{};
// Create the buffer...
vmaCreateBuffer(vmaAllocator,
&bufferInfo.operator VkBufferCreateInfo & (), // TODO: Verify if this works (can use renderdoc to check buffer variables?)
&bufferInfo.operator VkBufferCreateInfo & (), // TODO: Verify if this works (can use RenderDoc to check buffer variables?)
&allocCreateInfo,
&tempBuffer, &stagingAlloc, &allocInfo);
@ -221,6 +238,32 @@ namespace SHADE
vmaUnmapMemory(vmaAllocator, stagingAlloc);
}
std::pair<vk::Buffer, VmaAllocationInfo> SHVkBuffer::createBuffer(uint32_t size)
{
// Modify the size based on the parameter
sizeStored = size;
bufferCreateInfo.size = sizeStored;
// parameters of a vmaAllocation retrieved via vmaGetAllocationInfo
VmaAllocationInfo allocInfo;
// To get around VMA's usage for C version of vulkan, create a temp first...,
VkBuffer tempBuffer{};
// Create the buffer...
auto result = vmaCreateBuffer(vmaAllocator,
&bufferCreateInfo.operator VkBufferCreateInfo & (),
&allocCreateInfo,
&tempBuffer, &alloc, &allocInfo);
if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan buffer. ");
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created buffer. ");
return { tempBuffer, allocInfo };
}
/***************************************************************************/
/*!
@ -230,17 +273,15 @@ namespace SHADE
*/
/***************************************************************************/
SHVkBuffer::SHVkBuffer(std::reference_wrapper<VmaAllocator const> allocator) noexcept
: vkBuffer{}
, stagingBuffer{}
, sizeStored{ 0 }
, mappedPtr{ nullptr }
, alloc {nullptr}
, randomAccessOptimized{false}
, boundToCoherent {false}
, vmaAllocator{allocator}
{
}
: vkBuffer{}
, stagingBuffer{}
, sizeStored{ 0 }
, mappedPtr{ nullptr }
, alloc {nullptr}
, randomAccessOptimized{false}
, boundToCoherent {false}
, vmaAllocator{allocator}
{}
SHVkBuffer::SHVkBuffer(
uint32_t inSize,
@ -260,12 +301,14 @@ namespace SHADE
: vkBuffer{std::move (rhs.vkBuffer)}
, stagingBuffer{ std::move (rhs.stagingBuffer)}
, sizeStored{ std::move (rhs.sizeStored) }
, mappedPtr{ nullptr }
, mappedPtr{ std::move(rhs.mappedPtr) }
, alloc{ std::move (rhs.alloc) }
, randomAccessOptimized{ rhs.randomAccessOptimized }
, boundToCoherent{ rhs.boundToCoherent}
, vmaAllocator{ rhs.vmaAllocator }
, bufferUsageFlags {rhs.bufferUsageFlags}
, bufferCreateInfo { rhs.bufferCreateInfo }
, allocCreateInfo { rhs.allocCreateInfo }
{
rhs.vkBuffer = VK_NULL_HANDLE;
@ -279,12 +322,14 @@ namespace SHADE
vkBuffer = std::move(rhs.vkBuffer);
stagingBuffer = std::move(rhs.stagingBuffer);
sizeStored = std::move(rhs.sizeStored);
mappedPtr = nullptr;
mappedPtr = std::move(rhs.mappedPtr);
alloc = std::move(rhs.alloc);
randomAccessOptimized = rhs.randomAccessOptimized;
boundToCoherent = rhs.boundToCoherent;
vmaAllocator = std::move (rhs.vmaAllocator);
rhs.vkBuffer = VK_NULL_HANDLE;
bufferCreateInfo = rhs.bufferCreateInfo;
allocCreateInfo = rhs.allocCreateInfo;
bufferUsageFlags = rhs.bufferUsageFlags;
return *this;
@ -344,47 +389,26 @@ namespace SHADE
{
sizeStored = inSize;
// For creation of buffer
vk::BufferCreateInfo bufferInfo{};
// Set the buffer flags
bufferUsageFlags = bufferUsage;
// initialize size and usage (vertex, index, uniform, etc)
bufferInfo.size = sizeStored;
bufferInfo.usage = bufferUsage;
bufferInfo.sharingMode = vk::SharingMode::eExclusive;
bufferCreateInfo = vk::BufferCreateInfo{};
bufferCreateInfo.usage = bufferUsageFlags;
bufferCreateInfo.sharingMode = vk::SharingMode::eExclusive;
// Prepare allocation parameters for call to create buffers later
VmaAllocationCreateInfo allocCreateInfo{};
allocCreateInfo = VmaAllocationCreateInfo{};
allocCreateInfo.usage = memUsage;
// If vma allocation flags include dedicated bit, immediately activate dst bit
if (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT)
bufferInfo.usage |= vk::BufferUsageFlagBits::eTransferDst;
bufferCreateInfo.usage |= vk::BufferUsageFlagBits::eTransferDst;
allocCreateInfo.flags = allocFlags;
// parameters of a vmaAllocation retrieved via vmaGetAllocationInfo
VmaAllocationInfo allocInfo;
// To get around VMA's usage for C version of vulkan, create a temp first...,
VkBuffer tempBuffer{};
// Create the buffer...
auto result = vmaCreateBuffer(vmaAllocator,
&bufferInfo.operator VkBufferCreateInfo &(),
&allocCreateInfo,
&tempBuffer, &alloc, &allocInfo);
if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result (result), "Failed to create vulkan buffer. ");
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created buffer. ");
// ...then assign it to the hpp version
auto [tempBuffer, allocInfo] = createBuffer(sizeStored);
vkBuffer = tempBuffer;
// Set the buffer flags
bufferUsageFlags = bufferInfo.usage;
// This probably means that a HOST_CACHED memory type is used on allocation
if (allocFlags & VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)
randomAccessOptimized = true;
@ -456,7 +480,7 @@ namespace SHADE
/***************************************************************************/
void SHVkBuffer::Destroy(void) noexcept
{
vmaDestroyBuffer(vmaAllocator, vkBuffer, alloc);
if (vkBuffer)
vmaDestroyBuffer(vmaAllocator, vkBuffer, alloc);
}
}

View File

@ -47,13 +47,18 @@ namespace SHADE
//! buffer usage info flags
vk::BufferUsageFlags bufferUsageFlags;
vk::BufferCreateInfo bufferCreateInfo;
VmaAllocationCreateInfo allocCreateInfo;
//! Reference to the allocator
//VmaAllocator const& vmaAllocator;
std::reference_wrapper<VmaAllocator const> vmaAllocator;
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void PrepStagingBuffer (void* data, uint32_t srcSize) noexcept;
std::pair<vk::Buffer, VmaAllocationInfo> createBuffer(uint32_t size);
public:
/*-----------------------------------------------------------------------*/
@ -62,13 +67,13 @@ namespace SHADE
SHVkBuffer (void) noexcept = delete;
SHVkBuffer (std::reference_wrapper<VmaAllocator const> allocator) noexcept;
SHVkBuffer (
uint32_t inSize,
uint32_t inSize,
void* data,
uint32_t srcSize,
std::reference_wrapper<VmaAllocator const> allocator,
vk::BufferUsageFlags bufferUsage,
VmaMemoryUsage memUsage,
VmaAllocationCreateFlags allocFlags
VmaMemoryUsage memUsage = VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlags allocFlags = {}
) noexcept;
SHVkBuffer(SHVkBuffer&& rhs) noexcept;
SHVkBuffer& operator=(SHVkBuffer&& rhs) noexcept;
@ -78,26 +83,29 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
void Init (
uint32_t inSize,
void* data,
uint32_t srcSize,
vk::BufferUsageFlags bufferUsage,
VmaMemoryUsage memUsage,
VmaAllocationCreateFlags allocFlags
) noexcept;
void Destroy (void) noexcept;
void Init (
uint32_t inSize,
void* data,
uint32_t srcSize,
vk::BufferUsageFlags bufferUsage,
VmaMemoryUsage memUsage,
VmaAllocationCreateFlags allocFlags
) noexcept;
void Destroy (void) noexcept;
void Map (void) noexcept;
void Unmap (void) noexcept;
void WriteToMemory (void* data, uint32_t sizeToWrite, uint32_t srcOffset, uint32_t dstOffset) noexcept;
void MapWriteUnmap (void* data, uint32_t sizeToWrite, uint32_t srcOffset, uint32_t dstOffset) noexcept;
void Map (void) noexcept;
void Unmap (void) noexcept;
void WriteToMemory (void* data, uint32_t sizeToWrite, uint32_t srcOffset, uint32_t dstOffset) noexcept;
void MapWriteUnmap (void* data, uint32_t sizeToWrite, uint32_t srcOffset, uint32_t dstOffset) noexcept;
void TransferToDeviceResource(Handle<SHVkCommandBuffer> const& cmdBufferHdl) noexcept;
void ResizeNoCopy (uint32_t newSize);
void ResizeReplace (uint32_t newSize, void* data, uint32_t srcSize);
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
vk::Buffer GetVkBuffer (void) const noexcept;
vk::BufferUsageFlags GetUsageBits(void) const noexcept;
};
}

View File

@ -8,6 +8,7 @@
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
namespace SHADE
@ -255,7 +256,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
{
@ -353,6 +354,11 @@ namespace SHADE
}
}
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
{
vkCommandBuffer.bindDescriptorSets (bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
}
/***************************************************************************/
/*!
@ -451,6 +457,33 @@ namespace SHADE
// //vkCommandBuffer.pipelineBarrier()
//}
/***************************************************************************/
/*!
\brief
Issues a multi indirect draw call.
\param indirectDrawData
SHVkBuffer containing the data for the multi indirect draw call.
\param drawCount
Number of multi indirect draw sub-calls stored in indirectDrawData.
*/
/***************************************************************************/
void SHVkCommandBuffer::DrawMultiIndirect(Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount)
{
if (cmdBufferState != SH_CMD_BUFFER_STATE::RECORDING)
{
SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound.");
return;
}
vkCommandBuffer.drawIndexedIndirect(indirectDrawData->GetVkBuffer(), 0, drawCount, sizeof(vk::DrawIndexedIndirectCommand));
}
/***************************************************************************/
/*!

View File

@ -15,6 +15,7 @@ namespace SHADE
class SHVkFramebuffer;
class SHVkPipeline;
class SHVkBuffer;
class SHVkDescriptorSetGroup;
enum class SH_CMD_BUFFER_TYPE
{
@ -96,7 +97,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
void Reset(void);
// Begins, Ends and Nexts
// Begins and Ends
void BeginRecording (void) noexcept;
void EndRecording (void) noexcept;
void BeginRenderpass (Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkFramebuffer> const& framebufferHdl, vk::Offset2D offset = {0, 0}, vk::Extent2D extent = {0, 0}) noexcept;
@ -104,12 +105,13 @@ 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;
void BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept;
void BindIndexBuffer (Handle<SHVkBuffer> const& buffer, uint32_t startingIndex) const noexcept;
void BindDescriptorSet (Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets);
// Draw Commands
void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept;
@ -127,6 +129,7 @@ namespace SHADE
bool IsReadyToSubmit (void) const noexcept;
void HandlePostSubmit (void) noexcept;
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
// Push Constant variable setting
template <typename T>

View File

@ -52,7 +52,7 @@ namespace SHADE
{
vk::DebugUtilsMessengerCreateInfoEXT debMsgCreateInfo;
InitializeDebugCreateInfo(debMsgCreateInfo,
GenMessengerSeverity(SH_DEBUG_MSG_SEV::S_VERBOSE, SH_DEBUG_MSG_SEV::S_WARNING, SH_DEBUG_MSG_SEV::S_ERROR),
GenMessengerSeverity(SH_DEBUG_MSG_SEV::S_INFO, SH_DEBUG_MSG_SEV::S_VERBOSE, SH_DEBUG_MSG_SEV::S_WARNING, SH_DEBUG_MSG_SEV::S_ERROR),
GenMessengerType(SH_DEBUG_MSG_TYPE::T_GENERAL, SH_DEBUG_MSG_TYPE::T_VALIDATION, SH_DEBUG_MSG_TYPE::T_PERFORMANCE));
if (vk::Result result = SHVkInstance::GetVkInstance().createDebugUtilsMessengerEXT(&debMsgCreateInfo, nullptr, &debugMessenger); result != vk::Result::eSuccess)

View File

@ -8,10 +8,10 @@ namespace SHADE
enum class SH_DEBUG_MSG_SEV : VkDebugUtilsMessageSeverityFlagsEXT
{
S_VERBOSE = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
S_INFO = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
S_WARNING = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
S_ERROR = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
S_FLAG = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
S_INFO = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
S_WARNING = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
S_ERROR = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
S_FLAG = VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT,
};
enum class SH_DEBUG_MSG_TYPE : VkDebugUtilsMessageTypeFlagsEXT

View File

@ -93,6 +93,7 @@ namespace SHADE
std::string toLogger = "Vulkan Warning: " + std::string(SHVulkanDebugUtil::VkResultToString(vkResult)) + " | " + std::string(message);
SHLOGV_ERROR(toLogger);
std::cout << std::endl;
}

View File

@ -46,12 +46,15 @@ namespace SHADE
//for (auto& layout : layouts)
for (uint32_t i = 0; i < layouts.size(); ++i)
{
vkLayouts.push_back(layouts[i]->GetVkHandle());
vkLayouts[i] = layouts[i]->GetVkHandle();
}
// Check for variable descriptor count
if (variableDescCounts.size() != layouts.size())
{
SHLOG_ERROR("Number of variable descriptor counts does not match number of layouts. If a layout does not use variable counts, pass in 0. ");
return;
}
// Prepare variable descriptor counts
vk::DescriptorSetVariableDescriptorCountAllocateInfo variableAllocInfo{};
@ -185,4 +188,20 @@ namespace SHADE
}
void SHVkDescriptorSetGroup::UpdateSingleDescriptorSetImages(uint32_t set, uint32_t binding) noexcept
{
vk::WriteDescriptorSet writeDescSet{};
// Initialize info for write
writeDescSet.descriptorType = vk::DescriptorType::eCombinedImageSampler;
writeDescSet.dstArrayElement = 0;
writeDescSet.dstSet = descSets[set];
writeDescSet.dstBinding = binding;
writeDescSet.pImageInfo = updater.writeInfos[set].descImageInfos.data();
writeDescSet.descriptorCount = static_cast<uint32_t>(updater.writeInfos[set].descImageInfos.size());
device->UpdateDescriptorSet(writeDescSet);
}
}

View File

@ -56,8 +56,10 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
/* Descriptor set writing */
/*-----------------------------------------------------------------------------*/
void ModifyWriteDescImage (uint32_t set, uint32_t binding, std::vector<std::pair<vk::ImageView, vk::Sampler>> const& imageViewsAndSamplers) noexcept;
void UpdateDescriptorSet (void) noexcept;
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::vector<std::pair<vk::ImageView, vk::Sampler>> const& imageViewsAndSamplers) noexcept;
void UpdateDescriptorSet(void) noexcept;
void UpdateSingleDescriptorSetImages(uint32_t set, uint32_t binding) noexcept;
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
@ -68,6 +70,7 @@ namespace SHADE
/// <returns>Handle to the Vulkan Descriptor Set.</returns>
[[nodiscard]]
inline const std::vector<vk::DescriptorSet>& GetVkHandle() { return descSets; }
inline const uint32_t GetNumDescriptorSets(void) const noexcept { return static_cast<uint32_t>(descSets.size()); }
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */

View File

@ -15,6 +15,7 @@
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
namespace SHADE
{
@ -179,10 +180,13 @@ namespace SHADE
// for wide lines
features.wideLines = true;
vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{};
descIndexingFeature.descriptorBindingVariableDescriptorCount = true;
// Prepare to create the device
vk::DeviceCreateInfo deviceCreateInfo
{
.pNext = nullptr,
.pNext = &descIndexingFeature,
.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size()),
.pQueueCreateInfos = queueCreateInfos.data(),
.enabledLayerCount = 0, // deprecated and ignored
@ -204,21 +208,8 @@ namespace SHADE
InitializeVMA();
// TODO: Create pipeline caches
// TODO: Create Descriptor pools
//auto poolSizes = std::array
//{
// SHDescriptorPoolSize {SHDescriptorType::COMBINED_SAMPLER, 1000} // hard coded descriptor count
//};
//SHDescriptorPoolParams poolParams
//{
// .poolSizes = poolSizes,
// .maxDescriptorSets = 1000,
//};
//descriptorPool.Initialize(*this, poolParams);
//deviceStorage.Init(*this, queueFamilyIndices.indices[static_cast<uint32_t>(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS)].value());
uboBufferMemoryAlignment = parentPhysicalDeviceHdl->GetDeviceProperties().limits.minUniformBufferOffsetAlignment;
ssboBufferMemoryAlignment = parentPhysicalDeviceHdl->GetDeviceProperties().limits.minStorageBufferOffsetAlignment;
}
SHVkLogicalDevice::SHVkLogicalDevice(SHVkLogicalDevice&& rhs) noexcept
@ -295,6 +286,17 @@ namespace SHADE
return VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM;
}
uint32_t SHVkLogicalDevice::PadUBOSize(uint32_t originalSize) const noexcept
{
uint32_t alignedSize = originalSize;
//uint32_t minBuffer
if (uboBufferMemoryAlignment > 0)
{
alignedSize = (alignedSize + uboBufferMemoryAlignment - 1) & ~(uboBufferMemoryAlignment - 1);
}
return alignedSize;
}
/***************************************************************************/
/*!
@ -486,7 +488,7 @@ namespace SHADE
*/
/***************************************************************************/
Handle<SHVkPipeline> SHVkLogicalDevice::CreatePipeline(Handle<SHVkPipelineLayout> const& pipelineLayoutHdl, SHVkPipelineState const* const state, Handle<SHVkRenderpass> const& renderpassHdl, uint32_t subpass, SH_PIPELINE_TYPE type) noexcept
Handle<SHVkPipeline> SHVkLogicalDevice::CreatePipeline(Handle<SHVkPipelineLayout> const& pipelineLayoutHdl, SHVkPipelineState const* const state, Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHSubpass> subpass, SH_PIPELINE_TYPE type) noexcept
{
return SHVkInstance::GetResourceManager().Create <SHVkPipeline>(GetHandle(), pipelineLayoutHdl, state, renderpassHdl, subpass, type);
@ -520,6 +522,13 @@ namespace SHADE
}
Handle<SHVkDescriptorSetGroup> SHVkLogicalDevice::CreateDescriptorSetGroup(Handle<SHVkDescriptorPool> pool,
std::vector<Handle<SHVkDescriptorSetLayout>> const& layouts,
std::vector<uint32_t> const& variableDescCounts) noexcept
{
return SHVkInstance::GetResourceManager().Create<SHVkDescriptorSetGroup>(GetHandle(), pool, layouts, variableDescCounts);
}
/***************************************************************************/
/*!
@ -568,6 +577,11 @@ namespace SHADE
vkLogicalDevice.updateDescriptorSets(writeDescSets, {});
}
void SHVkLogicalDevice::UpdateDescriptorSet(vk::WriteDescriptorSet const& writeDescSet) noexcept
{
vkLogicalDevice.updateDescriptorSets(1, &writeDescSet, 0, {});
}
/***************************************************************************/
/*!
@ -656,6 +670,11 @@ namespace SHADE
return static_cast<SHQueueFamilyIndex>(SH_Q_FAM::INVALID);
}
Handle<SHVkPhysicalDevice> SHVkLogicalDevice::GetParentPhysicalDevice(void) const noexcept
{
return parentPhysicalDeviceHdl;
}
//SHDescriptorPool const& SHLogicalDevice::GetDescriptorPool(void) const noexcept
//{
// return descriptorPool;

View File

@ -39,6 +39,7 @@ namespace SHADE
class SHVkImageView;
class SHShaderBlockInterface;
class SHVkDescriptorSetGroup;
class SHSubpass;
/***************************************************************************/
/*!
@ -68,7 +69,11 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
//vk::DeviceSize bufferMemoryAlignment{ 64 };
//! UBO alignment
vk::DeviceSize uboBufferMemoryAlignment;
//! SSBO alignment
vk::DeviceSize ssboBufferMemoryAlignment;
//! Vulkan handle
vk::Device vkLogicalDevice;
@ -112,9 +117,12 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
// Miscellaneous functions
void WaitIdle (void) noexcept;
uint32_t FindMemoryType (uint32_t typeFilter, vk::MemoryPropertyFlags properties);
uint32_t PadUBOSize (uint32_t originalSize) const noexcept;
// creation functions
Handle<SHVkSurface> CreateSurface (HWND const& windowHandle) const noexcept;
Handle<SHVkSwapchain> CreateSwapchain (
Handle<SHVkSurface> const& surfaceHdl,
@ -167,7 +175,7 @@ namespace SHADE
Handle<SHVkPipelineLayout> const& pipelineLayoutHdl,
SHVkPipelineState const* const state,
Handle<SHVkRenderpass> const& renderpassHdl,
uint32_t subpass,
Handle<SHSubpass> subpass,
SH_PIPELINE_TYPE type
) noexcept;
@ -176,19 +184,25 @@ namespace SHADE
Handle<SHVkFramebuffer> CreateFramebuffer (Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept;
Handle<SHVkDescriptorSetLayout> CreateDescriptorSetLayout (std::vector<SHVkDescriptorSetLayout::Binding> const& bindings) noexcept;
Handle<SHVkDescriptorPool> CreateDescriptorPools (const SHVkDescriptorPool::Config& config = {}) noexcept;
Handle<SHVkDescriptorSetGroup> CreateDescriptorSetGroup(Handle<SHVkDescriptorPool> pool,
std::vector<Handle<SHVkDescriptorSetLayout>> const& layouts,
std::vector<uint32_t> const& variableDescCounts) noexcept;
Handle<SHVkPipelineLayout> CreatePipelineLayout (SHPipelineLayoutParams& pipelineLayoutParams) noexcept;
Handle<SHVkFence> CreateFence (void) const noexcept;
Handle<SHVkSemaphore> CreateSemaphore (void) const noexcept;
void UpdateDescriptorSets (std::vector<vk::WriteDescriptorSet> const& writeDescSets) noexcept;
void UpdateDescriptorSets(std::vector<vk::WriteDescriptorSet> const& writeDescSets) noexcept;
void UpdateDescriptorSet (vk::WriteDescriptorSet const& writeDescSet) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
vk::Device const& GetVkLogicalDevice (void) const noexcept;
Handle<SHVkQueue> const& GetQueue (SH_Q_FAM queueFamArrayIndex, uint8_t queueIndex) const;
VmaAllocator const& GetVMAAllocator (void) noexcept;
SHQueueFamilyIndex GetQueueFamilyIndex (SH_Q_FAM family) const noexcept;
vk::Device const& GetVkLogicalDevice (void) const noexcept;
Handle<SHVkQueue> const& GetQueue (SH_Q_FAM queueFamArrayIndex, uint8_t queueIndex) const;
VmaAllocator const& GetVMAAllocator (void) noexcept;
SHQueueFamilyIndex GetQueueFamilyIndex (SH_Q_FAM family) const noexcept;
Handle<SHVkPhysicalDevice> GetParentPhysicalDevice (void) const noexcept;
//vk::DeviceSize GetBufferAlignment (void) const noexcept;
//SHDescriptorPool const& GetDescriptorPool(void) const noexcept;

View File

@ -26,7 +26,8 @@ namespace SHADE
queueFamilyProperties = vkPhysicalDevice.getQueueFamilyProperties();
deviceFeatures = vkPhysicalDevice.getFeatures();
deviceFeatures = vkPhysicalDevice.getFeatures2();
}
SHVkPhysicalDevice::SHVkPhysicalDevice(SHVkPhysicalDevice&& rhs) noexcept

View File

@ -19,7 +19,7 @@ namespace SHADE
vk::PhysicalDeviceProperties deviceProperties{};
vk::PhysicalDeviceMemoryProperties memoryProperties{};
vk::PhysicalDeviceFeatures deviceFeatures{};
vk::PhysicalDeviceFeatures2 deviceFeatures{};
std::vector<vk::QueueFamilyProperties> queueFamilyProperties{};
public:

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,206 @@
/************************************************************************************//*!
\file SHBatch.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 2022
\brief Contains the definition of SHBatch's functions.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#include "SHpch.h"
#include "SHBatch.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/SHVkUtil.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* SHBatch - Usage Functions */
/*---------------------------------------------------------------------------------*/
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
: pipeline{ pipeline }
{
if (!pipeline)
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
}
void SHBatch::Add(const SHRenderable* renderable)
{
// Check if we have a SubBatch with the same mesh yet
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
{
return batch.Mesh == renderable->Mesh;
});
// Create one if not found
if (subBatch == subBatches.end())
{
subBatches.emplace_back(renderable->Mesh);
subBatch = subBatches.end() - 1;
}
// Add renderable in
subBatch->Renderables.insert(renderable);
}
void SHBatch::Remove(const SHRenderable* renderable)
{
// Check if we have a SubBatch with the same mesh yet
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
{
return batch.Mesh == renderable->Mesh;
});
// Attempt to remove if it exists
if (subBatch == subBatches.end())
return;
subBatch->Renderables.erase(renderable);
}
void SHBatch::Clear()
{
subBatches.clear();
// Clear CPU buffers
drawData.clear();
transformData.clear();
matPropsData.reset();
matPropsDataSize = 0;
// Clear GPU buffers
drawDataBuffer.Free();
transformDataBuffer.Free();
matPropsBuffer.Free();
}
void SHBatch::Build(Handle<SHVkLogicalDevice> device)
{
// No need to build as there are no changes
if (!isDirty)
return;
// Count number of elements
size_t numTotalElements = 0;
for (const auto& subBatch : subBatches)
{
numTotalElements += subBatch.Renderables.size();
}
// Generate CPU buffers
// - Draw data
drawData.reserve(subBatches.size());
drawData.clear();
// - Transform data
transformData.reserve(numTotalElements);
transformData.clear();
// - Material Properties Data
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
(
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
vk::ShaderStageFlagBits::eFragment
);
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
Byte singleMatPropSize = 0;
Byte matPropTotalBytes = 0;
if (!EMPTY_MAT_PROPS)
{
singleMatPropSize = SHADER_INFO->GetBytesRequired();
matPropTotalBytes = drawData.size() * singleMatPropSize;
if (matPropsDataSize < matPropTotalBytes)
{
matPropsData.reset(new char[matPropTotalBytes]);
matPropsDataSize = matPropTotalBytes;
}
}
// Build Sub Batches
uint32_t nextInstanceIndex = 0;
char* propsCurrPtr = matPropsData.get();
for (auto& subBatch : subBatches)
{
// Create command
drawData.emplace_back(vk::DrawIndexedIndirectCommand
{
.indexCount = subBatch.Mesh->IndexCount,
.instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()),
.firstIndex = subBatch.Mesh->FirstIndex,
.vertexOffset = subBatch.Mesh->FirstVertex,
.firstInstance = nextInstanceIndex
});
// Fill in buffers (CPU)
for (const SHRenderable* renderable : subBatch.Renderables)
{
// Transform
transformData.emplace_back(renderable->TransformMatrix);
// Material Properties
if (!EMPTY_MAT_PROPS)
{
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
propsCurrPtr += singleMatPropSize;
}
}
}
// Send all buffered data to the GPU buffers
using BuffUsage = vk::BufferUsageFlagBits;
// - Draw Data
if (drawDataBuffer)
drawDataBuffer->Unmap();
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
SHVkUtil::EnsureBufferAndCopyHostVisibleData
(
device, drawDataBuffer, drawData.data(), DRAW_DATA_BYTES,
BuffUsage::eIndirectBuffer
);
drawDataBuffer->Map();
// - Transform Buffer
if (transformDataBuffer)
transformDataBuffer->Unmap();
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
SHVkUtil::EnsureBufferAndCopyHostVisibleData
(
device, transformDataBuffer, transformData.data(), TF_DATA_BYTES,
BuffUsage::eVertexBuffer
);
transformDataBuffer->Map();
// - Material Properties Buffer
if (!EMPTY_MAT_PROPS)
{
if (matPropsBuffer)
matPropsBuffer->Unmap();
SHVkUtil::EnsureBufferAndCopyHostVisibleData
(
device, matPropsBuffer, matPropsData.get(), static_cast<uint32_t>(matPropTotalBytes),
BuffUsage::eStorageBuffer
);
matPropsBuffer->Map();
}
isDirty = false;
}
/*---------------------------------------------------------------------------------*/
/* SHBatch - Usage Functions */
/*---------------------------------------------------------------------------------*/
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer)
{
cmdBuffer->BindPipeline(pipeline);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer, 0);
cmdBuffer->DrawMultiIndirect(drawDataBuffer, static_cast<uint32_t>(drawData.size()));
}
}

View File

@ -0,0 +1,101 @@
/************************************************************************************//*!
\file SHBatch.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 2022
\brief Contains the definition of SHSubBatch and SHBatch.
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_set>
// External Dependencies
#include "Graphics/SHVulkanIncludes.h"
// Project Includes
#include "Resource/Handle.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Math/SHMatrix.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkBuffer;
class SHVkCommandBuffer;
class SHVkPipeline;
class SHMesh;
class SHRenderable;
class SHVkLogicalDevice;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Describes a segment of the sub batch operation.
*/
/***********************************************************************************/
struct SHSubBatch
{
public:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Handle<SHMesh> Mesh;
std::unordered_set<const SHRenderable*> Renderables;
};
/***********************************************************************************/
/*!
\brief
Describes a segment of the sub batch operation.
*/
/***********************************************************************************/
class SHBatch
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHBatch(Handle<SHVkPipeline> pipeline);
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
void Add(const SHRenderable* renderable);
void Remove(const SHRenderable* renderable);
void Clear();
void Build(Handle<SHVkLogicalDevice> device);
void Draw(Handle<SHVkCommandBuffer> cmdBuffer);
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; };
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Batch Properties
Handle<SHVkPipeline> pipeline;
// Batch Tree
std::vector<SHSubBatch> subBatches;
bool isDirty = true;
// CPU Buffers
std::vector<vk::DrawIndexedIndirectCommand> drawData;
std::vector<SHMatrix> transformData;
std::unique_ptr<char> matPropsData;
Byte matPropsDataSize = 0;
// GPU Buffers
Handle<SHVkBuffer> drawDataBuffer;
Handle<SHVkBuffer> transformDataBuffer;
Handle<SHVkBuffer> matPropsBuffer;
};
}

View File

@ -0,0 +1,126 @@
/************************************************************************************//*!
\file SHBatcher.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 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 "SHBatcher.h"
// STL Includes
#include <vector>
// Project Includes
#include "SHSuperBatch.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "Tools/SHLogger.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
void SHBatcher::Init(Handle<SHRenderGraph> _renderGraph)
{
renderGraph = _renderGraph;
}
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
void SHBatcher::PrepareBatches()
{
// Iterate through all renderables and send it into the batching
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
for (auto iter = renderables.cbegin(); iter != renderables.cend(); ++iter)
{
AddToBatch(&(*iter));
}
}
void SHBatcher::AddToBatch(SHRenderable const* renderable)
{
// Get Subpass Index for this renderables pipeline
const Handle<SHSubpass> SUBPASS = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass();
// Check if there is a SuperBatch for the specific Subpass
auto superBatch = std::find_if(superBatches.begin(), superBatches.end(), [&](Handle<SHSuperBatch> superBatch)
{
return superBatch->GetSubpass() == SUBPASS;
});
// Ignore and emit a warning if it doesn't exist
if (superBatch == superBatches.end())
{
SHLOG_WARNING("A renderable was attempted to be added to a SuperBatch which does not exist.");
return;
}
// Add the Renderable
(*superBatch)->Add(renderable);
}
void SHBatcher::RemoveFromBatch(SHRenderable const* renderable)
{
// Get Subpass Index for this renderables pipeline
const Handle<SHSubpass> SUBPASS = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass();
// Check if there is a SuperBatch for the specific RenderPass
auto superBatch = std::find_if(superBatches.begin(), superBatches.end(), [&](Handle<SHSuperBatch> superBatch)
{
return superBatch->GetSubpass() == SUBPASS;
});
// Remove if it exists
if (superBatch == superBatches.end())
{
SHLOG_WARNING("A renderable was attempted to be removed from a SuperBatch which does not exist.");
return;
}
(*superBatch)->Remove(renderable);
}
void SHBatcher::FinaliseBatches(Handle<SHVkLogicalDevice> device)
{
// Build SuperBatches
for (auto& batch : superBatches)
{
batch->Build(device);
}
}
void SHBatcher::ClearBatches()
{
for (auto& batch : superBatches)
{
batch->Clear();
}
superBatches.clear();
}
void SHBatcher::RegisterSuperBatch(Handle<SHSuperBatch> superBatch)
{
superBatches.emplace_back(superBatch);
}
void SHBatcher::DeregisterSuperBatch(Handle<SHSuperBatch> superBatch)
{
auto sbIter = std::find(superBatches.begin(), superBatches.end(), superBatch);
if (sbIter == superBatches.end())
return;
superBatches.erase(sbIter);
}
}

View File

@ -0,0 +1,64 @@
/************************************************************************************//*!
\file SHBatcher.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Aug 30, 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 <vector>
// Project Includes
#include "Resource/Handle.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHRenderable;
class SHRenderGraph;
class SHSuperBatch;
class SHVkLogicalDevice;
class SHVkCommandBuffer;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Handles batching of all Renderables assigned to a specific Renderer.
*/
/***********************************************************************************/
class SHBatcher
{
public:
/*-----------------------------------------------------------------------------*/
/* Lifecycle Functions */
/*-----------------------------------------------------------------------------*/
void Init(Handle<SHRenderGraph> _renderGraph);
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
void PrepareBatches();
void AddToBatch(SHRenderable const* renderable);
void RemoveFromBatch(SHRenderable const* renderable);
void FinaliseBatches(Handle<SHVkLogicalDevice> device);
void ClearBatches();
void RegisterSuperBatch(Handle<SHSuperBatch> superBatch);
void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch);
private:
Handle<SHRenderGraph> renderGraph;
// Children
std::vector<Handle<SHSuperBatch>> superBatches;
};
}

View File

@ -0,0 +1,99 @@
/************************************************************************************//*!
\file SHSuperBatch.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 8, 2022
\brief Contains the definition of SHSuperBatch's functions.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#include "SHpch.h"
#include "SHSuperBatch.h"
#include "SHBatch.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
SHSuperBatch::SHSuperBatch(Handle<SHSubpass> sp)
: subpass { sp }
{}
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
void SHSuperBatch::Add(const SHRenderable* renderable) noexcept
{
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
// Check if we have a batch with the same pipeline first
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
{
return batch.GetPipeline() == PIPELINE;
});
// Create one if not found
if (batch == batches.end())
{
batches.emplace_back(PIPELINE);
batch = batches.end() - 1;
}
// Add renderable in
batch->Add(renderable);
}
void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept
{
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
// Check if we have a Batch with the same pipeline yet
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)
{
return batch.GetPipeline() == PIPELINE;
});
// Attempt to remove if it exists
if (batch == batches.end())
return;
batch->Remove(renderable);
}
void SHSuperBatch::Clear() noexcept
{
for (auto& batch : batches)
{
batch.Clear();
}
batches.clear();
}
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device) noexcept
{
// Build all batches
for (auto& batch : batches)
{
batch.Build(device);
}
}
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer) noexcept
{
// Build all batches
for (auto& batch : batches)
{
batch.Draw(cmdBuffer);
}
}
}

View File

@ -0,0 +1,75 @@
/************************************************************************************//*!
\file SHSuperBatch.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 8, 2022
\brief Contains the definition of SHSuperBatch.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// External Dependencies
#include "Graphics/SHVulkanIncludes.h"
// Project Includes
#include "Resource/Handle.h"
#include "SHBatch.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkBuffer;
class SHVkCommandBuffer;
class SHMesh;
class SHRenderable;
class SHVkLogicalDevice;
class SHSubpass;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Stores and manages data for all of the batches associated with a specific SubPass
within a RenderGraph.
*/
/***********************************************************************************/
class SHSuperBatch
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHSuperBatch(Handle<SHSubpass> sp);
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
void Add(const SHRenderable* renderable) noexcept;
void Remove(const SHRenderable* renderable) noexcept;
void Clear() noexcept;
void Build(Handle<SHVkLogicalDevice> device) noexcept;
void Draw(Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHSubpass> GetSubpass() const noexcept { return subpass; };
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Batch Properties
Handle<SHSubpass> subpass;
// Children
std::vector<SHBatch> batches;
};
}

View File

@ -0,0 +1,97 @@
#include "SHpch.h"
#include "SHGraphicsGlobalData.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Pipeline/SHPipelineState.h"
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
namespace SHADE
{
void SHGraphicsGlobalData::InitDescSetLayouts(Handle<SHVkLogicalDevice> logicalDevice) noexcept
{
SHVkDescriptorSetLayout::Binding genericDataBinding
{
.Type = vk::DescriptorType::eUniformBufferDynamic,
.Stage = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eCompute,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::GENERIC_DATA,
.DescriptorCount = 1,
};
SHVkDescriptorSetLayout::Binding texturesBinding
{
.Type = vk::DescriptorType::eCombinedImageSampler,
.Stage = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eCompute,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA,
.DescriptorCount = 2000, // we can have up to 2000 textures for now
.flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount,
};
// For global data (generic data and textures)
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout({ genericDataBinding, texturesBinding });
SHVkDescriptorSetLayout::Binding lightBinding
{
.Type = vk::DescriptorType::eStorageBufferDynamic,
.Stage = vk::ShaderStageFlagBits::eFragment,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::LIGHTS_DATA,
.DescriptorCount = 1,
};
// For Dynamic global data (lights)
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout({ lightBinding });
SHVkDescriptorSetLayout::Binding cameraDataBinding
{
.Type = vk::DescriptorType::eUniformBufferDynamic,
.Stage = vk::ShaderStageFlagBits::eVertex,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA,
.DescriptorCount = 1,
};
// For High frequency global data (camera)
Handle<SHVkDescriptorSetLayout> cameraDataGlobalLayout = logicalDevice->CreateDescriptorSetLayout({ cameraDataBinding });
SHVkDescriptorSetLayout::Binding materialDataBinding
{
.Type = vk::DescriptorType::eStorageBufferDynamic,
.Stage = vk::ShaderStageFlagBits::eFragment,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
.DescriptorCount = 1,
};
// For High frequency global data (camera)
Handle<SHVkDescriptorSetLayout> materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout({ materialDataBinding });
globalDescSetLayouts.push_back(staticGlobalLayout);
globalDescSetLayouts.push_back(dynamicGlobalLayout);
globalDescSetLayouts.push_back(cameraDataGlobalLayout);
globalDescSetLayouts.push_back(materialDataPerInstanceLayout);
}
void SHGraphicsGlobalData::InitDefaultVertexInputState(void) noexcept
{
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 SHGraphicsGlobalData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept
{
InitDescSetLayouts(logicalDevice);
InitDefaultVertexInputState();
}
std::vector<Handle<SHVkDescriptorSetLayout>> const& SHGraphicsGlobalData::GetDescSetLayouts(void) const noexcept
{
return globalDescSetLayouts;
}
SHVertexInputState const& SHGraphicsGlobalData::GetDefaultViState(void) const noexcept
{
return defaultVertexInputState;
}
}

View File

@ -0,0 +1,39 @@
#pragma once
#include "SH_API.h"
#include "Graphics/Pipeline/SHPipelineState.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
namespace SHADE
{
class SHVkLogicalDevice;
class SHVkDescriptorSetLayout;
class SHVkDescriptorSetGroup;
class SH_API SHGraphicsGlobalData
{
private:
//! Global descriptor set layouts. Used to allocate descriptor sets
std::vector<Handle<SHVkDescriptorSetLayout>> globalDescSetLayouts;
//! Global Descriptor sets
Handle<SHVkDescriptorSetGroup> globalDescSets;
//! Default vertex input state (used by everything).
SHVertexInputState defaultVertexInputState;
void InitDescSetLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
void InitDefaultVertexInputState(void) noexcept;
public:
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescSetLayouts (void) const noexcept;
SHVertexInputState const& GetDefaultViState (void) const 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)
{
SHVec3 view = target - pos; view = SHVec3::Normalise(view);
SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right);
const SHVec3 UP = SHVec3::Cross(right, view);
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 */
/*---------------------------------------------------------------------------------*/
SHMatrix SHCamera::GetViewMatrix() const
{
return viewMatrix;
}
SHMatrix SHCamera::GetProjectionMatrix() const
{
return projMatrix;
}
SHMatrix SHCamera::GetViewProjectionMatrix()
{
updateMatrices();
return vpMatrix;
}
SHMatrix SHCamera::GetInverseViewMatrix() const
{
return inverseVpMatrix;
}
SHMatrix SHCamera::GetInverseProjectionMatrix() const
{
return inverseProjMatrix;
}
SHMatrix 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 = SHMatrix::Inverse(vpMatrix);
}
}
SHVec3 SHCamera::multiplyHomogenous(const SHMatrix& 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 SHVec3& vec);
};
}

View File

@ -0,0 +1,157 @@
/************************************************************************************//*!
\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 generic data.
*/
/***************************************************************************/
static constexpr uint32_t GENERIC_DATA = 0;
/***************************************************************************/
/*!
\brief
DescriptorSet binding for combined image sampler data.
*/
/***************************************************************************/
static constexpr uint32_t IMAGE_AND_SAMPLERS_DATA = 1;
/***************************************************************************/
/*!
\brief
DescriptorSet binding for lights.
*/
/***************************************************************************/
static constexpr uint32_t LIGHTS_DATA = 0;
/***************************************************************************/
/*!
\brief
DescriptorSet binding for lights.
*/
/***************************************************************************/
static constexpr uint32_t CAMERA_DATA = 0;
/***************************************************************************/
/*!
\brief
DescriptorSet binding for per instance material values.
*/
/***************************************************************************/
static constexpr uint32_t BATCHED_PER_INST_DATA = 0;
};
struct VertexBufferBindings
{
/***************************************************************************/
/*!
\brief
Vertex buffer bindings for the transform matrix buffer.
*/
/***************************************************************************/
static constexpr uint32_t POSITION = 0;
/***************************************************************************/
/*!
\brief
Vertex buffer bindings for the transform matrix buffer.
*/
/***************************************************************************/
static constexpr uint32_t TEX_COORD = 1;
/***************************************************************************/
/*!
\brief
Vertex buffer bindings for the transform matrix buffer.
*/
/***************************************************************************/
static constexpr uint32_t NORMAL = 2;
/***************************************************************************/
/*!
\brief
Vertex buffer bindings for the transform matrix buffer.
*/
/***************************************************************************/
static constexpr uint32_t TANGENT = 3;
/***************************************************************************/
/*!
\brief
Vertex buffer bindings for the transform matrix buffer.
*/
/***************************************************************************/
static constexpr uint32_t TRANSFORM = 4;
};
/*******************************************************************************/
/*!
\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,247 +19,452 @@ 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"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Graphics/MiddleEnd/Batching/SHSuperBatch.h"
#include "SHGraphicsConstants.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
void SHGraphicsSystem::Init(void)
{
// 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);
// 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
});
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 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);
if (frameData.cmdPoolHdls.empty())
throw std::runtime_error("No command pools available!");
Handle<SHVkCommandPool> commandPool = frameData.cmdPoolHdls[0];
//commandBuffers[i] = commandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY); // works
}
descPool = device->CreateDescriptorPools();
/*-----------------------------------------------------------------------*/
/* RENDERGRAPH TESTING */
/*-----------------------------------------------------------------------*/
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
auto writeSubpass = node->AddSubpass("G-Buffer Write");
writeSubpass->AddColorOutput("Position");
writeSubpass->AddColorOutput("Present");
// Second subpass to read from G-Buffer
auto compositeSubpass = node->AddSubpass("G-Buffer Composite");
compositeSubpass->AddColorOutput("Composite");
compositeSubpass->AddInput("Normals");
compositeSubpass->AddInput("Position");
//auto compositeNode = renderGraph.AddNode("Bloom", { "Composite", "Downscale", "Present" }, { "G-Buffer" });
//auto bloomSubpass = compositeNode->AddSubpass("Downsample");
//bloomSubpass->AddInput("Composite");
//bloomSubpass->AddColorOutput("Downscale");
//bloomSubpass->AddColorOutput("Present");
renderGraph.Generate();
/*-----------------------------------------------------------------------*/
/* RENDERGRAPH END TESTING */
/*-----------------------------------------------------------------------*/
}
void SHGraphicsSystem::Run(float dt) noexcept
/* Constructor/Destructors */
/*---------------------------------------------------------------------------------*/
void SHGraphicsSystem::Init(void)
{
/*-----------------------------------------------------------------------*/
/* BACKEND BOILERPLATE */
/*-----------------------------------------------------------------------*/
// Set Up Instance
SHVkInstance::Init(true, true, true);
// Get Physical Device and Construct Logical Device
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 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
});
// 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);
transferQueue = device->GetQueue(SH_Q_FAM::TRANSFER, 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 a descriptor pool
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);
/*-----------------------------------------------------------------------*/
/* MIDDLE END SETUP
- Viewports
- Renderer
- Render graph in renderers
- Render graph command buffer semaphores
- Default vertex input state
- Global data
/*-----------------------------------------------------------------------*/
globalData = resourceManager.Create<SHGraphicsGlobalData>();
globalData->Init(device);
// 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(static_cast<float>(windowDims.first), static_cast<float>(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, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
// Create Default Viewport
defaultViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
// Get render graph from default viewport world renderer
auto worldRenderGraph = resourceManager.Create<SHRenderGraph>();
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{swapchain->GetNumImages()};
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
{
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
}
// Initialize world render graph
worldRenderGraph->Init(device, swapchain, renderContextCmdPools, globalData);
//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 gBufferWriteSubpass = node->AddSubpass("G-Buffer Write");
gBufferWriteSubpass->AddColorOutput("Present");
//writeSubpass->AddColorOutput("Normals");
// //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");
// TODO: Use macro to add this node when SH_EDITOR is enabled
//auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {});
//auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
//imguiSubpass->AddColorOutput("Present");
worldRenderGraph->Generate();
// Create Semaphore
for (auto& semaHandle : graphSemaphores)
{
semaHandle = device->CreateSemaphore();
}
// Create Debug Renderers
/*debugScreenRenderer = defaultViewport->AddRenderer(resourceManager, worldRenderGraph);
debugScreenRenderer->SetCamera(screenCamera);
debugWorldRenderer = defaultViewport->AddRenderer(resourceManager, worldRenderGraph);
debugWorldRenderer->SetCamera(worldCamera);*/
// Add world renderer to default viewport
worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), descPool, globalData->GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera);
// TODO: This is VERY temporarily here until a more solid resource management system is implemented
shaderSourceLibrary.Init("../../TempShaderFolder/");
shaderSourceLibrary.LoadShader(0, "TestCubeVs.glsl", SH_SHADER_TYPE::VERTEX, true);
shaderSourceLibrary.LoadShader(1, "TestCubeFs.glsl", SH_SHADER_TYPE::FRAGMENT, true);
shaderModuleLibrary.ImportFromSourceLibrary(device, shaderSourceLibrary);
auto cubeVS = shaderModuleLibrary.GetShaderModule("TestCubeVs.glsl");
auto cubeFS = shaderModuleLibrary.GetShaderModule("TestCubeFs.glsl");
//triVS->Reflect();
//triFS->Reflect();
defaultMaterial = AddMaterial(cubeVS, cubeFS, gBufferWriteSubpass);
}
/***************************************************************************/
/*!
\brief
Main render loop. Loops through viewports -> renderers -> invoke render
graphs sequentially using semaphores.
\param dt
\return
*/
/***************************************************************************/
void SHGraphicsSystem::Run(double) 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);
using BufferPair = std::pair<Handle<SHVkBuffer>, uint32_t>;
const std::initializer_list<BufferPair> MESH_DATA =
{
std::make_pair(meshLibrary.GetVertexPositionsBuffer(), SHGraphicsConstants::VertexBufferBindings::POSITION),
std::make_pair(meshLibrary.GetVertexTexCoordsBuffer(), SHGraphicsConstants::VertexBufferBindings::TEX_COORD),
std::make_pair(meshLibrary.GetVertexNormalsBuffer(), SHGraphicsConstants::VertexBufferBindings::NORMAL),
std::make_pair(meshLibrary.GetVertexTangentsBuffer(), SHGraphicsConstants::VertexBufferBindings::TANGENT),
std::make_pair(meshLibrary.GetIndexBuffer(), 0),
};
renderContext.ResetFence();
// For every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
{
auto& 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(), MESH_DATA);
// 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] },
{ vk::PipelineStageFlagBits::eColorAttachmentOutput },
{ (vpIndex == viewports.size() - 1 && renIndex == renderers.size() - 1) ? frameData.fenceHdl : Handle<SHVkFence>{} }
);
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()
{
// Finalise all batches
for (auto vp : viewports)
for (auto renderer : vp->GetRenderers())
{
renderer->GetRenderGraph()->FinaliseBatch();
}
// Resize
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();
const uint32_t CURR_FRAME_IDX_2 = renderContext.GetCurrentFrame();
// #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: 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, Handle<SHSubpass> subpass)
{
// Retrieve pipeline from pipeline storage or create if unavailable
auto shaderPair = std::make_pair(vertShader, fragShader);
// Create material
auto mat = resourceManager.Create<SHMaterial>();
auto renderGraphNode = subpass->GetParentNode();
auto pipeline = renderGraphNode->GetOrCreatePipeline(std::make_pair(vertShader, fragShader), subpass);
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);
}
SHADE::Handle<SHADE::SHMaterialInstance> SHGraphicsSystem::AddMaterialInstance()
{
return AddMaterialInstance(defaultMaterial);
}
void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance)
{
resourceManager.Free(materialInstance);
}
/*---------------------------------------------------------------------------------*/
/* Mesh Registration Functions */
/*---------------------------------------------------------------------------------*/
SHADE::Handle<SHADE::SHMesh> SHGraphicsSystem::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)
{
return meshLibrary.AddMesh(vertexCount, positions, texCoords, tangents, normals, indexCount, indices);
}
void SHGraphicsSystem::RemoveMesh(Handle<SHMesh> mesh)
{
meshLibrary.RemoveMesh(mesh);
}
void SHGraphicsSystem::BuildMeshBuffers()
{
transferCmdBuffer->BeginRecording();
meshLibrary.BuildBuffers(device, transferCmdBuffer);
transferCmdBuffer->EndRecording();
transferQueue->SubmitCommandBuffer({ transferCmdBuffer });
}
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
{
window = wind;
window = wind;
}
SHRenderGraph const& SHGraphicsSystem::GetRenderGraph(void) const noexcept
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{
return renderGraph;
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
}
void SHGraphicsSystem::SHGraphicsSystemRoutine::Execute(double dt) noexcept
void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->Run(dt);
}
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
}
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
{
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
for (auto& renderable : renderables)
{
if (!renderable.WasMaterialChanged())
continue;
// Remove from old material's SuperBatch
Handle<SHMaterial> prevMaterial = renderable.GetPrevMaterial();
if (prevMaterial)
{
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
oldSuperBatch->Remove(&renderable);
}
// Add to new SuperBatch
Handle<SHSuperBatch> newSuperBatch = renderable.GetMaterial()->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
newSuperBatch->Add(&renderable);
// Unset change flag
renderable.ResetChangedFlag();
}
}
}

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,137 +24,232 @@ 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/RenderGraph/SHRenderGraph.h"
#include "Graphics/MiddleEnd/Shaders/SHShaderSourceLibrary.h"
#include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h"
#include "SHMeshLibrary.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* 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;
class SHMaterial;
class SHMaterialInstance;
/*---------------------------------------------------------------------------------*/
/* 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;
};
/***********************************************************************************/
/*!
\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;
};
class SH_API BatcherDispatcherRoutine 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, Handle<SHSubpass> subpass);
void RemoveMaterial(Handle<SHMaterial> material);;
Handle<SHMaterialInstance> AddMaterialInstance();
Handle<SHMaterialInstance> AddMaterialInstance(Handle<SHMaterial> material);
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
/*-----------------------------------------------------------------------------*/
/* Mesh Registration 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
indices.
\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 SHMesh::VertexTangent* const tangents, const SHMesh::VertexNormal* const normals, uint32_t indexCount, const SHMesh::Index* const indices);
/*******************************************************************************/
/*!
/*-----------------------------------------------------------------------------*/
/* Setters */
/*-----------------------------------------------------------------------------*/
void SetWindow (SHWindow* wind) noexcept;
\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.
/*-----------------------------------------------------------------------------*/
/* 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;}
\param mesh
Handle to the mesh to remove.
*/
/*******************************************************************************/
void RemoveMesh(Handle<SHMesh> mesh);
/***************************************************************************/
/*!
\brief
Finalises all changes to the MeshLibrary into the GPU buffers.
*/
/***************************************************************************/
void BuildMeshBuffers();
/*-----------------------------------------------------------------------------*/
/* 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; }
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;
// Not Owned Resources
SHWindow* window;
// Renderers
//Handle<SHRenderer> debugWorldRenderer;
//Handle<SHRenderer> debugScreenRenderer;
//std::vector<SHRenderer> renderers;
SHRenderGraph renderGraph;
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Owned Vulkan Resources
Handle<SHVkPhysicalDevice> physicalDevice;
Handle<SHVkLogicalDevice> device;
Handle<SHVkSurface> surface;
Handle<SHVkSwapchain> swapchain;
Handle<SHVkQueue> graphicsQueue;
Handle<SHVkQueue> transferQueue;
Handle<SHVkDescriptorPool> descPool;
Handle<SHVkCommandPool> transferCmdPool;
Handle<SHVkCommandBuffer> transferCmdBuffer;
SHRenderContext renderContext;
std::array<Handle<SHVkSemaphore>, 2> graphSemaphores;
// Not Owned Resources
SHWindow* window = nullptr;
friend SHGraphicsSystemRoutine;
};
// global data (descriptor sets as well)
Handle<SHGraphicsGlobalData> globalData;
// Middle End Resources
ResourceManager resourceManager;
SHMeshLibrary meshLibrary;
// Viewports
Handle<SHViewport> defaultViewport; // Whole screen
std::vector<Handle<SHViewport>> viewports; // Additional viewports
// Debug Renderers
Handle<SHRenderer> debugWorldRenderer;
Handle<SHRenderer> debugScreenRenderer;
// Temp renderers
Handle<SHRenderer> worldRenderer;
// Temp Cameras
Handle<SHCamera> worldCamera;
Handle<SHCamera> screenCamera;
// TODO: Temporary only until resource library from Xiao Qi is implemented
SHShaderSourceLibrary shaderSourceLibrary;
SHShaderModuleLibrary shaderModuleLibrary;
// Temp Materials
Handle<SHMaterial> defaultMaterial;
};
}

View File

@ -0,0 +1,78 @@
#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
const Handle<SHShaderBlockInterface> SHADER_INFO = getShaderBlockInterface();
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
if (propMemorySize <= 0)
{
propMemory.reset();
}
else
{
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
if (propMemory)
memset(propMemory.get(), 0, propMemorySize);
}
void SHMaterial::ExportProperties(void* dest) const noexcept
{
if (propMemory)
memcpy(dest, propMemory.get(), propMemorySize);
}
size_t SHMaterial::GetPropertiesMemorySize() const noexcept
{
const Handle<SHShaderBlockInterface> SHADER_INFO = getShaderBlockInterface();
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
}
/*---------------------------------------------------------------------------------*/
/* 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,79 @@
/************************************************************************************//*!
\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 "SHGraphicsConstants.h"
#include "SHMaterial.h"
#include "Graphics/Pipeline/SHVkPipeline.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
const SHShaderBlockInterface::Variable* variable = SHADER_INFO->GetVariable(static_cast<uint32_t>(data.Index));
if (variable == nullptr)
{
SHLOG_WARNING("[SHMaterialInstance] Invalid override data indices provided. Skipping.");
continue;
}
const auto DATA_OFFSET = variable->offset;
memcpy(static_cast<char*>(dest) + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize);
}
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterialInstance::getShaderBlockInterface() const noexcept
{
return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface
(
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
vk::ShaderStageFlagBits::eFragment
);
}
}

View File

@ -0,0 +1,88 @@
/************************************************************************************//*!
\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"
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.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;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> getShaderBlockInterface() const noexcept;
};
}
#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();
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 "Math/SHMath.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 = SHVec3;
using VertexTexCoord = SHVec2;
using VertexTangent = SHVec3;
using VertexNormal = SHVec3;
/*-----------------------------------------------------------------------------*/
/* 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 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,97 @@
/************************************************************************************//*!
\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"
#include "SHGraphicsSystem.h"
#include "SHMaterialInstance.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* SHComponent Lifecycle Functions */
/*-----------------------------------------------------------------------------------*/
void SHRenderable::OnCreate()
{
materialChanged = true;
sharedMaterial = {};
material = {};
oldMaterial = {};
}
void SHRenderable::OnDestroy()
{
if (material)
{
material.Free();
material = {};
}
// Remove from SuperBatch
Handle<SHSuperBatch> superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
superBatch->Remove(this);
}
/*-----------------------------------------------------------------------------------*/
/* Material Functions */
/*-----------------------------------------------------------------------------------*/
void SHRenderable::SetMaterial(Handle<SHMaterialInstance> materialInstance)
{
// Ignore if same material set
if (!material && sharedMaterial == materialInstance)
return;
// Free copies of materials if any
if (material)
{
material.Free();
material = {};
}
// Flag that material was changed
materialChanged = true;
if (sharedMaterial)
oldMaterial = sharedMaterial->GetBaseMaterial();
// Update the 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;
}
void SHRenderable::ResetChangedFlag()
{
materialChanged = false;
oldMaterial = {};
}
}

View File

@ -0,0 +1,81 @@
/************************************************************************************//*!
\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"
#include "SH_API.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHMaterialInstance;
class SHMaterial;
class SHMesh;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*************************************************************************************/
/*!
\brief
Represents an object that should be rendered.
*/
/*************************************************************************************/
class SH_API SHRenderable final : public SHComponent
{
public:
/*-------------------------------------------------------------------------------*/
/* SHComponent Lifecycle Functions */
/*-------------------------------------------------------------------------------*/
void OnCreate() override final;
void OnDestroy() override final;
/*-------------------------------------------------------------------------------*/
/* Material Functions */
/*-------------------------------------------------------------------------------*/
void SetMaterial(Handle<SHMaterialInstance> materialInstance);
Handle<SHMaterialInstance> GetMaterial() const;
Handle<SHMaterialInstance> GetModifiableMaterial();
/*-------------------------------------------------------------------------------*/
/* Getter Functions */
/*-------------------------------------------------------------------------------*/
bool WasMaterialChanged() const noexcept { return materialChanged; }
Handle<SHMaterial> GetPrevMaterial() const noexcept { return oldMaterial; }
/*-------------------------------------------------------------------------------*/
/* Batcher Dispatcher Functions */
/*-------------------------------------------------------------------------------*/
void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this
/*-------------------------------------------------------------------------------*/
/* Data Members */
/*-------------------------------------------------------------------------------*/
Handle<SHMesh> Mesh;
SHMatrix TransformMatrix; // TODO: Replace with Transform component
private:
/*-------------------------------------------------------------------------------*/
/* Data Members */
/*-------------------------------------------------------------------------------*/
Handle<SHMaterialInstance> sharedMaterial;
Handle<SHMaterialInstance> material;
bool materialChanged = true;
Handle<SHMaterial> oldMaterial;
};
}

View File

@ -0,0 +1,67 @@
/************************************************************************************//*!
\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"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------------*/
SHRenderer::SHRenderer(Handle<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph)
: viewport { viewport }
, renderGraph { renderGraph }
{
cameraDescriptorSet = logicalDevice->CreateDescriptorSetGroup(descriptorPool, { cameraDescLayout }, { 1 });
cpuCameraData.resize(numFrames);
cameraDataAlignedSize = logicalDevice->PadUBOSize(sizeof(SHShaderCameraData));
}
/*-----------------------------------------------------------------------------------*/
/* Camera Registration */
/*-----------------------------------------------------------------------------------*/
void SHRenderer::SetCamera(Handle<SHCamera> _camera)
{
camera = _camera;
}
/*-----------------------------------------------------------------------------------*/
/* Drawing Functions */
/*-----------------------------------------------------------------------------------*/
void SHRenderer::Draw(uint32_t frameIndex, std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> graphScopeBuffers) noexcept
{
renderGraph->Execute(frameIndex, graphScopeBuffers);
}
void SHRenderer::BindDescriptorSet(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
}
Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept
{
return renderGraph;
}
}

View File

@ -0,0 +1,98 @@
/************************************************************************************//*!
\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 "Graphics/RenderGraph/SHRenderGraph.h"
#include "Math/SHMath.h"
#include <vector>
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkBuffer;
class SHVkRenderpass;
class SHVkFramebuffer;
class SHMaterial;
class SHVkLogicalDevice;
class SHViewport;
class SHVkImageView;
class SHVkCommandBuffer;
class SHCamera;
class SHVkDescriptorSetGroup;
class SHGraphicsGlobalData;
class SHVkDescriptorPool;
struct SHShaderCameraData
{
SHVec4 cameraPosition;
SHMatrix viewProjectionMatrix;
};
/*---------------------------------------------------------------------------------*/
/* 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<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph);
/*-----------------------------------------------------------------------------*/
/* Camera Registration */
/*-----------------------------------------------------------------------------*/
void SetCamera(Handle<SHCamera> _camera);
/*-----------------------------------------------------------------------------*/
/* Drawing Functions */
/*-----------------------------------------------------------------------------*/
void Draw(uint32_t frameIndex, std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> graphScopeBuffers) noexcept;
void BindDescriptorSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
/*-----------------------------------------------------------------------------*/
/* Setters and Getters */
/*-----------------------------------------------------------------------------*/
Handle<SHRenderGraph> GetRenderGraph (void) const noexcept;
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
//! Vulkan UBOs need to be aligned, this is pad SHShaderCameraData struct
uint32_t cameraDataAlignedSize;
Handle<SHViewport> viewport;
Handle<SHCamera> camera;
Handle<SHRenderGraph> renderGraph;
Handle<SHVkDescriptorSetGroup> cameraDescriptorSet;
std::vector<SHShaderCameraData> cpuCameraData;
};
}

View File

@ -0,0 +1,76 @@
/************************************************************************************//*!
\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"
#include "Resource/ResourceLibrary.h"
#include "Graphics/RenderGraph/SHRenderGraph.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, uint32_t numFrames, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph)
{
// Create the renderer
auto renderer = resourceManager.Create<SHRenderer>(device, numFrames, descriptorPool, cameraDescLayout, GetHandle(), renderGraph);
// 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,85 @@
/************************************************************************************//*!
\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;
class ResourceManager;
class SHRenderGraph;
class SHVkDescriptorPool;
class SHVkDescriptorSetLayout;
/*---------------------------------------------------------------------------------*/
/* 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, uint32_t numFrames, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph);
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; }
std::vector<Handle<SHRenderer>>& GetRenderers() { return renderers; }
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Handle<SHVkLogicalDevice> device;
vk::Viewport viewport;
std::vector<Handle<SHRenderer>> renderers;
};
}

View File

@ -0,0 +1,36 @@
/************************************************************************************//*!
\file SHPrimitiveGenerator.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 18, 2022
\brief Contains the static class definition of SHPrimitiveGenerator.
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 "Math/SHMath.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
namespace SHADE
{
/*************************************************************************************/
/*!
\brief
Static class that contains functions for generating 3D primitives.
*/
/*************************************************************************************/
struct SHMeshData
{
std::vector<SHMesh::VertexPosition> VertexPositions;
std::vector<SHMesh::VertexTexCoord> VertexTexCoords;
std::vector<SHMesh::VertexTangent> VertexTangents;
std::vector<SHMesh::VertexNormal> VertexNormals;
std::vector<SHMesh::Index> Indices;
};
}

View File

@ -0,0 +1,223 @@
/************************************************************************************//*!
\file SHPrimitiveGenerator.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 "SHPrimitiveGenerator.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
namespace SHADE
{
SHMeshData SHPrimitiveGenerator::Cube() noexcept
{
SHMeshData mesh;
mesh.VertexPositions =
{
// front
SHVec3(-0.5f, -0.5f, 0.5f),
SHVec3( 0.5f, -0.5f, 0.5f),
SHVec3( 0.5f, 0.5f, 0.5f),
SHVec3(-0.5f, 0.5f, 0.5f),
// back
SHVec3(-0.5f, -0.5f, -0.5f),
SHVec3(-0.5f, 0.5f, -0.5f),
SHVec3( 0.5f, 0.5f, -0.5f),
SHVec3( 0.5f, -0.5f, -0.5f),
// top
SHVec3(-0.5f, 0.5f, -0.5f),
SHVec3(-0.5f, 0.5f, 0.5f),
SHVec3( 0.5f, 0.5f, 0.5f),
SHVec3( 0.5f, 0.5f, -0.5f),
// bottom
SHVec3(-0.5f, -0.5f, -0.5f),
SHVec3( 0.5f, -0.5f, -0.5f),
SHVec3( 0.5f, -0.5f, 0.5f),
SHVec3(-0.5f, -0.5f, 0.5f),
// right
SHVec3(0.5f, -0.5f, -0.5f),
SHVec3(0.5f, 0.5f, -0.5f),
SHVec3(0.5f, 0.5f, 0.5f),
SHVec3(0.5f, -0.5f, 0.5f),
// left
SHVec3(-0.5f, -0.5f, -0.5f),
SHVec3(-0.5f, -0.5f, 0.5f),
SHVec3(-0.5f, 0.5f, 0.5f),
SHVec3(-0.5f, 0.5f, -0.5f)
};
mesh.VertexTexCoords =
{
SHVec2(0.0f, 1.0f),
SHVec2(1.0f, 1.0f),
SHVec2(1.0f, 0.0f),
SHVec2(0.0f, 0.0f),
SHVec2(0.0f, 1.0f),
SHVec2(1.0f, 1.0f),
SHVec2(1.0f, 0.0f),
SHVec2(0.0f, 0.0f),
SHVec2(0.0f, 1.0f),
SHVec2(1.0f, 1.0f),
SHVec2(1.0f, 0.0f),
SHVec2(0.0f, 0.0f),
SHVec2(0.0f, 1.0f),
SHVec2(1.0f, 1.0f),
SHVec2(1.0f, 0.0f),
SHVec2(0.0f, 0.0f),
SHVec2(0.0f, 1.0f),
SHVec2(1.0f, 1.0f),
SHVec2(1.0f, 0.0f),
SHVec2(0.0f, 0.0f),
SHVec2(0.0f, 1.0f),
SHVec2(1.0f, 1.0f),
SHVec2(1.0f, 0.0f),
SHVec2(0.0f, 0.0f)
};
mesh.VertexTangents =
{
// front
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
// back
SHVec3(-1.0f, 0.0f, 0.0f),
SHVec3(-1.0f, 0.0f, 0.0f),
SHVec3(-1.0f, 0.0f, 0.0f),
SHVec3(-1.0f, 0.0f, 0.0f),
// top
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
// bottom
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
// right
SHVec3(0.0f, 0.0f, -1.0f),
SHVec3(0.0f, 0.0f, -1.0f),
SHVec3(0.0f, 0.0f, -1.0f),
SHVec3(0.0f, 0.0f, -1.0f),
// left
SHVec3(0.0f, 0.0f, 1.0f),
SHVec3(0.0f, 0.0f, 1.0f),
SHVec3(0.0f, 0.0f, 1.0f),
SHVec3(0.0f, 0.0f, 1.0f)
};
mesh.VertexNormals =
{
// front
SHVec3(0.0f, 0.0f, 1.0f),
SHVec3(0.0f, 0.0f, 1.0f),
SHVec3(0.0f, 0.0f, 1.0f),
SHVec3(0.0f, 0.0f, 1.0f),
//back
SHVec3(0.0f, 0.0f, -1.0f),
SHVec3(0.0f, 0.0f, -1.0f),
SHVec3(0.0f, 0.0f, -1.0f),
SHVec3(0.0f, 0.0f, -1.0f),
// top
SHVec3(0.0f, 1.0f, 0.0f),
SHVec3(0.0f, 1.0f, 0.0f),
SHVec3(0.0f, 1.0f, 0.0f),
SHVec3(0.0f, 1.0f, 0.0f),
// bottom
SHVec3(0.0f, -1.0f, 0.0f),
SHVec3(0.0f, -1.0f, 0.0f),
SHVec3(0.0f, -1.0f, 0.0f),
SHVec3(0.0f, -1.0f, 0.0f),
// right
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
SHVec3(1.0f, 0.0f, 0.0f),
// left
SHVec3(-1.0f, 0.0f, 0.0f),
SHVec3(-1.0f, 0.0f, 0.0f),
SHVec3(-1.0f, 0.0f, 0.0f),
SHVec3(-1.0f, 0.0f, 0.0f)
};
mesh.Indices =
{
0, 1, 2, 0, 2, 3,
4, 5, 6, 4, 6, 7,
8, 9, 10, 8, 10, 11,
12, 13, 14, 12, 14, 15,
16, 17, 18, 16, 18, 19,
20, 21, 22, 20, 22, 23
};
return mesh;
}
Handle<SHMesh> SHPrimitiveGenerator::Cube(SHMeshLibrary& meshLibrary) noexcept
{
static SHMeshData meshData = Cube();
return meshLibrary.AddMesh
(
meshData.VertexPositions.size(),
meshData.VertexPositions.data(),
meshData.VertexTexCoords.data(),
meshData.VertexTangents.data(),
meshData.VertexNormals.data(),
meshData.Indices.size(),
meshData.Indices.data()
);
}
Handle<SHADE::SHMesh> SHPrimitiveGenerator::Cube(SHGraphicsSystem& gfxSystem) noexcept
{
static SHMeshData meshData = Cube();
return gfxSystem.AddMesh
(
meshData.VertexPositions.size(),
meshData.VertexPositions.data(),
meshData.VertexTexCoords.data(),
meshData.VertexTangents.data(),
meshData.VertexNormals.data(),
meshData.Indices.size(),
meshData.Indices.data()
);
}
}

View File

@ -0,0 +1,89 @@
/************************************************************************************//*!
\file SHPrimitiveGenerator.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 18, 2022
\brief Contains the static class definition of SHPrimitiveGenerator.
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"
#include "SHMeshData.h"
#include "SH_API.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHGraphicsSystem;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*************************************************************************************/
/*!
\brief
Static class that contains functions for generating 3D primitives.
*/
/*************************************************************************************/
class SH_API SHPrimitiveGenerator
{
public:
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
SHPrimitiveGenerator() = delete;
/*---------------------------------------------------------------------------------*/
/* Primitive Generation Functions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
Produces a cube and stores the data in a SHMeshData object.
\return
SHMeshData object containing vertex data for the cube.
*/
/***********************************************************************************/
[[nodiscard]] static SHMeshData Cube() noexcept;
/***********************************************************************************/
/*!
\brief
Produces a cube and constructs a SHMesh using the SHMeshLibrary provided.
\param meshLibrary
Reference to the SHMeshLibrary to procude and store a cube mesh in.
\return
SHMesh object that points to the generated cube mesh in the SHMeshLibrary.
*/
/***********************************************************************************/
[[nodiscard]] static Handle<SHMesh> Cube(SHMeshLibrary& meshLibrary) noexcept;
/***********************************************************************************/
/*!
\brief
Produces a cube and constructs a SHMesh using the SHGraphicsSystem provided.
\param gfxSystem
Reference to the SHGraphicsSystem to produce and store a cube mesh in.
\return
SHMesh object that points to the generated cube mesh in the SHGraphicsSystem.
*/
/***********************************************************************************/
[[nodiscard]] static Handle<SHMesh> Cube(SHGraphicsSystem& gfxSystem) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] static SHMeshData genCubeData() noexcept;
};
}

View File

@ -0,0 +1,54 @@
#include "SHpch.h"
#include "SHPipelineLibrary.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
namespace SHADE
{
Handle<SHVkPipeline> SHPipelineLibrary::CreateDrawPipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept
{
SHPipelineLayoutParams params
{
.shaderModules = {vsFsPair.first, vsFsPair.second},
.globalDescSetLayouts = globalData->GetDescSetLayouts()
};
// 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(globalData->GetDefaultViState());
// Actually construct the pipeline
newPipeline->ConstructPipeline();
// Emplace the new pipeline
pipelines.emplace (vsFsPair, newPipeline);
return newPipeline;
}
void SHPipelineLibrary::Init(Handle<SHVkLogicalDevice> device, Handle<SHGraphicsGlobalData> inGlobalData) noexcept
{
logicalDevice = device;
globalData = inGlobalData;
}
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,46 @@
#pragma once
#include <unordered_map>
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
namespace SHADE
{
class SHVRenderpass;
class SHVkDescriptorSetLayouts;
class SHVkPipeline;
class SHSubpass;
class SHGraphicsGlobalData;
// 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
//! 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>> pipelines;
// Global data
Handle<SHGraphicsGlobalData> globalData;
public:
void Init (Handle<SHVkLogicalDevice> device, Handle<SHGraphicsGlobalData> inGlobalData) 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,
Handle<SHSubpass> subpass
) 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

@ -269,4 +269,40 @@ namespace SHADE
}
SHShaderData::SHShaderData(SHShaderData const& rhs) noexcept
: spirvBinary{rhs.spirvBinary}
, shaderType{ rhs.shaderType}
, name{rhs.name }
, id{rhs.id }
{
}
SHShaderData& SHShaderData::operator=(SHShaderData const& rhs) noexcept
{
if (this == &rhs)
return *this;
spirvBinary = rhs.spirvBinary;
shaderType = rhs.shaderType;
name = rhs.name;
id = rhs.id;
return *this;
}
SHShaderData& SHShaderData::operator=(SHShaderData&& rhs) noexcept
{
if (this == &rhs)
return *this;
spirvBinary = std::move(rhs.spirvBinary);
shaderType = std::move (rhs.shaderType);
name = std::move (rhs.name);
id = std::move (rhs.id);
return *this;
}
}

View File

@ -25,7 +25,10 @@ namespace SHADE
uint32_t id;
SHShaderData(void) noexcept;
SHShaderData(SHShaderData const& rhs) noexcept;
SHShaderData(SHShaderData&& rhs) noexcept;
SHShaderData& operator= (SHShaderData&& rhs) noexcept;
SHShaderData& operator= (SHShaderData const& rhs) noexcept;
};
// TODO: This class is purely temporary and will be converted/changed when XQ implements his resource manager

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

@ -1,5 +1,6 @@
#include "SHPch.h"
#include "SHPipelineState.h"
#include "Graphics/RenderGraph/SHRenderGraph.h"
namespace SHADE
{
@ -61,10 +62,10 @@ namespace SHADE
renderpassHdl = inRenderpassHdl;
}
void SHVkPipelineState::SetSubpassIndex(uint32_t index) noexcept
void SHVkPipelineState::SetSubpass(Handle<SHSubpass> sp) noexcept
{
dirty = true;
subpassIndex = index;
subpass = sp;
}
SHVertexInputState const& SHVkPipelineState::GetVertexInputState(void) const noexcept
@ -107,9 +108,9 @@ namespace SHADE
return renderpassHdl;
}
uint32_t SHVkPipelineState::GetSubpassIndex(void) const noexcept
Handle<SHSubpass> SHVkPipelineState::GetSubpass(void) noexcept
{
return subpassIndex;
return subpass;
}
void SHVkPipelineState::SetDirty(bool isDirty) noexcept
@ -203,6 +204,8 @@ namespace SHADE
// Offset is 0 at first (for first element)
uint32_t offset = 0;
binding.binding = static_cast<uint32_t>(bindings.size() - 1);
// for every attribute passed in
for (auto const& attrib : inAttribs)
{

View File

@ -8,6 +8,8 @@
namespace SHADE
{
class SHSubpass;
// This is mainly for non-interleaved attributes where we have a separate buffer for
// each vertex attribute.
struct SHVertexInputState
@ -62,7 +64,7 @@ namespace SHADE
vk::CullModeFlags cull_mode{ vk::CullModeFlagBits::eBack };
//! CW or CCW
vk::FrontFace frontFacingOrientation{ vk::FrontFace::eCounterClockwise };
vk::FrontFace frontFacingOrientation{ vk::FrontFace::eClockwise };
bool depthBias{ VK_FALSE };
};
@ -120,7 +122,7 @@ namespace SHADE
bool depthWrite{ VK_TRUE };
// Note: Using Reversed depth-buffer for increased precision, so Greater depth values are kept
vk::CompareOp depthCompare{ vk::CompareOp::eGreater };
vk::CompareOp depthCompare{ vk::CompareOp::eLess };
bool depthBounds{ VK_FALSE };
@ -133,11 +135,24 @@ namespace SHADE
struct SHColorBlendState
{
VkBool32 logic_op_enable{ VK_TRUE };
VkBool32 logic_op_enable{ VK_FALSE };
vk::LogicOp logic_op{ VK_LOGIC_OP_COPY };
std::vector<vk::PipelineColorBlendAttachmentState> attachments;
std::vector<vk::PipelineColorBlendAttachmentState> attachments =
{
vk::PipelineColorBlendAttachmentState
{
.blendEnable = true,
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
}
};
};
// TODO: Specialization constants
@ -152,31 +167,31 @@ namespace SHADE
bool dirty{ false };
//! Vertex input state
SHVertexInputState vertexInputState;
SHVertexInputState vertexInputState;
//! Input assembly
SHInputAssemblyState inputAssemblyState;
SHInputAssemblyState inputAssemblyState;
//! Rasterization state
SHRasterizationState rasterizationState;
SHRasterizationState rasterizationState;
//! Viewport state
SHViewportState viewportState;
SHViewportState viewportState;
//! Multisample state
SHMultisampleState multisampleState;
SHMultisampleState multisampleState;
//! Depth Stencil state
SHDepthStencilState depthStencilState;
SHDepthStencilState depthStencilState;
//! Color blend state
SHColorBlendState colorBlendState;
SHColorBlendState colorBlendState;
//! Renderpass that is compatible with the pipeline
Handle<SHVkRenderpass> renderpassHdl;
Handle<SHVkRenderpass> renderpassHdl;
//! Subpass index
uint32_t subpassIndex;
Handle<SHSubpass> subpass;
friend class SHVkPipeline;
public:
@ -189,7 +204,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;
@ -198,17 +213,17 @@ namespace SHADE
void SetDepthStencilState (SHDepthStencilState const& state) noexcept;
void SetColorBlenState (SHColorBlendState const& state) noexcept;
void SetRenderpass (Handle<SHVkRenderpass> const& inRenderpassHdl) noexcept;
void SetSubpassIndex (uint32_t index) noexcept;
void SetSubpass (Handle<SHSubpass> sp) noexcept;
SHVertexInputState const& GetVertexInputState (void) const noexcept;
SHInputAssemblyState const& GetInputAssemblyState (void) const noexcept;
SHRasterizationState const& GetRasterizationState (void) const noexcept;
SHViewportState const& GetViewportState (void) const noexcept;
SHMultisampleState const& GetMultisampleState (void) const noexcept;
SHDepthStencilState const& GetDepthStencilState (void) const noexcept;
SHColorBlendState const& GetColorBlenState (void) const noexcept;
Handle<SHVkRenderpass> const& GetRenderpass (void) const noexcept;
uint32_t GetSubpassIndex (void) const noexcept;
SHVertexInputState const& GetVertexInputState (void) const noexcept;
SHInputAssemblyState const& GetInputAssemblyState (void) const noexcept;
SHRasterizationState const& GetRasterizationState (void) const noexcept;
SHViewportState const& GetViewportState (void) const noexcept;
SHMultisampleState const& GetMultisampleState (void) const noexcept;
SHDepthStencilState const& GetDepthStencilState (void) const noexcept;
SHColorBlendState const& GetColorBlenState (void) const noexcept;
Handle<SHVkRenderpass> const& GetRenderpass (void) const noexcept;
Handle<SHSubpass> GetSubpass (void) noexcept;
void SetDirty(bool isDirty) noexcept;
};

View File

@ -3,6 +3,7 @@
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/Debugging/SHVulkanDebugUtil.h"
#include "Graphics/RenderGraph/SHRenderGraph.h"
namespace SHADE
{
@ -154,7 +155,7 @@ namespace SHADE
gpCreateInfo.layout = pipelineLayout->GetVkPipelineLayout();
gpCreateInfo.renderPass = pipelineState.GetRenderpass()->GetVkRenderpass();
gpCreateInfo.subpass = pipelineState.GetSubpassIndex();
gpCreateInfo.subpass = pipelineState.GetSubpass()->GetIndex();
gpCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
gpCreateInfo.basePipelineIndex = -1;
@ -204,8 +205,8 @@ namespace SHADE
*/
/***************************************************************************/
SHVkPipeline::SHVkPipeline(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkPipelineLayout> const& inPipelineLayout, SHVkPipelineState const* const state, Handle<SHVkRenderpass> const& renderpassHdl, uint32_t subpass, SH_PIPELINE_TYPE type) noexcept
: pipelineState{ } // copy the pipeline state
SHVkPipeline::SHVkPipeline(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkPipelineLayout> const& inPipelineLayout, SHVkPipelineState const* const state, Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHSubpass> subpass, SH_PIPELINE_TYPE type) noexcept
: pipelineState{ }
, pipelineType {type}
, vkPipeline {VK_NULL_HANDLE}
, logicalDeviceHdl{ inLogicalDeviceHdl }
@ -222,8 +223,8 @@ namespace SHADE
}
else
{
pipelineState.SetRenderpass(renderpassHdl);
pipelineState.SetSubpassIndex(subpass);
pipelineState.SetRenderpass (renderpassHdl);
pipelineState.SetSubpass (subpass);
}
}

View File

@ -9,6 +9,7 @@
namespace SHADE
{
class SHVkLogicalDevice;
class SHSubpass;
class SHVkPipeline
{
@ -50,7 +51,7 @@ namespace SHADE
Handle<SHVkPipelineLayout> const& inPipelineLayout,
SHVkPipelineState const* const state,
Handle<SHVkRenderpass> const& renderpassHdl,
uint32_t subpass,
Handle<SHSubpass> subpass,
SH_PIPELINE_TYPE type) noexcept;
SHVkPipeline (SHVkPipeline&& rhs) noexcept;

View File

@ -124,4 +124,9 @@ namespace SHADE
return result;
}
vk::Queue SHVkQueue::GetVkQueue() noexcept
{
return vkQueue;
}
}

View File

@ -49,6 +49,7 @@ namespace SHADE
void SubmitCommandBuffer (std::initializer_list<Handle<SHVkCommandBuffer>> cmdBuffers, std::initializer_list<Handle<SHVkSemaphore>> signalSems = {}, std::initializer_list<Handle<SHVkSemaphore>> waitSems = {}, vk::PipelineStageFlags waitDstStageMask = {}, Handle<SHVkFence> const& fence = {}) noexcept;
vk::Result Present (Handle<SHVkSwapchain> const& swapchain, std::initializer_list<Handle<SHVkSemaphore>> waitSems, uint32_t frameIndex) noexcept;
vk::Queue GetVkQueue() noexcept;
};
}

View File

@ -1,4 +1,4 @@
#include "SHPch.h"
#include "SHPch.h"
#include "SHRenderGraph.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
@ -6,6 +6,7 @@
#include "Graphics/Images/SHVkImage.h"
#include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Tools/SHLogger.h"
namespace SHADE
@ -209,12 +210,17 @@ namespace SHADE
*/
/***************************************************************************/
SHRenderGraphNode::SHSubpass::SHSubpass(Handle<SHRenderGraphNode> const& parent, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
SHSubpass::SHSubpass(ResourceManager& rm, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
: resourceAttachmentMapping{ mapping }
, ptrToResources{ resources }
, parentNode{ parent }
, subpassIndex{ index }
, superBatch{}
, colorReferences{}
, depthReferences{}
, inputReferences{}
{
superBatch = rm.Create<SHSuperBatch>(GetHandle());
}
/***************************************************************************/
@ -228,8 +234,11 @@ namespace SHADE
*/
/***************************************************************************/
SHRenderGraphNode::SHSubpass::SHSubpass(SHSubpass&& rhs) noexcept
: colorReferences{ std::move(rhs.colorReferences) }
SHSubpass::SHSubpass(SHSubpass&& rhs) noexcept
: subpassIndex{ std::move(rhs.subpassIndex) }
, parentNode{ std::move(rhs.parentNode) }
, superBatch{ std::move(rhs.superBatch) }
, colorReferences{ std::move(rhs.colorReferences) }
, depthReferences{ std::move(rhs.depthReferences) }
, inputReferences{ std::move(rhs.inputReferences) }
, resourceAttachmentMapping{ rhs.resourceAttachmentMapping }
@ -249,11 +258,14 @@ namespace SHADE
*/
/***************************************************************************/
SHRenderGraphNode::SHSubpass& SHRenderGraphNode::SHSubpass::operator=(SHSubpass&& rhs) noexcept
SHSubpass& SHSubpass::operator=(SHSubpass&& rhs) noexcept
{
if (this == &rhs)
return *this;
subpassIndex = std::move(rhs.subpassIndex);
parentNode = std::move(rhs.parentNode);
superBatch = std::move(rhs.superBatch);
colorReferences = std::move(rhs.colorReferences);
depthReferences = std::move(rhs.depthReferences);
inputReferences = std::move(rhs.inputReferences);
@ -275,7 +287,7 @@ namespace SHADE
*/
/***************************************************************************/
void SHRenderGraphNode::SHSubpass::AddColorOutput(std::string resourceToReference) noexcept
void SHSubpass::AddColorOutput(std::string resourceToReference) noexcept
{
colorReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eColorAttachmentOptimal });
}
@ -296,7 +308,7 @@ namespace SHADE
*/
/***************************************************************************/
void SHRenderGraphNode::SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType) noexcept
void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType) noexcept
{
vk::ImageLayout imageLayout;
switch (attachmentDescriptionType)
@ -329,14 +341,15 @@ namespace SHADE
*/
/***************************************************************************/
void SHRenderGraphNode::SHSubpass::AddInput(std::string resourceToReference) noexcept
void SHSubpass::AddInput(std::string resourceToReference) noexcept
{
inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
}
void SHRenderGraphNode::SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer) noexcept
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer) noexcept
{
// Draw all the batches
superBatch->Draw(commandBuffer);
// Draw all the exterior draw calls
for (auto& drawCall : exteriorDrawCalls)
@ -345,7 +358,7 @@ namespace SHADE
}
}
void SHRenderGraphNode::SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
{
exteriorDrawCalls.push_back(newDrawCall);
}
@ -361,11 +374,21 @@ namespace SHADE
*/
/***************************************************************************/
Handle<SHRenderGraphNode> const& SHRenderGraphNode::SHSubpass::GetParentNode(void) const noexcept
Handle<SHRenderGraphNode> const& SHSubpass::GetParentNode(void) const noexcept
{
return parentNode;
}
SHADE::SHSubPassIndex SHSubpass::GetIndex() const noexcept
{
return subpassIndex;
}
Handle<SHSuperBatch> SHSubpass::GetSuperBatch(void) const noexcept
{
return superBatch;
}
/***************************************************************************/
/*!
@ -433,7 +456,7 @@ namespace SHADE
*/
/***************************************************************************/
SHRenderGraphNode::SHRenderGraphNode(ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept
SHRenderGraphNode::SHRenderGraphNode(ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources, Handle<SHGraphicsGlobalData> globalData) noexcept
: logicalDeviceHdl{ logicalDevice }
, renderpass{}
, framebuffers{}
@ -447,6 +470,9 @@ namespace SHADE
, resourceManager{ rm }
, ptrToResources{ resources }
{
// pipeline library initialization
pipelineLibrary.Init(logicalDeviceHdl, globalData);
attachmentDescriptions.resize(attResources.size());
bool containsSwapchainImage = false;
@ -535,7 +561,7 @@ namespace SHADE
*/
/***************************************************************************/
Handle<SHRenderGraphNode::SHSubpass> SHRenderGraphNode::AddSubpass(std::string subpassName) noexcept
Handle<SHSubpass> SHRenderGraphNode::AddSubpass(std::string subpassName) noexcept
{
// if subpass already exists, don't add.
if (subpassIndexing.contains(subpassName))
@ -545,9 +571,14 @@ namespace SHADE
}
// Add subpass to container and create mapping for it
subpasses.emplace_back(resourceManager.Create<SHSubpass>(GetHandle(), &resourceAttachmentMapping, ptrToResources));
subpasses.emplace_back(resourceManager.Create<SHSubpass>(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
return subpasses.at(subpassIndexing[subpassName]);
Handle<SHSubpass> subpass = subpasses.back();
// Register the SuperBatch
batcher.RegisterSuperBatch(subpass->GetSuperBatch());
return subpass;
}
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept
@ -567,6 +598,34 @@ namespace SHADE
commandBuffer->EndRenderpass();
}
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
{
// verify subpass exists
if (subpass->GetIndex() >= subpasses.size())
{
SHLOG_ERROR("Subpass index passed in is not valid. RenderGraphNode does not have that many passes. ");
return {};
}
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetDrawPipline(vsFsPair);
if (!pipeline)
{
pipeline = pipelineLibrary.CreateDrawPipeline
(
vsFsPair,
renderpass,
subpass
);
}
return pipeline;
}
void SHRenderGraphNode::FinaliseBatch()
{
batcher.FinaliseBatches(logicalDeviceHdl);
}
/***************************************************************************/
/*!
@ -583,6 +642,11 @@ namespace SHADE
return renderpass;
}
Handle<SHSubpass> SHRenderGraphNode::GetSubpass(std::string_view subpassName) const noexcept
{
return subpasses[subpassIndexing.at(subpassName.data())];
}
/***************************************************************************/
/*!
@ -892,11 +956,12 @@ namespace SHADE
/***************************************************************************/
void SHRenderGraph::ConfigureCommands(void) noexcept
{
commandPool = logicalDeviceHdl->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
//commandPools.resize (static_cast<std::size_t>(swapchainHdl->GetNumImages()));
commandBuffers.resize(static_cast<std::size_t>(swapchainHdl->GetNumImages()));
for (auto& cmdBuffer : commandBuffers)
for (uint32_t i = 0; i < commandBuffers.size(); ++i)
{
cmdBuffer = commandPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
commandBuffers[i] = commandPools[i]->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
}
}
@ -915,10 +980,12 @@ namespace SHADE
*/
/***************************************************************************/
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHVkCommandPool>> const& cmdPools, Handle<SHGraphicsGlobalData> inGlobalData) noexcept
{
logicalDeviceHdl = logicalDevice;
swapchainHdl = swapchain;
globalData = inGlobalData;
commandPools = cmdPools;
}
/***************************************************************************/
@ -996,7 +1063,7 @@ namespace SHADE
}
}
nodes.emplace_back(resourceManager.Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(resources), std::move(predecessors), &graphResources));
nodes.emplace_back(resourceManager.Create<SHRenderGraphNode>(resourceManager, logicalDeviceHdl, swapchainHdl, std::move(resources), std::move(predecessors), &graphResources, globalData));
nodeIndexing.emplace(nodeName, static_cast<uint32_t>(nodes.size()) - 1u);
return nodes.at(nodeIndexing[nodeName]);
}
@ -1023,23 +1090,40 @@ namespace SHADE
ConfigureCommands();
}
void SHRenderGraph::Execute(uint32_t frameIndex) noexcept
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
// better way to manage these
void SHRenderGraph::Execute(uint32_t frameIndex, std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> graphScopeBuffers) noexcept
{
commandPool->Reset();
//commandPools[frameIndex]->Reset();
auto& cmdBuffer = commandBuffers[frameIndex];
cmdBuffer->BeginRecording();
cmdBuffer->SetviewportScissor(1920.0f, 1080.0f, 1920, 1080);
// TODO: DON'T HARDCODE THIS
cmdBuffer->SetViewportScissor(1920.0f, 1080.0f, 1920, 1080);
for (auto& node : nodes)
for (auto& [buffer, bindingPoint]: graphScopeBuffers)
{
node->Execute(commandBuffers[frameIndex], frameIndex);
if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer)
cmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0);
else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer)
cmdBuffer->BindIndexBuffer(buffer, 0);
}
for (auto& node : nodes)
node->Execute(cmdBuffer, frameIndex);
cmdBuffer->EndRecording();
}
void SHRenderGraph::FinaliseBatch()
{
for (auto& node : nodes)
{
node->FinaliseBatch();
}
}
Handle<SHRenderGraphNode> SHRenderGraph::GetNode(std::string const& nodeName) const noexcept
{
if (nodeIndexing.contains(nodeName))

View File

@ -4,6 +4,9 @@
#include "Graphics/Renderpass/SHVkRenderpass.h"
#include "Resource/ResourceLibrary.h"
#include "SH_API.h"
#include "Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.h"
#include "Graphics/MiddleEnd/Batching/SHSuperBatch.h"
#include "../MiddleEnd/Batching/SHBatcher.h"
#include <string>
#include <map>
@ -18,6 +21,8 @@ namespace SHADE
class SHVkFramebuffer;
class SHVkCommandPool;
class SHVkCommandBuffer;
class SHRenderGraphNode;
class SHGraphicsGlobalData;
// Used for attachment description creation for renderpass node
enum class SH_ATT_DESC_TYPE
@ -29,6 +34,7 @@ namespace SHADE
DEPTH_STENCIL,
};
class SH_API SHRenderGraphResource
{
private:
@ -69,7 +75,78 @@ namespace SHADE
SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept;
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource (void) noexcept;
~SHRenderGraphResource(void) noexcept;
friend class SHRenderGraphNode;
friend class SHRenderGraph;
};
class SH_API SHSubpass : public ISelfHandle<SHSubpass>
{
private:
/*---------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
/*---------------------------------------------------------------------*/
//! The index of the subpass in the render graph
uint32_t subpassIndex;
//! The parent renderpass that this subpass belongs to
Handle<SHRenderGraphNode> parentNode;
//!
Handle<SHSuperBatch> superBatch;
//! Color attachments
std::vector<vk::AttachmentReference> colorReferences;
//! Depth attachments
std::vector<vk::AttachmentReference> depthReferences;
//! Input attachments
std::vector<vk::AttachmentReference> inputReferences;
//! For getting attachment reference indices using handles
std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
//! Pointer to resources in the render graph (for getting handle IDs)
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
//! Sometimes there exists entities that we want to render onto a render target
//! but don't want it to come from the batching system. An example would be ImGUI.
//! For these entities we want to link a function from the outside and draw them
//! after we draw everything from the batch. Because of this, these draw calls
//! are always the last things drawn, so DO NOT USE THIS FUNCTIONALITY FOR ANYTHING
//! COMPLEX.
std::vector<std::function<void(Handle<SHVkCommandBuffer>&)>> exteriorDrawCalls;
public:
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHSubpass(ResourceManager& rm, Handle<SHRenderGraphNode> const& parent, uint32_t index, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept;
SHSubpass(SHSubpass&& rhs) noexcept;
SHSubpass& operator=(SHSubpass&& rhs) noexcept;
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
// Preparation functions
void AddColorOutput(std::string resourceToReference) noexcept;
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType = SH_ATT_DESC_TYPE::DEPTH_STENCIL) noexcept;
void AddInput(std::string resourceToReference) noexcept;
// Runtime functions
void Execute(Handle<SHVkCommandBuffer>& commandBuffer) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
/*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/
Handle<SHRenderGraphNode> const& GetParentNode(void) const noexcept;
SHSubPassIndex GetIndex() const noexcept;
Handle<SHSuperBatch> GetSuperBatch (void) const noexcept;
friend class SHRenderGraphNode;
friend class SHRenderGraph;
@ -77,69 +154,6 @@ namespace SHADE
class SH_API SHRenderGraphNode : public ISelfHandle<SHRenderGraphNode>
{
public:
class SH_API SHSubpass
{
public:
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHSubpass(Handle<SHRenderGraphNode> const& parent, std::unordered_map<uint64_t, uint32_t> const* mapping, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources) noexcept;
SHSubpass(SHSubpass&& rhs) noexcept;
SHSubpass& operator=(SHSubpass&& rhs) noexcept;
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
// Preparation functions
void AddColorOutput (std::string resourceToReference) noexcept;
void AddDepthOutput (std::string resourceToReference, SH_ATT_DESC_TYPE attachmentDescriptionType = SH_ATT_DESC_TYPE::DEPTH_STENCIL) noexcept;
void AddInput (std::string resourceToReference) noexcept;
// Runtime functions
void Execute (Handle<SHVkCommandBuffer>& commandBuffer) noexcept;
void AddExteriorDrawCalls (std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
/*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/
Handle<SHRenderGraphNode> const& GetParentNode (void) const noexcept;
private:
/*---------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
/*---------------------------------------------------------------------*/
//! The parent renderpass that this subpass belongs to
Handle<SHRenderGraphNode> parentNode;
//! Color attachments
std::vector<vk::AttachmentReference> colorReferences;
//! Depth attachments
std::vector<vk::AttachmentReference> depthReferences;
//! Input attachments
std::vector<vk::AttachmentReference> inputReferences;
//! For getting attachment reference indices using handles
std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
//! Pointer to resources in the render graph (for getting handle IDs)
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
//! Sometimes there exists entities that we want to render onto a render target
//! but don't want it to come from the batching system. An example would be ImGUI.
//! For these entities we want to link a function from the outside and draw them
//! after we draw everything from the batch. Because of this, these draw calls
//! are always the last things drawn, so DO NOT USE THIS FUNCTIONALITY FOR ANYTHING
//! COMPLEX.
std::vector<std::function<void(Handle<SHVkCommandBuffer>&)>> exteriorDrawCalls;
friend class SHRenderGraphNode;
friend class SHRenderGraph;
};
private:
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
@ -184,12 +198,16 @@ namespace SHADE
//! Pointer to resources in the render graph (for getting handle IDs)
std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* ptrToResources;
//! Every renderpass will require a pipeline library that will contain pipelines compatible with this renderpass
SHPipelineLibrary pipelineLibrary;
//! Whether or not the node has finished execution
bool executed;
//! Whether or not the node has been configured already or not
bool configured;
SHBatcher batcher;
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */
@ -201,21 +219,24 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHRenderGraphNode (ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources) noexcept;
SHRenderGraphNode (ResourceManager& rm, Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHRenderGraphResource>> attRes, std::vector<Handle<SHRenderGraphNode>> predecessors, std::unordered_map<std::string, Handle<SHRenderGraphResource>> const* resources, Handle<SHGraphicsGlobalData> globalData) noexcept;
SHRenderGraphNode(SHRenderGraphNode&& rhs) noexcept;
SHRenderGraphNode& operator= (SHRenderGraphNode&& rhs) noexcept;
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
Handle<SHSubpass> AddSubpass (std::string subpassName) noexcept;
void Execute (Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
Handle<SHSubpass> AddSubpass (std::string subpassName) noexcept;
// TODO: RemoveSubpass()
void Execute (Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
Handle<SHVkPipeline> GetOrCreatePipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
void FinaliseBatch();
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
Handle<SHVkRenderpass> GetRenderpass (void) const noexcept;
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
friend class SHRenderGraph;
};
@ -251,12 +272,14 @@ namespace SHADE
//! Resource library for graph handles
ResourceManager resourceManager;
//! Command pool for the render graph
Handle<SHVkCommandPool> commandPool;
//! Command pool for the render graph. DO NOT RESET OR FREE THESE, THEY ARE NON-OWNING. TODO: If application is multithreaded, we need more pools.
std::vector<Handle<SHVkCommandPool>> commandPools;
//! Command buffers for the render graph
std::vector<Handle<SHVkCommandBuffer>> commandBuffers;
//! Handle to global data
Handle<SHGraphicsGlobalData> globalData;
public:
/*-----------------------------------------------------------------------*/
@ -267,11 +290,12 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain) noexcept;
void AddResource (std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageCreateFlagBits createFlags = {});
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<std::string> resourceNames, std::initializer_list<std::string> predecessorNodes) noexcept;
void Generate (void) noexcept;
void Execute (uint32_t frameIndex) noexcept;
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHVkCommandPool>> const& cmdPools, Handle<SHGraphicsGlobalData> inGlobalData) noexcept;
void AddResource (std::string resourceName, SH_ATT_DESC_TYPE type, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageCreateFlagBits createFlags = {});
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<std::string> resourceNames, std::initializer_list<std::string> predecessorNodes) noexcept;
void Generate (void) noexcept;
void Execute (uint32_t frameIndex, std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> graphScopeBuffers) noexcept;
void FinaliseBatch();
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */

View File

@ -10,6 +10,10 @@ namespace SHADE
{
class SHVkLogicalDevice;
class SHVkFramebuffer;
/*-----------------------------------------------------------------------*/
/* TYPE DEFINTIIONS */
/*-----------------------------------------------------------------------*/
using SHSubPassIndex = uint32_t;
class SHVkRenderpass
{

View File

@ -1,6 +1,10 @@
#include "SHPch.h"
#include "SHVkUtil.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
namespace SHADE
{
@ -19,4 +23,52 @@ namespace SHADE
IsDepthOnlyFormat(format);
}
void SHVkUtil::EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
{
if (bufferHandle)
{
// Resize
bufferHandle->ResizeReplace(size, src, size);
}
else
{
// Create new
using BuffUsage = vk::BufferUsageFlagBits;
bufferHandle = device->CreateBuffer
(
size,
src,
size,
usage | BuffUsage::eTransferDst,
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT
);
}
// Order transfers
bufferHandle->TransferToDeviceResource(cmdBuffer);
}
void SHVkUtil::EnsureBufferAndCopyHostVisibleData(Handle<SHVkLogicalDevice> device, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage)
{
if (bufferHandle)
{
// Resize
bufferHandle->ResizeReplace(size, src, size); // TODO: Set to host visible method?
}
else
{
// Create new
using BuffUsage = vk::BufferUsageFlagBits;
bufferHandle = device->CreateBuffer
(
size,
src,
size,
usage,
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT
);
}
}
}

View File

@ -3,13 +3,79 @@
#include "SHVulkanIncludes.h"
#include "Resource/Handle.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkLogicalDevice;
class SHVkCommandBuffer;
class SHVkBuffer;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
class SHVkUtil
{
public:
static bool IsDepthOnlyFormat (vk::Format format) noexcept;
static bool IsDepthStencilAttachment(vk::Format format) noexcept;
/***********************************************************************************/
/*!
\brief
Ensures that the specified bufferHandle contains a non-host visible buffer that
fits the specified size and creates it if it does not exist. This follows by
issuing a transfer command into the created buffer.
All created buffers will use VMA_MEMORY_USAGE_AUTO and
VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
\param device
Device used to create the SHVkBuffer.
\param cmdBuffer
CommandBuffer which commands for issuing transferring the data to the GPU.
\param bufferHandle
Reference to the handle that holds any existing buffer or will be used to hold the
created buffer.
\param src
Data to copy from.
\param size
Size of data to copy.
\param usage
Usage flags for the buffer.
*/
/***********************************************************************************/
static void EnsureBufferAndCopyData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage);
/***********************************************************************************/
/*!
\brief
Ensures that the specified bufferHandle contains a host visible buffer that fits
the specified size and creates it if it does not exist. This follows by copying
the data from the specified source to the buffer.
All created buffers will use VMA_MEMORY_USAGE_AUTO and
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT.
\param device
Device used to create the SHVkBuffer.
\param bufferHandle
Reference to the handle that holds any existing buffer or will be used to hold the
created buffer.
\param src
Data to copy from.
\param size
Size of data to copy.
\param usage
Usage flags for the buffer.
*/
/***********************************************************************************/
static void EnsureBufferAndCopyHostVisibleData(Handle<SHVkLogicalDevice> device, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage);
};
}

View File

@ -1,35 +1,55 @@
#include "SHPch.h"
#include "SHShaderBlockInterface.h"
#include "Tools/SHLogger.h"
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;
}
variables.emplace_back(std::move(newVariable));
variableIndexing.try_emplace(std::move(name), static_cast<uint32_t>(variables.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));
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
{
if (!variableIndexing.contains(variableName))
throw std::invalid_argument("Attempted to retrieve index to variable that does not exist!");
return variableIndexing.at(variableName);
}
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 { rhs.bytesRequired }
{}
void SHShaderBlockInterface::SetBytesRequired(uint32_t bytes) noexcept
{
@ -46,16 +66,11 @@ namespace SHADE
{
if (&rhs == this)
return *this;
variables = std::move(rhs.variables);
bytesRequired = std::move(rhs.bytesRequired);
variableIndexing = std::move(rhs.variableIndexing);
bytesRequired = 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;

View File

@ -14,6 +14,7 @@
#include <string>
#include "Vector/SHVec4.h"
#include "SH_API.h"
namespace SHADE
{
@ -32,7 +33,7 @@ namespace SHADE
/**
* @brief Interface for a Column-Major Row Vector 4x4 Matrix.
*/
class SHMatrix : public DirectX::XMFLOAT4X4
class SH_API SHMatrix : public DirectX::XMFLOAT4X4
{
public:
/*---------------------------------------------------------------------------------*/

View File

@ -10,7 +10,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
template<typename T>
class ResourceLibrary;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
@ -89,7 +89,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
Handle() = default;
~Handle() = default;
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
@ -190,6 +190,33 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
Handle<T> handle;
};
}
namespace std
{
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// std::hash template specialization for Handle<T>
/// </summary>
/// <typeparam name="T">Type for the Handle.</typeparam>
template<typename T>
struct hash<SHADE::Handle<T>>
{
std::size_t operator() (const SHADE::Handle<T>& hdl) const;
};
/// <summary>
/// std::hash template specialization for std::pair<Handle<T1>, Handle<T2>>
/// </summary>
/// <typeparam name="T">Type for the first Handle.</typeparam>
/// <typeparam name="T">Type for the second Handle.</typeparam>
template<typename T1, typename T2>
struct hash<std::pair<SHADE::Handle<T1>, SHADE::Handle<T2>>>
{
std::size_t operator() (std::pair<SHADE::Handle<T1>, SHADE::Handle<T2>> const& pair) const;
};
}
#include "Handle.hpp"

View File

@ -1,6 +1,7 @@
#pragma once
// Primary Header
#include "Handle.h"
#include "ResourceLibrary.h"
namespace SHADE
{
@ -14,16 +15,16 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* HandleBase - Overloaded Operators */
/*---------------------------------------------------------------------------------*/
inline HandleBase::operator bool() const
/*---------------------------------------------------------------------------------*/
{
return id.Raw != INVALID_ID.Raw;
}
/*---------------------------------------------------------------------------------*/
/* Handle<T> - Usage Functions */
/*---------------------------------------------------------------------------------*/
template<typename T>
template<typename T>
inline void Handle<T>::Free()
{
library->Free(*this);
@ -94,3 +95,23 @@ namespace SHADE
handle = hdl;
}
}
namespace std
{
/*---------------------------------------------------------------------------------*/
/* std::hash Template Specializations */
/*---------------------------------------------------------------------------------*/
template <typename T>
std::size_t hash<SHADE::Handle<T>>::operator()(const SHADE::Handle<T>& hdl) const
{
return std::hash<uint64_t>{}(hdl.GetId().Raw);
}
template <typename T1, typename T2>
std::size_t hash<pair<SHADE::Handle<T1>, SHADE::Handle<T2>>>::operator()(
std::pair<SHADE::Handle<T1>, SHADE::Handle<T2>> const& pair) const
{
return std::hash<uint64_t>{}(pair.first.GetId().Raw) ^ std::hash<uint64_t>{}(pair.second.GetId().Raw);
}
}

View File

@ -62,14 +62,14 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
SparseSet<T> objects;
SparseSet<uint32_t> versionCounts;
std::queue<uint32_t> freeList;
std::queue<uint32_t> freeList;
uint32_t lastIdx = 0;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
void assertHandleValid(Handle<T> handle) const;
uint32_t getAvailableFreeIndex();
uint32_t getAvailableFreeIndex();
};
/// <summary>

View File

@ -31,5 +31,6 @@
#include <sstream>
#include <iomanip>
#include <cstddef>
#include <span>
#include "Common/SHCommonTypes.h"

View File

@ -8,7 +8,7 @@
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#include <SHpch.h>
#include "SHpch.h"
// Primary Header
#include "SHSceneGraph.h"

View File

@ -16,6 +16,7 @@
#include "ECS_Base/General/SHFamily.h"
#include "SHScene.h"
#include <functional>
#include "SH_API.h"
namespace SHADE
{

View File

@ -0,0 +1,72 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
layout(location = 0) in struct
{
//mat3 BTN;
vec4 vertColor;
//vec3 localSpacePosition;
//vec2 uv;
//vec3 localLightPosition;
//vec3 localEyePosition;
} In;
//layout(std140, push_constant) uniform TestPushConstant
//{
// mat4 pvMat;
// vec4 lightPosition;
// vec4 eyePosition;
// vec4 ambientColor;
// vec4 lightColor;
//
//} testPushConstant;
layout(location = 0) out vec4 outColor;
//layout(binding = 0) uniform sampler2D diffuseMap;
//layout(binding = 1) uniform sampler2D normalMap;
//layout(binding = 2) uniform sampler2D aoMap;
//layout(binding = 3) uniform sampler2D glossinessMap;
//layout(binding = 4) uniform sampler2D samplerRoughnessMap;
void main()
{
//vec3 normal;
//// Get the tangent space normal from normal map. It is a BC5 texture and therefore only use red and green
//normal.xy = (texture (normalMap, In.uv).gr * 2.0f) - 1.0f;
//// z value is derived (TODO: Find out what this does)
//normal.z = sqrt(1.0f - dot(normal.xy, normal.xy));
//// Transform the normal from tangent space to local space
//normal = In.BTN * normal;
//// Get the vector from fragment to light
//vec3 localLightDir = normalize(In.localLightPosition - In.localSpacePosition);
//// get the value of dot between normal from texture and frag to light
//float diffuse = max(0, dot(normal, localLightDir));
//// sample the diffuse texture
//vec4 diffuseColor = texture (diffuseMap, In.uv) * In.vertColor;
//vec3 eyeDirection = normalize(In.localSpacePosition - In.localEyePosition);
//const float shininess = mix(1, 100, 1 - texture (samplerRoughnessMap, In.uv).r);
//float specular = pow(max(0, dot(normal, normalize(localLightDir - eyeDirection))), shininess);
//outColor.rgb = testPushConstant.ambientColor.rgb * diffuseColor.rgb * texture (aoMap, In.uv).rgb;
//outColor.rgb += testPushConstant.lightColor.rgb * (specular.rrr * 0.4 + diffuse.rrr * diffuseColor.rgb);
//const float gamma = testPushConstant.eyePosition.w;
//outColor.rgb = pow(outColor.rgb, vec3(1.0f / gamma));
//outColor.a = diffuseColor.a;
outColor = vec4 (1.0f);
}

Binary file not shown.

View File

@ -0,0 +1,53 @@
#version 450
#extension GL_KHR_vulkan_glsl : enable
layout(location = 0) in vec3 aVertexPos;
layout(location = 1) in vec2 aUV;
layout(location = 2) in vec3 aNormal;
layout(location = 3) in vec3 aTangent;
layout(location = 4) in mat4 worldTransform;
//layout(std140, push_constant) uniform TestPushConstant
//{
// mat4 pvMat;
// vec4 lightPosition;
// vec4 eyePosition;
// vec4 ambientColor;
// vec4 lightColor;
//
//} testPushConstant;
layout(location = 0) out struct
{
//mat3 BTN;
vec4 vertColor;
//vec3 localSpacePosition;
//vec2 uv;
//vec3 localLightPosition;
//vec3 localEyePosition;
} Out;
void main()
{
//const float gamma = testPushConstant.eyePosition.w;
//mat4 W2L = inverse(worldTransform);
//// Since attributes are instanced we want the local positions of light and eye (camera)
//Out.localLightPosition = vec3(W2L * vec4(testPushConstant.lightPosition.xyz, 1.0f));
//Out.localEyePosition = vec3(W2L * vec4(testPushConstant.eyePosition.xyz, 1.0f));
//vec3 biTangent = normalize(cross(aNormal, aTangent));
//gl_Position = testPushConstant.pvMat * worldTransform * vec4(aVertexPos, 1.0);
//// Since the normal we are sampling is in tangent space, we want to later convert them to local space
//// so we need this matrix to multiply with the sampled texel of the normal map.
//Out.BTN = mat3(aTangent, biTangent, aNormal);
//Out.localSpacePosition = aVertexPos;
//Out.uv = aUV;
// render NDC first
gl_Position = vec4(aVertexPos, 1.0);
Out.vertColor = vec4 (aVertexPos, 1.0f);
}

Binary file not shown.