Now able to render a cube and fixed numerous behind the scene issues with Vulkan abstractions #47

Merged
Pycorax merged 20 commits from SP3-1-Rendering into main 2022-09-23 23:36:52 +08:00
58 changed files with 1028 additions and 416 deletions

View File

@ -25,6 +25,7 @@
#include "Math/Transform/SHTransformSystem.h" #include "Math/Transform/SHTransformSystem.h"
#include "Scenes/SBTestScene.h" #include "Scenes/SBTestScene.h"
#include "Math/Transform/SHTransformComponent.h"
using namespace SHADE; using namespace SHADE;
@ -67,8 +68,10 @@ namespace Sandbox
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::BeginRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::RenderRoutine>();
SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::EndRoutine>(); SHADE::SHSystemManager::RegisterRoutine<SHADE::SHGraphicsSystem, SHADE::SHGraphicsSystem::EndRoutine>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHRenderable>();
SHADE::SHComponentManager::CreateComponentSparseSet<SHADE::SHTransformComponent>();
// Set up graphics system and windows // Set up graphics system and windows
graphicsSystem->SetWindow(&window); graphicsSystem->SetWindow(&window);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND()); sdlWindow = SDL_CreateWindowFrom(window.GetHWND());

View File

@ -38,24 +38,56 @@ namespace Sandbox
// Create Materials // Create Materials
auto matInst = graphicsSystem->AddMaterialInstance(); auto matInst = graphicsSystem->AddMaterialInstance();
// Create entity and add mesh // Create Stress Test Objects
testObj = SHADE::SHEntityManager::CreateEntity<SHADE::SHRenderable, SHADE::SHTransformComponent>(); static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f };
auto& renderable = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHRenderable>(testObj); constexpr int NUM_ROWS = 200;
renderable.Mesh = CUBE_MESH; constexpr int NUM_COLS = 100;
renderable.SetMaterial(matInst); static const SHVec3 TEST_OBJ_SPACING = { 1.0f, 1.0f, 1.0f };
// Create transform static const SHVec3 TEST_OBJ_START_POS = { - (NUM_COLS / 2 * TEST_OBJ_SPACING.x ), 0.0f, 0.0f };
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj); for (int z = 0; z < NUM_ROWS; ++z)
transform.SetLocalPosition(SHVec3{ 0.0f, 0.0f, 2.0f }); for (int x = 0; x < NUM_COLS; ++x)
{
auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
renderable.TransformMatrix = SHMatrix::Translate(0.0f, 0.0f, 2.0f); renderable.Mesh = CUBE_MESH;
renderable.SetMaterial(matInst);
// Set initial positions
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, 0.0f, z * TEST_OBJ_SPACING.z });
//transform.SetLocalScale(TEST_OBJ_SCALE);
stressTestObjects.emplace_back(entity);
}
// Create blank entity with a script
testObj = SHADE::SHEntityManager::CreateEntity();
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>()); SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
scriptEngine->AddScript(*SHADE::SHEntityManager::GetEntityByID(testObj), "TestScript"); scriptEngine->AddScript(testObj, "TestScript");
} }
void SBTestScene::Update(float dt) void SBTestScene::Update(float dt)
{ {
(void)dt; /*static float rotation = 0.0f;
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(testObj);
transform.SetLocalRotation(rotation, 0.0f, 0.0f);
rotation += dt * 10.0f;*/
/*static float rotation = 0.0f;
auto& transform = *SHADE::SHComponentManager::GetComponent_s<SHADE::SHTransformComponent>(stressTestObjects[0]);
transform.SetWorldPosition({rotation, 0.0f, 0.0f});
rotation += dt * 10.0f;*/
// Destroy entity if space is pressed
if (GetKeyState(VK_SPACE) & 0x8000) if (GetKeyState(VK_SPACE) & 0x8000)
SHADE::SHEntityManager::DestroyEntity(testObj); {
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
scriptEngine->RemoveAllScripts(testObj);
}
} }
void SBTestScene::Render() void SBTestScene::Render()

View File

@ -10,7 +10,7 @@ namespace Sandbox
private: private:
EntityID camera; EntityID camera;
EntityID testObj; EntityID testObj;
std::vector<EntityID> stressTestObjects;
public: public:
virtual void Load(); virtual void Load();

View File

@ -49,6 +49,11 @@ namespace SHADE
Init(newSize, data, srcSize, bufferUsageFlags, allocCreateInfo.usage, allocCreateInfo.flags); Init(newSize, data, srcSize, bufferUsageFlags, allocCreateInfo.usage, allocCreateInfo.flags);
} }
void SHVkBuffer::FlushAllocation(uint32_t srcOffset, uint32_t dstOffset) noexcept
{
vmaFlushAllocation(vmaAllocator, alloc, srcOffset, dstOffset);
}
vk::Buffer SHVkBuffer::GetVkBuffer(void) const noexcept vk::Buffer SHVkBuffer::GetVkBuffer(void) const noexcept
{ {
return vkBuffer; return vkBuffer;
@ -72,8 +77,7 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHVkBuffer::Map(void) noexcept void SHVkBuffer::Map(void) noexcept
{ {
if (!boundToCoherent) vmaMapMemory(vmaAllocator, alloc, &mappedPtr);
vmaMapMemory(vmaAllocator, alloc, &mappedPtr);
} }
/***************************************************************************/ /***************************************************************************/
@ -90,11 +94,8 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHVkBuffer::Unmap(void) noexcept void SHVkBuffer::Unmap(void) noexcept
{ {
if (!boundToCoherent) vmaUnmapMemory(vmaAllocator, alloc);
{ mappedPtr = nullptr;
vmaUnmapMemory(vmaAllocator, alloc);
mappedPtr = nullptr;
}
} }
/***************************************************************************/ /***************************************************************************/
@ -132,9 +133,7 @@ namespace SHADE
Otherwise, only the copying is carried out. Otherwise, only the copying is carried out.
In the instance where memory is non-coherent but HOST_VISIBLE, we want to In the instance where memory is non-coherent but HOST_VISIBLE, we want to
write to data and then unmap and flush it immediately. If you want to write write to data and then unmap and flush it immediately.
to memory in random-access fashion, consider, mapping, writing a few
things, unmapping then flushing.
\param vmaAllocator \param vmaAllocator
The VMA allocator object. The VMA allocator object.
@ -155,18 +154,11 @@ namespace SHADE
/***************************************************************************/ /***************************************************************************/
void SHVkBuffer::MapWriteUnmap(void* data, uint32_t sizeToWrite, uint32_t srcOffset, uint32_t dstOffset) noexcept void SHVkBuffer::MapWriteUnmap(void* data, uint32_t sizeToWrite, uint32_t srcOffset, uint32_t dstOffset) noexcept
{ {
if (!boundToCoherent) // map from host visible memory to pointer, do a DMA, and then unmap
{ Map();
// map from host visible memory to pointer, do a DMA, and then unmap WriteToMemory(data, sizeToWrite, srcOffset, dstOffset);
Map(); Unmap();
WriteToMemory(data, sizeToWrite, srcOffset, dstOffset); FlushAllocation(srcOffset, dstOffset);
Unmap();
}
else
{
if (mappedPtr)
std::memcpy(static_cast<uint8_t*>(mappedPtr) + dstOffset, static_cast<uint8_t*>(data) + srcOffset, sizeToWrite);
}
} }
/***************************************************************************/ /***************************************************************************/
@ -279,7 +271,6 @@ namespace SHADE
, mappedPtr{ nullptr } , mappedPtr{ nullptr }
, alloc {nullptr} , alloc {nullptr}
, randomAccessOptimized{false} , randomAccessOptimized{false}
, boundToCoherent {false}
, vmaAllocator{allocator} , vmaAllocator{allocator}
{} {}
@ -304,7 +295,6 @@ namespace SHADE
, mappedPtr{ std::move(rhs.mappedPtr) } , mappedPtr{ std::move(rhs.mappedPtr) }
, alloc{ std::move (rhs.alloc) } , alloc{ std::move (rhs.alloc) }
, randomAccessOptimized{ rhs.randomAccessOptimized } , randomAccessOptimized{ rhs.randomAccessOptimized }
, boundToCoherent{ rhs.boundToCoherent}
, vmaAllocator{ rhs.vmaAllocator } , vmaAllocator{ rhs.vmaAllocator }
, bufferUsageFlags {rhs.bufferUsageFlags} , bufferUsageFlags {rhs.bufferUsageFlags}
, bufferCreateInfo { rhs.bufferCreateInfo } , bufferCreateInfo { rhs.bufferCreateInfo }
@ -325,7 +315,6 @@ namespace SHADE
mappedPtr = std::move(rhs.mappedPtr); mappedPtr = std::move(rhs.mappedPtr);
alloc = std::move(rhs.alloc); alloc = std::move(rhs.alloc);
randomAccessOptimized = rhs.randomAccessOptimized; randomAccessOptimized = rhs.randomAccessOptimized;
boundToCoherent = rhs.boundToCoherent;
vmaAllocator = std::move (rhs.vmaAllocator); vmaAllocator = std::move (rhs.vmaAllocator);
rhs.vkBuffer = VK_NULL_HANDLE; rhs.vkBuffer = VK_NULL_HANDLE;
bufferCreateInfo = rhs.bufferCreateInfo; bufferCreateInfo = rhs.bufferCreateInfo;
@ -430,18 +419,20 @@ namespace SHADE
// mainly host visible. Can be cached (need to flush/invalidate), uncached (always coherent) and coherent (virtual). // mainly host visible. Can be cached (need to flush/invalidate), uncached (always coherent) and coherent (virtual).
if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
{ {
// If memory is marked to be coherent between CPU and GPU (no need flush/invalidate) (TODO: Verify if VMA_ALLOCATION_CREATE_MAPPED_BIT is used when VMA_MEMORY_USAGE_AUTO is set) const bool CREATE_MAPPED = allocFlags & VMA_ALLOCATION_CREATE_MAPPED_BIT;
// TODO: also verify that coherent bit = pointer is already mapped
if (memPropFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) if (CREATE_MAPPED)
{
boundToCoherent = true;
mappedPtr = allocInfo.pMappedData; mappedPtr = allocInfo.pMappedData;
}
else else
mappedPtr = nullptr; mappedPtr = nullptr;
if (data) if (data)
MapWriteUnmap(data, srcSize, 0, 0); {
if (CREATE_MAPPED)
WriteToMemory(data, srcSize, 0, 0);
else
MapWriteUnmap(data, srcSize, 0, 0);
}
} }
else else
{ {

View File

@ -41,9 +41,6 @@ namespace SHADE
//! If initialized with vma random access flag, this is true //! If initialized with vma random access flag, this is true
bool randomAccessOptimized; bool randomAccessOptimized;
//! Whether or not this buffer is bound to coherent memory
bool boundToCoherent;
//! buffer usage info flags //! buffer usage info flags
vk::BufferUsageFlags bufferUsageFlags; vk::BufferUsageFlags bufferUsageFlags;
@ -100,6 +97,7 @@ namespace SHADE
void TransferToDeviceResource(Handle<SHVkCommandBuffer> const& cmdBufferHdl) noexcept; void TransferToDeviceResource(Handle<SHVkCommandBuffer> const& cmdBufferHdl) noexcept;
void ResizeNoCopy (uint32_t newSize); void ResizeNoCopy (uint32_t newSize);
void ResizeReplace (uint32_t newSize, void* data, uint32_t srcSize); void ResizeReplace (uint32_t newSize, void* data, uint32_t srcSize);
void FlushAllocation (uint32_t srcOffset, uint32_t dstOffset) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */

View File

@ -8,6 +8,7 @@
#include "Graphics/Framebuffer/SHVkFramebuffer.h" #include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "Graphics/Pipeline/SHVkPipeline.h" #include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/Buffers/SHVkBuffer.h" #include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Images/SHVkImage.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
@ -421,9 +422,42 @@ namespace SHADE
vkCommandBuffer.drawIndexed(indexCount, 1, firstIndex, vertexOffset, 0); vkCommandBuffer.drawIndexed(indexCount, 1, firstIndex, vertexOffset, 0);
} }
/***************************************************************************/
/*!
\brief
Issues a multi indirect draw call.
void SHVkCommandBuffer::PipelineBarrier ( \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));
}
void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo)
{
vkCommandBuffer.copyBufferToImage
(
src, dst, vk::ImageLayout::eTransferDstOptimal,
static_cast<uint32_t>(copyInfo.size()), copyInfo.data()
);
}
void SHVkCommandBuffer::PipelineBarrier(
vk::PipelineStageFlags srcStage, vk::PipelineStageFlags srcStage,
vk::PipelineStageFlags dstStage, vk::PipelineStageFlags dstStage,
vk::DependencyFlags deps, vk::DependencyFlags deps,
@ -457,33 +491,11 @@ namespace SHADE
// //vkCommandBuffer.pipelineBarrier() // //vkCommandBuffer.pipelineBarrier()
//} //}
/***************************************************************************/ void SHVkCommandBuffer::ForceSetPipelineLayout(Handle<SHVkPipelineLayout> pipelineLayout) noexcept
/*!
\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) boundPipelineLayoutHdl = pipelineLayout;
{
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 SHVkFramebuffer;
class SHVkPipeline; class SHVkPipeline;
class SHVkBuffer; class SHVkBuffer;
class SHVkImage;
class SHVkDescriptorSetGroup; class SHVkDescriptorSetGroup;
enum class SH_CMD_BUFFER_TYPE enum class SH_CMD_BUFFER_TYPE
@ -116,6 +117,10 @@ namespace SHADE
// Draw Commands // Draw Commands
void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept; void DrawArrays (uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const noexcept;
void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept; void DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept;
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
// Buffer Copy
void CopyBufferToImage (const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo);
// memory barriers // memory barriers
void PipelineBarrier ( void PipelineBarrier (
@ -129,7 +134,6 @@ namespace SHADE
bool IsReadyToSubmit (void) const noexcept; bool IsReadyToSubmit (void) const noexcept;
void HandlePostSubmit (void) noexcept; void HandlePostSubmit (void) noexcept;
void DrawMultiIndirect (Handle<SHVkBuffer> indirectDrawData, uint32_t drawCount);
// Push Constant variable setting // Push Constant variable setting
template <typename T> template <typename T>
@ -137,6 +141,7 @@ namespace SHADE
{ {
memcpy (static_cast<uint8_t*>(pushConstantData) + boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T)); memcpy (static_cast<uint8_t*>(pushConstantData) + boundPipelineLayoutHdl->GetPushConstantInterface().GetOffset(variableName), &data, sizeof (T));
}; };
void ForceSetPipelineLayout (Handle<SHVkPipelineLayout> pipelineLayout) noexcept;
void SubmitPushConstants (void) const noexcept; void SubmitPushConstants (void) const noexcept;

View File

@ -20,23 +20,6 @@ namespace SHADE
} }
/***************************************************************************/
/*!
\brief
Links the write infos to the vulkan write descriptor sets.
*/
/***************************************************************************/
void SHDescriptorSetUpdater::LinkInfoToWriteDescSet(void) noexcept
{
for (uint32_t i = 0; i < writeInfos.size(); ++i)
{
writeDescSets[i].pImageInfo = writeInfos[i].descImageInfos.data();
writeDescSets[i].pBufferInfo = writeInfos[i].descBufferInfos.data();
writeDescSets[i].pTexelBufferView = writeInfos[i].descTexelBufferInfos.data();
}
}
SHDescriptorWriteInfo& SHDescriptorWriteInfo::operator=(SHDescriptorWriteInfo&& rhs) noexcept SHDescriptorWriteInfo& SHDescriptorWriteInfo::operator=(SHDescriptorWriteInfo&& rhs) noexcept
{ {
@ -65,11 +48,6 @@ namespace SHADE
} }
std::vector<vk::WriteDescriptorSet> const& SHDescriptorSetUpdater::GetWriteDescriptorSets(void) const noexcept
{
return writeDescSets;
}
SHDescriptorSetUpdater& SHDescriptorSetUpdater::operator=(SHDescriptorSetUpdater&& rhs) noexcept SHDescriptorSetUpdater& SHDescriptorSetUpdater::operator=(SHDescriptorSetUpdater&& rhs) noexcept
{ {
if (&rhs == this) if (&rhs == this)

View File

@ -41,10 +41,6 @@ namespace SHADE
//! When we want to update a write, we need to use this to identify the index of the write. //! When we want to update a write, we need to use this to identify the index of the write.
std::unordered_map<BindingAndSetHash, uint32_t> writeHashMap; std::unordered_map<BindingAndSetHash, uint32_t> writeHashMap;
//! We keep this here because we want this to be immediately passable to vkUpdateDescriptorSets
std::vector<vk::WriteDescriptorSet> writeDescSets;
void LinkInfoToWriteDescSet(void) noexcept;
public: public:
SHDescriptorSetUpdater (void) noexcept; SHDescriptorSetUpdater (void) noexcept;
@ -52,8 +48,6 @@ namespace SHADE
SHDescriptorSetUpdater& operator= (SHDescriptorSetUpdater&& rhs) noexcept; SHDescriptorSetUpdater& operator= (SHDescriptorSetUpdater&& rhs) noexcept;
public: public:
std::vector<vk::WriteDescriptorSet> const& GetWriteDescriptorSets (void) const noexcept;
friend class SHVkDescriptorSetGroup; friend class SHVkDescriptorSetGroup;
}; };
} }

View File

@ -50,9 +50,8 @@ namespace SHADE
return *this; return *this;
} }
std::vector<Handle<SHVkDescriptorSetGroup>> SHVkDescriptorPool::Allocate(const std::vector<Handle<SHVkDescriptorSetLayout>>& layouts, std::vector<uint32_t> const& variableDescCounts) Handle<SHVkDescriptorSetGroup> SHVkDescriptorPool::Allocate(const std::vector<Handle<SHVkDescriptorSetLayout>>& layouts, std::vector<uint32_t> const& variableDescCounts)
{ {
SHVkInstance::GetResourceManager().Create<SHVkDescriptorSetGroup>(device, GetHandle(), layouts, variableDescCounts); return SHVkInstance::GetResourceManager().Create<SHVkDescriptorSetGroup>(device, GetHandle(), layouts, variableDescCounts);
return {};
} }
} }

View File

@ -101,7 +101,7 @@ namespace SHADE
/// Handles to the created Descriptor Sets. If this DescriptorPool has run out of /// Handles to the created Descriptor Sets. If this DescriptorPool has run out of
/// space, lesser number of Handles will be returned. /// space, lesser number of Handles will be returned.
/// </returns> /// </returns>
std::vector<Handle<SHVkDescriptorSetGroup>> Allocate(const std::vector<Handle<SHVkDescriptorSetLayout>>& layouts, std::vector<uint32_t> const& variableDescCounts); Handle<SHVkDescriptorSetGroup> Allocate(const std::vector<Handle<SHVkDescriptorSetLayout>>& layouts, std::vector<uint32_t> const& variableDescCounts);
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -7,6 +7,11 @@
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "Graphics/Images/SHVkImage.h"
#include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Images/SHVkSampler.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE namespace SHADE
{ {
@ -39,6 +44,7 @@ namespace SHADE
: device{deviceHdl} : device{deviceHdl}
, descPool {pool} , descPool {pool}
, descSets{} , descSets{}
, layoutsUsed {layouts}
{ {
// Create the layout for each concurrent frame // Create the layout for each concurrent frame
std::vector<vk::DescriptorSetLayout> vkLayouts{ layouts.size() }; std::vector<vk::DescriptorSetLayout> vkLayouts{ layouts.size() };
@ -47,6 +53,7 @@ namespace SHADE
for (uint32_t i = 0; i < layouts.size(); ++i) for (uint32_t i = 0; i < layouts.size(); ++i)
{ {
vkLayouts[i] = layouts[i]->GetVkHandle(); vkLayouts[i] = layouts[i]->GetVkHandle();
setIndexing.emplace(layouts[i]->GetSetIndex(), i);
} }
// Check for variable descriptor count // Check for variable descriptor count
@ -73,34 +80,22 @@ namespace SHADE
// allocate descriptor sets // allocate descriptor sets
descSets = device->GetVkLogicalDevice().allocateDescriptorSets(DESC_SET_LAYOUT_CREATE_INFO); descSets = device->GetVkLogicalDevice().allocateDescriptorSets(DESC_SET_LAYOUT_CREATE_INFO);
// Now we want to prepare the write descriptor sets info for writing later.
// Now we want to prepare the write descriptor sets for writing later.
for (uint32_t i = 0; i < layouts.size(); ++i) for (uint32_t i = 0; i < layouts.size(); ++i)
{ {
auto const& bindings = layouts[i]->GetBindings(); auto const& bindings = layouts[i]->GetBindings();
for (auto& binding : bindings) for (auto& binding : bindings)
{ {
BindingAndSetHash writeHash = binding.BindPoint; BindingAndSetHash writeHash = binding.BindPoint;
writeHash |= static_cast<uint64_t>(i) << 32; writeHash |= static_cast<uint64_t>(layouts[i]->GetSetIndex()) << 32;
// new write for the binding // new write for the binding
updater.writeInfos.emplace_back(); updater.writeInfos.emplace_back();
updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1); updater.writeHashMap.try_emplace(writeHash, updater.writeInfos.size() - 1);
auto& writeInfo = updater.writeInfos.back(); auto& writeInfo = updater.writeInfos.back();
updater.writeDescSets.emplace_back();
auto& writeDescSet = updater.writeDescSets.back();
// Initialize info for write
writeDescSet.descriptorType = binding.Type;
writeDescSet.dstArrayElement = 0;
writeDescSet.dstSet = descSets[i];
writeDescSet.dstBinding = binding.BindPoint;
// Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in // Descriptor count for the write descriptor set. Usually this is set to 1, but if binding is variable sized, set to info passed in
uint32_t descriptorCount = (binding.flags & vk::DescriptorBindingFlagBits::eVariableDescriptorCount) ? variableDescCounts[i] : 1; uint32_t descriptorCount = (binding.flags & vk::DescriptorBindingFlagBits::eVariableDescriptorCount) ? variableDescCounts[i] : 1;
writeDescSet.descriptorCount = descriptorCount;
switch (binding.Type) switch (binding.Type)
{ {
@ -114,8 +109,10 @@ namespace SHADE
case vk::DescriptorType::eUniformTexelBuffer: case vk::DescriptorType::eUniformTexelBuffer:
case vk::DescriptorType::eStorageTexelBuffer: case vk::DescriptorType::eStorageTexelBuffer:
case vk::DescriptorType::eUniformBuffer: case vk::DescriptorType::eUniformBuffer:
case vk::DescriptorType::eUniformBufferDynamic:
case vk::DescriptorType::eStorageBuffer: case vk::DescriptorType::eStorageBuffer:
writeInfo.descImageInfos.resize (descriptorCount); case vk::DescriptorType::eStorageBufferDynamic:
writeInfo.descBufferInfos.resize (descriptorCount);
break; break;
//case vk::DescriptorType::eUniformBufferDynamic: //case vk::DescriptorType::eUniformBufferDynamic:
// break; // break;
@ -130,8 +127,6 @@ namespace SHADE
} }
} }
} }
// Link all the writeDescSet data for vkUpdateDescriptorSets to write to the linked descriptors
updater.LinkInfoToWriteDescSet();
} }
/***************************************************************************/ /***************************************************************************/
@ -160,7 +155,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::vector<std::pair<vk::ImageView, vk::Sampler>> const& imageViewsAndSamplers) noexcept void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::pair<Handle<SHVkImageView>, Handle<SHVkSampler>>> const& imageViewsAndSamplers) noexcept
{ {
// Find the target writeDescSet // Find the target writeDescSet
BindingAndSetHash writeHash = binding; BindingAndSetHash writeHash = binding;
@ -176,32 +171,83 @@ namespace SHADE
{ {
// write sampler and image view // write sampler and image view
auto& ivs = imageViewsAndSamplers[i]; auto& ivs = imageViewsAndSamplers[i];
writeInfo.descImageInfos[i].imageView = ivs.first; writeInfo.descImageInfos[i].imageView = ivs.first->GetImageView();
writeInfo.descImageInfos[i].sampler = ivs.second; writeInfo.descImageInfos[i].sampler = ivs.second->GetVkSampler();
} }
} }
void SHVkDescriptorSetGroup::ModifyWriteDescBuffer(uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept
void SHVkDescriptorSetGroup::UpdateDescriptorSet(void) noexcept
{ {
device->UpdateDescriptorSets(updater.GetWriteDescriptorSets()); // Find the target writeDescSet
BindingAndSetHash writeHash = binding;
writeHash |= static_cast<uint64_t>(set) << 32;
auto& writeInfo = updater.writeInfos[updater.writeHashMap.at(writeHash)];
if (buffers.size() > writeInfo.descBufferInfos.size())
{
SHLOG_ERROR("Attempting write too many descriptors into descriptor set. Failed to write to vk::WriteDescriptorSet. ");
}
for (uint32_t i = 0; i < buffers.size(); ++i)
{
// write sampler and image view
auto& buffer = buffers[i];
writeInfo.descBufferInfos[i].buffer = buffer->GetVkBuffer();
writeInfo.descBufferInfos[i].offset = offset;
writeInfo.descBufferInfos[i].range = range;
}
} }
void SHVkDescriptorSetGroup::UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept
void SHVkDescriptorSetGroup::UpdateSingleDescriptorSetImages(uint32_t set, uint32_t binding) noexcept
{ {
vk::WriteDescriptorSet writeDescSet{}; vk::WriteDescriptorSet writeDescSet{};
// Get binding + set hash
BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding);
// to index a set
uint32_t setIndex = setIndexing[bsHash];
// to index a write for a binding
uint32_t writeInfoIndex = updater.writeHashMap[bsHash];
// Initialize info for write // Initialize info for write
writeDescSet.descriptorType = vk::DescriptorType::eCombinedImageSampler; writeDescSet.descriptorType = layoutsUsed[setIndex]->GetBindings()[binding].Type;
writeDescSet.dstArrayElement = 0; writeDescSet.dstArrayElement = 0;
writeDescSet.dstSet = descSets[set]; writeDescSet.dstSet = descSets[setIndex];
writeDescSet.dstBinding = binding; writeDescSet.dstBinding = binding;
writeDescSet.pImageInfo = updater.writeInfos[set].descImageInfos.data(); writeDescSet.pImageInfo = updater.writeInfos[writeInfoIndex].descImageInfos.data();
writeDescSet.descriptorCount = static_cast<uint32_t>(updater.writeInfos[set].descImageInfos.size()); writeDescSet.descriptorCount = static_cast<uint32_t>(updater.writeInfos[writeInfoIndex].descImageInfos.size());
device->UpdateDescriptorSet(writeDescSet); device->UpdateDescriptorSet(writeDescSet);
} }
void SHVkDescriptorSetGroup::UpdateDescriptorSetBuffer(uint32_t set, uint32_t binding) noexcept
{
vk::WriteDescriptorSet writeDescSet{};
// Get binding + set hash
BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding);
// to index a set
uint32_t setIndex = setIndexing[bsHash];
// to index a write for a binding
uint32_t writeInfoIndex = updater.writeHashMap[bsHash];
// Initialize info for write
writeDescSet.descriptorType = layoutsUsed[setIndex]->GetBindings()[binding].Type;
writeDescSet.dstArrayElement = 0;
writeDescSet.dstSet = descSets[setIndex];
writeDescSet.dstBinding = binding;
writeDescSet.pBufferInfo = updater.writeInfos[writeInfoIndex].descBufferInfos.data();
writeDescSet.descriptorCount = static_cast<uint32_t>(updater.writeInfos[writeInfoIndex].descBufferInfos.size());
device->UpdateDescriptorSet(writeDescSet);
}
} }

View File

@ -14,6 +14,10 @@ namespace SHADE
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHVkDescriptorSetLayout; class SHVkDescriptorSetLayout;
class SHVkSampler;
class SHVkImage;
class SHVkImageView;
class SHVkBuffer;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -54,12 +58,14 @@ namespace SHADE
SHVkDescriptorSetGroup& operator=(SHVkDescriptorSetGroup&& rhs) noexcept = default; SHVkDescriptorSetGroup& operator=(SHVkDescriptorSetGroup&& rhs) noexcept = default;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Descriptor set writing */ /* Public member functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::vector<std::pair<vk::ImageView, vk::Sampler>> const& imageViewsAndSamplers) noexcept; void UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept;
void UpdateDescriptorSet(void) noexcept; void UpdateDescriptorSetBuffer(uint32_t set, uint32_t binding) noexcept;
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::pair<Handle<SHVkImageView>, Handle<SHVkSampler>>> const& imageViewsAndSamplers) noexcept;
void ModifyWriteDescBuffer (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
void UpdateSingleDescriptorSetImages(uint32_t set, uint32_t binding) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
@ -81,9 +87,17 @@ namespace SHADE
//! Descriptor pool to allocate descriptor sets //! Descriptor pool to allocate descriptor sets
Handle<SHVkDescriptorPool> descPool; Handle<SHVkDescriptorPool> descPool;
//! Sometimes when we pass in a layout, the set of the layout used in the
//! shader cannot be used to index into descSets. This is to mitigate that issue
//! when we update descriptor sets.
std::unordered_map<SetIndex, uint32_t> setIndexing;
//! Descriptor sets //! Descriptor sets
std::vector<vk::DescriptorSet> descSets; std::vector<vk::DescriptorSet> descSets;
//! Layouts used to create this descriptor set group
std::vector<Handle<SHVkDescriptorSetLayout>> layoutsUsed;
//! for updating descriptor sets. We want to cache this so that we don't create the //! for updating descriptor sets. We want to cache this so that we don't create the
//! write structs at runtime. //! write structs at runtime.
SHDescriptorSetUpdater updater; SHDescriptorSetUpdater updater;

View File

@ -7,9 +7,10 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructor/Destructor */ /* Constructor/Destructor */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHVkDescriptorSetLayout::SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, const std::vector<Binding>& bindings) SHVkDescriptorSetLayout::SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, SetIndex set, const std::vector<Binding>& bindings)
: device { device } : device { device }
, layoutDesc { bindings } , layoutDesc { bindings }
, setIndex {set}
{ {
// Check if auto-binding point calculation configuration is valid // Check if auto-binding point calculation configuration is valid
bool autoCalc = false; bool autoCalc = false;
@ -74,6 +75,7 @@ namespace SHADE
: device {rhs.device} : device {rhs.device}
, setLayout {rhs.setLayout} , setLayout {rhs.setLayout}
, layoutDesc{std::move (rhs.layoutDesc)} , layoutDesc{std::move (rhs.layoutDesc)}
, setIndex {rhs.setIndex}
{ {
rhs.setLayout = VK_NULL_HANDLE; rhs.setLayout = VK_NULL_HANDLE;
} }
@ -90,6 +92,11 @@ namespace SHADE
return layoutDesc; return layoutDesc;
} }
SetIndex SHVkDescriptorSetLayout::GetSetIndex(void) const noexcept
{
return setIndex;
}
SHVkDescriptorSetLayout& SHVkDescriptorSetLayout::operator=(SHVkDescriptorSetLayout&& rhs) noexcept SHVkDescriptorSetLayout& SHVkDescriptorSetLayout::operator=(SHVkDescriptorSetLayout&& rhs) noexcept
{ {
if (&rhs == this) if (&rhs == this)
@ -98,6 +105,7 @@ namespace SHADE
device = rhs.device; device = rhs.device;
setLayout = rhs.setLayout; setLayout = rhs.setLayout;
layoutDesc = std::move(rhs.layoutDesc); layoutDesc = std::move(rhs.layoutDesc);
setIndex = rhs.setIndex;
rhs.setLayout = VK_NULL_HANDLE; rhs.setLayout = VK_NULL_HANDLE;

View File

@ -74,7 +74,7 @@ namespace SHADE
/// </summary> /// </summary>
/// <param name="device"></param> /// <param name="device"></param>
/// <param name="bindings"></param> /// <param name="bindings"></param>
SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, const std::vector<Binding>& bindings); SHVkDescriptorSetLayout(Handle<SHVkLogicalDevice> device, SetIndex setIndex, const std::vector<Binding>& bindings);
SHVkDescriptorSetLayout(const SHVkDescriptorSetLayout&) = delete; SHVkDescriptorSetLayout(const SHVkDescriptorSetLayout&) = delete;
SHVkDescriptorSetLayout(SHVkDescriptorSetLayout&& rhs) noexcept; SHVkDescriptorSetLayout(SHVkDescriptorSetLayout&& rhs) noexcept;
/// <summary> /// <summary>
@ -97,6 +97,7 @@ namespace SHADE
/// <returns>Handle to the Vulkan Descriptor Set Layout handle.</returns> /// <returns>Handle to the Vulkan Descriptor Set Layout handle.</returns>
inline const vk::DescriptorSetLayout& GetVkHandle() const { return setLayout; } inline const vk::DescriptorSetLayout& GetVkHandle() const { return setLayout; }
std::vector<Binding> const& GetBindings (void) const noexcept; std::vector<Binding> const& GetBindings (void) const noexcept;
SetIndex GetSetIndex (void) const noexcept;
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -105,5 +106,6 @@ namespace SHADE
Handle<SHVkLogicalDevice> device; Handle<SHVkLogicalDevice> device;
vk::DescriptorSetLayout setLayout; vk::DescriptorSetLayout setLayout;
std::vector<Binding> layoutDesc; // Stores description of the layout std::vector<Binding> layoutDesc; // Stores description of the layout
SetIndex setIndex; // Index of the set
}; };
} }

View File

@ -467,7 +467,12 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
Handle<SHVkPipelineLayout> SHVkLogicalDevice::CreatePipelineLayout(SHPipelineLayoutParams& pipelineLayoutParams) noexcept Handle<SHVkPipelineLayout> SHVkLogicalDevice::CreatePipelineLayout(SHPipelineLayoutParams const& pipelineLayoutParams) noexcept
{
return SHVkInstance::GetResourceManager().Create <SHVkPipelineLayout>(GetHandle(), pipelineLayoutParams);
}
Handle<SHVkPipelineLayout> SHVkLogicalDevice::CreatePipelineLayoutDummy(SHPipelineLayoutParamsDummy const& pipelineLayoutParams) noexcept
{ {
return SHVkInstance::GetResourceManager().Create <SHVkPipelineLayout>(GetHandle(), pipelineLayoutParams); return SHVkInstance::GetResourceManager().Create <SHVkPipelineLayout>(GetHandle(), pipelineLayoutParams);
} }
@ -488,9 +493,9 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
Handle<SHVkPipeline> SHVkLogicalDevice::CreatePipeline(Handle<SHVkPipelineLayout> const& pipelineLayoutHdl, SHVkPipelineState const* const state, Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHSubpass> subpass, SH_PIPELINE_TYPE type) noexcept Handle<SHVkPipeline> SHVkLogicalDevice::CreateGraphicsPipeline(Handle<SHVkPipelineLayout> const& pipelineLayoutHdl, SHVkPipelineState const* const state, Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHSubpass> subpass) noexcept
{ {
return SHVkInstance::GetResourceManager().Create <SHVkPipeline>(GetHandle(), pipelineLayoutHdl, state, renderpassHdl, subpass, type); return SHVkInstance::GetResourceManager().Create <SHVkPipeline>(GetHandle(), pipelineLayoutHdl, state, renderpassHdl, subpass);
} }
@ -510,9 +515,9 @@ namespace SHADE
} }
Handle<SHVkDescriptorSetLayout> SHVkLogicalDevice::CreateDescriptorSetLayout(std::vector<SHVkDescriptorSetLayout::Binding> const& bindings) noexcept Handle<SHVkDescriptorSetLayout> SHVkLogicalDevice::CreateDescriptorSetLayout(SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings) noexcept
{ {
return SHVkInstance::GetResourceManager().Create <SHVkDescriptorSetLayout>(GetHandle(), bindings); return SHVkInstance::GetResourceManager().Create <SHVkDescriptorSetLayout>(GetHandle(), setIndex, bindings);
} }

View File

@ -21,6 +21,7 @@
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
#include "Graphics/Images/SHVkImage.h" #include "Graphics/Images/SHVkImage.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -171,23 +172,23 @@ namespace SHADE
std::string const& shaderName std::string const& shaderName
) noexcept; ) noexcept;
Handle<SHVkPipeline> CreatePipeline ( Handle<SHVkPipeline> CreateGraphicsPipeline (
Handle<SHVkPipelineLayout> const& pipelineLayoutHdl, Handle<SHVkPipelineLayout> const& pipelineLayoutHdl,
SHVkPipelineState const* const state, SHVkPipelineState const* const state,
Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkRenderpass> const& renderpassHdl,
Handle<SHSubpass> subpass, Handle<SHSubpass> subpass
SH_PIPELINE_TYPE type
) noexcept; ) noexcept;
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept; Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept;
Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::span<vk::SubpassDescription> const spDescs, std::span<vk::SubpassDependency> const spDeps) noexcept; Handle<SHVkRenderpass> CreateRenderpass (std::span<vk::AttachmentDescription> const vkDescriptions, std::span<vk::SubpassDescription> const spDescs, std::span<vk::SubpassDependency> const spDeps) noexcept;
Handle<SHVkFramebuffer> CreateFramebuffer (Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept; 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<SHVkDescriptorSetLayout> CreateDescriptorSetLayout (SetIndex setIndex, std::vector<SHVkDescriptorSetLayout::Binding> const& bindings) noexcept;
Handle<SHVkDescriptorPool> CreateDescriptorPools (const SHVkDescriptorPool::Config& config = {}) noexcept; Handle<SHVkDescriptorPool> CreateDescriptorPools (const SHVkDescriptorPool::Config& config = {}) noexcept;
Handle<SHVkDescriptorSetGroup> CreateDescriptorSetGroup(Handle<SHVkDescriptorPool> pool, Handle<SHVkDescriptorSetGroup> CreateDescriptorSetGroup(Handle<SHVkDescriptorPool> pool,
std::vector<Handle<SHVkDescriptorSetLayout>> const& layouts, std::vector<Handle<SHVkDescriptorSetLayout>> const& layouts,
std::vector<uint32_t> const& variableDescCounts) noexcept; std::vector<uint32_t> const& variableDescCounts) noexcept;
Handle<SHVkPipelineLayout> CreatePipelineLayout (SHPipelineLayoutParams& pipelineLayoutParams) noexcept; Handle<SHVkPipelineLayout> CreatePipelineLayout(SHPipelineLayoutParams const& pipelineLayoutParams) noexcept;
Handle<SHVkPipelineLayout> CreatePipelineLayoutDummy(SHPipelineLayoutParamsDummy const& pipelineLayoutParams) noexcept;
Handle<SHVkFence> CreateFence (void) const noexcept; Handle<SHVkFence> CreateFence (void) const noexcept;
Handle<SHVkSemaphore> CreateSemaphore (void) const noexcept; Handle<SHVkSemaphore> CreateSemaphore (void) const noexcept;

View File

@ -234,7 +234,7 @@ namespace SHADE
return SHVkInstance::GetResourceManager().Create<SHVkImageView>(inLogicalDeviceHdl, parent, createParams); return SHVkInstance::GetResourceManager().Create<SHVkImageView>(inLogicalDeviceHdl, parent, createParams);
} }
void SHVkImage::TransferToDeviceResource(void) noexcept void SHVkImage::TransferToDeviceResource(Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept
{ {
// prepare copy regions // prepare copy regions
std::vector<vk::BufferImageCopy> copyRegions{mipOffsets.size()}; std::vector<vk::BufferImageCopy> copyRegions{mipOffsets.size()};
@ -252,7 +252,7 @@ namespace SHADE
copyRegions[i].imageExtent = vk::Extent3D{ width >> i, height >> i, 1 }; copyRegions[i].imageExtent = vk::Extent3D{ width >> i, height >> i, 1 };
} }
//PrepareImageTransition(); cmdBufferHdl->CopyBufferToImage(stagingBuffer, vkImage, copyRegions);
} }
/***************************************************************************/ /***************************************************************************/
@ -274,7 +274,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkImage::PrepareImageTransition(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept void SHVkImage::PrepareImageTransitionInfo(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept
{ {
barrier.oldLayout = oldLayout; barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout; barrier.newLayout = newLayout;
@ -286,33 +286,6 @@ namespace SHADE
barrier.subresourceRange.levelCount = mipLevelCount; barrier.subresourceRange.levelCount = mipLevelCount;
barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = layerCount; barrier.subresourceRange.layerCount = layerCount;
vk::PipelineStageFlagBits srcStage = vk::PipelineStageFlagBits::eTopOfPipe;
vk::PipelineStageFlagBits dstStage = vk::PipelineStageFlagBits::eTopOfPipe;
if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal)
{
srcStage = vk::PipelineStageFlagBits::eTopOfPipe;
dstStage = vk::PipelineStageFlagBits::eTransfer;
barrier.srcAccessMask = vk::AccessFlagBits::eNone;
barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
}
else if (oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal)
{
srcStage = vk::PipelineStageFlagBits::eTransfer;
// TODO, what if we want to access in compute shader
dstStage = vk::PipelineStageFlagBits::eFragmentShader;
barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
}
else
{
SHLOG_ERROR("Image layouts are invalid. ");
}
} }
void SHVkImage::LinkWithExteriorImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t layers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept void SHVkImage::LinkWithExteriorImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t layers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept

View File

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

View File

@ -4,4 +4,9 @@
namespace SHADE namespace SHADE
{ {
vk::Sampler SHVkSampler::GetVkSampler(void) const noexcept
{
return vkSampler;
}
} }

View File

@ -22,6 +22,7 @@ namespace SHADE
SHVkSampler (SHVkSampler&& rhs) noexcept; SHVkSampler (SHVkSampler&& rhs) noexcept;
SHVkSampler&& operator=(SHVkSampler&& rhs) noexcept; SHVkSampler&& operator=(SHVkSampler&& rhs) noexcept;
vk::Sampler GetVkSampler (void) const noexcept;
}; };
} }

View File

@ -22,6 +22,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/Pipeline/SHVkPipeline.h" #include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h" #include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE namespace SHADE
{ {
@ -33,6 +35,9 @@ namespace SHADE
{ {
if (!pipeline) if (!pipeline)
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!"); throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
// Mark all as dirty
setAllDirtyFlags();
} }
void SHBatch::Add(const SHRenderable* renderable) void SHBatch::Add(const SHRenderable* renderable)
@ -52,6 +57,9 @@ namespace SHADE
// Add renderable in // Add renderable in
subBatch->Renderables.insert(renderable); subBatch->Renderables.insert(renderable);
// Mark all as dirty
setAllDirtyFlags();
} }
void SHBatch::Remove(const SHRenderable* renderable) void SHBatch::Remove(const SHRenderable* renderable)
@ -67,6 +75,10 @@ namespace SHADE
return; return;
subBatch->Renderables.erase(renderable); subBatch->Renderables.erase(renderable);
// Mark all as dirty
for (bool& dirt : isDirty)
dirt = true;
} }
void SHBatch::Clear() void SHBatch::Clear()
@ -81,15 +93,56 @@ namespace SHADE
// Clear GPU buffers // Clear GPU buffers
drawDataBuffer.Free(); for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
transformDataBuffer.Free(); {
matPropsBuffer.Free(); drawDataBuffer[i].Free();
transformDataBuffer[i].Free();
matPropsBuffer[i].Free();
}
} }
void SHBatch::Build(Handle<SHVkLogicalDevice> device) void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
{ {
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
return;
}
// Reset Transform Data
transformData.clear();
// Populate on the CPU
for (auto& subBatch : subBatches)
for (const SHRenderable* renderable : subBatch.Renderables)
{
// Transform
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(renderable->GetEID());
if (!transform)
{
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
transformData.emplace_back();
}
else
{
transformData.emplace_back(transform->GetTRS());
}
}
// Transfer to GPU
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), transformData.size() * sizeof(SHMatrix), 0, 0);
}
void SHBatch::Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex)
{
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{
SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index.");
return;
}
// No need to build as there are no changes // No need to build as there are no changes
if (!isDirty) if (!isDirty[frameIndex])
return; return;
// Count number of elements // Count number of elements
@ -99,108 +152,131 @@ namespace SHADE
numTotalElements += subBatch.Renderables.size(); numTotalElements += subBatch.Renderables.size();
} }
// Generate CPU buffers // Generate CPU buffers if there are changes
// - Draw data if (isCPUBuffersDirty)
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(); // - Draw data
matPropTotalBytes = drawData.size() * singleMatPropSize; drawData.reserve(subBatches.size());
if (matPropsDataSize < matPropTotalBytes) 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)
{ {
matPropsData.reset(new char[matPropTotalBytes]); singleMatPropSize = SHADER_INFO->GetBytesRequired();
matPropsDataSize = matPropTotalBytes; matPropTotalBytes = drawData.size() * singleMatPropSize;
} if (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); matPropsData.reset(new char[matPropTotalBytes]);
propsCurrPtr += singleMatPropSize; 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
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(renderable->GetEID());
if (!transform)
{
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
transformData.emplace_back();
}
else
{
transformData.emplace_back(transform->GetTRS());
}
// Material Properties
if (!EMPTY_MAT_PROPS)
{
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
propsCurrPtr += singleMatPropSize;
}
}
}
// Successfully update CPU buffers
isCPUBuffersDirty = false;
} }
// Send all buffered data to the GPU buffers // Send all buffered data to the GPU buffers
using BuffUsage = vk::BufferUsageFlagBits; using BuffUsage = vk::BufferUsageFlagBits;
// - Draw Data // - Draw Data
if (drawDataBuffer)
drawDataBuffer->Unmap();
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand)); const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, drawDataBuffer, drawData.data(), DRAW_DATA_BYTES, device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
BuffUsage::eIndirectBuffer BuffUsage::eIndirectBuffer
); );
drawDataBuffer->Map();
// - Transform Buffer // - Transform Buffer
if (transformDataBuffer)
transformDataBuffer->Unmap();
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)); const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, transformDataBuffer, transformData.data(), TF_DATA_BYTES, device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer
); );
transformDataBuffer->Map();
// - Material Properties Buffer // - Material Properties Buffer
if (!EMPTY_MAT_PROPS) if (matPropsData)
{ {
if (matPropsBuffer)
matPropsBuffer->Unmap();
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, matPropsBuffer, matPropsData.get(), static_cast<uint32_t>(matPropTotalBytes), device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
BuffUsage::eStorageBuffer BuffUsage::eStorageBuffer
); );
matPropsBuffer->Map();
} }
isDirty = false; isDirty[frameIndex] = false;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* SHBatch - Usage Functions */ /* SHBatch - Usage Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer) void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
{ {
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{
SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
return;
}
cmdBuffer->BindPipeline(pipeline); cmdBuffer->BindPipeline(pipeline);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer, 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
cmdBuffer->DrawMultiIndirect(drawDataBuffer, static_cast<uint32_t>(drawData.size())); cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
}
/*---------------------------------------------------------------------------------*/
/* SHBatch - Helper Functions */
/*---------------------------------------------------------------------------------*/
void SHBatch::setAllDirtyFlags()
{
for (bool& dirt : isDirty)
dirt = true;
isCPUBuffersDirty = true;
} }
} }

View File

@ -14,12 +14,14 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes // STL Includes
#include <unordered_set> #include <unordered_set>
#include <array>
// External Dependencies // External Dependencies
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
// Project Includes // Project Includes
#include "Resource/Handle.h" #include "Resource/Handle.h"
#include "Graphics/MiddleEnd/Interface/SHMaterial.h" #include "Graphics/MiddleEnd/Interface/SHMaterial.h"
#include "Math/SHMatrix.h" #include "Math/SHMatrix.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
namespace SHADE namespace SHADE
{ {
@ -71,8 +73,9 @@ namespace SHADE
void Add(const SHRenderable* renderable); void Add(const SHRenderable* renderable);
void Remove(const SHRenderable* renderable); void Remove(const SHRenderable* renderable);
void Clear(); void Clear();
void Build(Handle<SHVkLogicalDevice> device); void UpdateTransformBuffer(uint32_t frameIndex);
void Draw(Handle<SHVkCommandBuffer> cmdBuffer); void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
@ -87,15 +90,21 @@ namespace SHADE
Handle<SHVkPipeline> pipeline; Handle<SHVkPipeline> pipeline;
// Batch Tree // Batch Tree
std::vector<SHSubBatch> subBatches; std::vector<SHSubBatch> subBatches;
bool isDirty = true; std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> isDirty;
// CPU Buffers // CPU Buffers
std::vector<vk::DrawIndexedIndirectCommand> drawData; std::vector<vk::DrawIndexedIndirectCommand> drawData;
std::vector<SHMatrix> transformData; std::vector<SHMatrix> transformData;
std::unique_ptr<char> matPropsData; std::unique_ptr<char> matPropsData;
Byte matPropsDataSize = 0; Byte matPropsDataSize = 0;
bool isCPUBuffersDirty = true;
// GPU Buffers // GPU Buffers
Handle<SHVkBuffer> drawDataBuffer; std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer;
Handle<SHVkBuffer> transformDataBuffer; std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> transformDataBuffer;
Handle<SHVkBuffer> matPropsBuffer; std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> matPropsBuffer;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
void setAllDirtyFlags();
}; };
} }

View File

@ -91,12 +91,12 @@ namespace SHADE
(*superBatch)->Remove(renderable); (*superBatch)->Remove(renderable);
} }
void SHBatcher::FinaliseBatches(Handle<SHVkLogicalDevice> device) void SHBatcher::FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex)
{ {
// Build SuperBatches // Build SuperBatches
for (auto& batch : superBatches) for (auto& batch : superBatches)
{ {
batch->Build(device); batch->Build(device, frameIndex);
} }
} }
@ -109,6 +109,14 @@ namespace SHADE
superBatches.clear(); superBatches.clear();
} }
void SHBatcher::UpdateTransformBuffer(uint32_t frameIndex)
{
for (auto& batch : superBatches)
{
batch->UpdateTransformBuffer(frameIndex);
}
}
void SHBatcher::RegisterSuperBatch(Handle<SHSuperBatch> superBatch) void SHBatcher::RegisterSuperBatch(Handle<SHSuperBatch> superBatch)
{ {
superBatches.emplace_back(superBatch); superBatches.emplace_back(superBatch);

View File

@ -51,8 +51,9 @@ namespace SHADE
void PrepareBatches(); void PrepareBatches();
void AddToBatch(SHRenderable const* renderable); void AddToBatch(SHRenderable const* renderable);
void RemoveFromBatch(SHRenderable const* renderable); void RemoveFromBatch(SHRenderable const* renderable);
void FinaliseBatches(Handle<SHVkLogicalDevice> device); void FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
void ClearBatches(); void ClearBatches();
void UpdateTransformBuffer(uint32_t frameIndex);
void RegisterSuperBatch(Handle<SHSuperBatch> superBatch); void RegisterSuperBatch(Handle<SHSuperBatch> superBatch);
void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch); void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch);

View File

@ -78,21 +78,29 @@ namespace SHADE
batches.clear(); batches.clear();
} }
void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device) noexcept void SHSuperBatch::UpdateTransformBuffer(uint32_t frameIndex)
{ {
// Build all batches
for (auto& batch : batches) for (auto& batch : batches)
{ {
batch.Build(device); batch.UpdateTransformBuffer(frameIndex);
} }
} }
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer) noexcept void SHSuperBatch::Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept
{ {
// Build all batches // Build all batches
for (auto& batch : batches) for (auto& batch : batches)
{ {
batch.Draw(cmdBuffer); batch.Build(device, frameIndex);
}
}
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
// Build all batches
for (auto& batch : batches)
{
batch.Draw(cmdBuffer, frameIndex);
} }
} }

View File

@ -55,8 +55,9 @@ namespace SHADE
void Add(const SHRenderable* renderable) noexcept; void Add(const SHRenderable* renderable) noexcept;
void Remove(const SHRenderable* renderable) noexcept; void Remove(const SHRenderable* renderable) noexcept;
void Clear() noexcept; void Clear() noexcept;
void Build(Handle<SHVkLogicalDevice> device) noexcept; void UpdateTransformBuffer(uint32_t frameIndex);
void Draw(Handle<SHVkCommandBuffer> cmdBuffer) noexcept; void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept;
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */

View File

@ -2,6 +2,7 @@
#include "SHGraphicsGlobalData.h" #include "SHGraphicsGlobalData.h"
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Pipeline/SHPipelineState.h" #include "Graphics/Pipeline/SHPipelineState.h"
#include "Graphics/Pipeline/SHVkPipelineLayout.h"
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
namespace SHADE namespace SHADE
@ -27,7 +28,7 @@ namespace SHADE
}; };
// For global data (generic data and textures) // For global data (generic data and textures)
Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout({ genericDataBinding, texturesBinding }); Handle<SHVkDescriptorSetLayout> staticGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,{ genericDataBinding, texturesBinding });
SHVkDescriptorSetLayout::Binding lightBinding SHVkDescriptorSetLayout::Binding lightBinding
{ {
@ -38,7 +39,7 @@ namespace SHADE
}; };
// For Dynamic global data (lights) // For Dynamic global data (lights)
Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout({ lightBinding }); Handle<SHVkDescriptorSetLayout> dynamicGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, { lightBinding });
SHVkDescriptorSetLayout::Binding cameraDataBinding SHVkDescriptorSetLayout::Binding cameraDataBinding
{ {
@ -49,7 +50,7 @@ namespace SHADE
}; };
// For High frequency global data (camera) // For High frequency global data (camera)
Handle<SHVkDescriptorSetLayout> cameraDataGlobalLayout = logicalDevice->CreateDescriptorSetLayout({ cameraDataBinding }); Handle<SHVkDescriptorSetLayout> cameraDataGlobalLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, { cameraDataBinding });
SHVkDescriptorSetLayout::Binding materialDataBinding SHVkDescriptorSetLayout::Binding materialDataBinding
{ {
@ -60,12 +61,15 @@ namespace SHADE
}; };
// For High frequency global data (camera) // For High frequency global data (camera)
Handle<SHVkDescriptorSetLayout> materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout({ materialDataBinding }); Handle<SHVkDescriptorSetLayout> materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, { materialDataBinding });
globalDescSetLayouts.push_back(staticGlobalLayout); globalDescSetLayouts.push_back(staticGlobalLayout);
globalDescSetLayouts.push_back(dynamicGlobalLayout); globalDescSetLayouts.push_back(dynamicGlobalLayout);
globalDescSetLayouts.push_back(cameraDataGlobalLayout); globalDescSetLayouts.push_back(cameraDataGlobalLayout);
globalDescSetLayouts.push_back(materialDataPerInstanceLayout); globalDescSetLayouts.push_back(materialDataPerInstanceLayout);
dummyPipelineLayout = logicalDevice->CreatePipelineLayoutDummy(SHPipelineLayoutParamsDummy{globalDescSetLayouts});
} }
void SHGraphicsGlobalData::InitDefaultVertexInputState(void) noexcept void SHGraphicsGlobalData::InitDefaultVertexInputState(void) noexcept
@ -94,4 +98,9 @@ namespace SHADE
return defaultVertexInputState; return defaultVertexInputState;
} }
Handle<SHVkPipelineLayout> SHGraphicsGlobalData::GetDummyPipelineLayout(void) const noexcept
{
return dummyPipelineLayout;
}
} }

View File

@ -9,6 +9,7 @@ namespace SHADE
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHVkDescriptorSetLayout; class SHVkDescriptorSetLayout;
class SHVkDescriptorSetGroup; class SHVkDescriptorSetGroup;
class SHVkPipelineLayout;
class SH_API SHGraphicsGlobalData class SH_API SHGraphicsGlobalData
{ {
@ -22,6 +23,10 @@ namespace SHADE
//! Default vertex input state (used by everything). //! Default vertex input state (used by everything).
SHVertexInputState defaultVertexInputState; SHVertexInputState defaultVertexInputState;
//! Since we want to bind global data but can't do so without a pipeline layout,
//! we create a dummy pipeline layout to use it for binding.
Handle<SHVkPipelineLayout> dummyPipelineLayout;
void InitDescSetLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept; void InitDescSetLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
void InitDefaultVertexInputState(void) noexcept; void InitDefaultVertexInputState(void) noexcept;
public: public:
@ -35,5 +40,6 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescSetLayouts (void) const noexcept; std::vector<Handle<SHVkDescriptorSetLayout>> const& GetDescSetLayouts (void) const noexcept;
SHVertexInputState const& GetDefaultViState (void) const noexcept; SHVertexInputState const& GetDefaultViState (void) const noexcept;
Handle<SHVkPipelineLayout> GetDummyPipelineLayout (void) const noexcept;
}; };
} }

View File

@ -22,24 +22,24 @@ namespace SHADE
void SHCamera::SetLookAt(const SHVec3& pos, const SHVec3& target, const SHVec3& up) void SHCamera::SetLookAt(const SHVec3& pos, const SHVec3& target, const SHVec3& up)
{ {
SHVec3 view = target - pos; view = SHVec3::Normalise(view); SHVec3 view = target - pos; view = SHVec3::Normalise(view);
SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right); SHVec3 right = SHVec3::Cross(view, up); right = SHVec3::Normalise(right);
const SHVec3 UP = SHVec3::Cross(right, view); const SHVec3 UP = SHVec3::Cross(right, view);
viewMatrix = SHMatrix::Identity; viewMatrix = SHMatrix::Identity;
viewMatrix(0, 0) = right[0]; viewMatrix(0, 0) = UP[0];
viewMatrix(1, 0) = right[1]; viewMatrix(1, 0) = UP[1];
viewMatrix(2, 0) = right[2]; viewMatrix(2, 0) = UP[2];
viewMatrix(0, 1) = UP[0]; viewMatrix(0, 1) = right[0];
viewMatrix(1, 1) = UP[1]; viewMatrix(1, 1) = right[1];
viewMatrix(2, 1) = UP[2]; viewMatrix(2, 1) = right[2];
viewMatrix(0, 2) = -view[0]; viewMatrix(0, 2) = view[0];
viewMatrix(1, 2) = -view[1]; viewMatrix(1, 2) = view[1];
viewMatrix(2, 2) = -view[2]; viewMatrix(2, 2) = view[2];
viewMatrix(3, 0) = -right.Dot(pos); viewMatrix(3, 0) = -UP.Dot(pos);
viewMatrix(3, 1) = -UP.Dot(pos); viewMatrix(3, 1) = -right.Dot(pos);
viewMatrix(3, 2) = view.Dot(pos); viewMatrix(3, 2) = -view.Dot(pos);
isDirty = true; isDirty = true;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -29,6 +29,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Batching/SHSuperBatch.h" #include "Graphics/MiddleEnd/Batching/SHSuperBatch.h"
#include "SHGraphicsConstants.h" #include "SHGraphicsConstants.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h" #include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "Graphics/Buffers/SHVkBuffer.h"
namespace SHADE namespace SHADE
{ {
@ -113,7 +114,8 @@ namespace SHADE
screenCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f)); 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); screenCamera->SetOrthographic(static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.01f, 100.0f);
worldCamera = resourceManager.Create<SHCamera>(); 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->SetLookAt(SHVec3(1.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f));
worldCamera->SetLookAt(SHVec3(0.0f, 5.0f, -1.0f), SHVec3(0.0f, 0.0f, 2.0f), SHVec3(0.0f, 1.0f, 0.0f));
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f); worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
// Create Default Viewport // Create Default Viewport
@ -129,7 +131,7 @@ namespace SHADE
} }
// Initialize world render graph // Initialize world render graph
worldRenderGraph->Init(device, swapchain, renderContextCmdPools, globalData); worldRenderGraph->Init(device, swapchain, globalData);
//worldRenderGraph->AddResource("Position", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat); //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("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("Composite", SH_ATT_DESC_TYPE::COLOR, windowDims.first, windowDims.second, vk::Format::eR16G16B16A16Sfloat);
@ -167,7 +169,7 @@ namespace SHADE
debugWorldRenderer->SetCamera(worldCamera);*/ debugWorldRenderer->SetCamera(worldCamera);*/
// Add world renderer to default viewport // Add world renderer to default viewport
worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), descPool, globalData->GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph); worldRenderer = defaultViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, globalData->GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera); worldRenderer->SetCamera(worldCamera);
@ -203,6 +205,7 @@ namespace SHADE
{ {
// Frame data for the current frame // Frame data for the current frame
auto const& frameData = renderContext.GetCurrentFrameData(); auto const& frameData = renderContext.GetCurrentFrameData();
uint32_t frameIndex = renderContext.GetCurrentFrame();
// semaphore index. This is for render graphs to have semaphores to signal that the next render graph will use to wait on. // 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; bool semIndex = 0;
@ -219,7 +222,6 @@ namespace SHADE
renderContext.ResetFence(); renderContext.ResetFence();
// For every viewport // For every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex) for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
{ {
@ -228,16 +230,42 @@ namespace SHADE
// For every renderer // For every renderer
for (int renIndex = 0; renIndex < static_cast<int>(renderers.size()); ++renIndex) for (int renIndex = 0; renIndex < static_cast<int>(renderers.size()); ++renIndex)
{ {
// Draw first /*-----------------------------------------------------------------------*/
renderers[renIndex]->Draw(renderContext.GetCurrentFrame(), MESH_DATA); /* Renderer start */
/*-----------------------------------------------------------------------*/
// get command buffer of the renderer in the current frame
auto currentCmdBuffer = renderers[renIndex]->GetCommandBuffer(frameIndex);
// get render graph // Begin recording the command buffer
auto rg = renderers[renIndex]->GetRenderGraph(); currentCmdBuffer->BeginRecording();
currentCmdBuffer->ForceSetPipelineLayout(globalData->GetDummyPipelineLayout());
// Bind all the buffers required for meshes
for (auto& [buffer, bindingPoint] : MESH_DATA)
{
if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eVertexBuffer)
currentCmdBuffer->BindVertexBuffer(bindingPoint, buffer, 0);
else if (buffer->GetUsageBits() & vk::BufferUsageFlagBits::eIndexBuffer)
currentCmdBuffer->BindIndexBuffer(buffer, 0);
}
// bind camera data
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
// Draw first
renderers[renIndex]->Draw(frameIndex);
// End the command buffer recording
currentCmdBuffer->EndRecording();
/*-----------------------------------------------------------------------*/
/* Renderer end */
/*-----------------------------------------------------------------------*/
// submit a command buffer from the current render graph and make it wait for the previous render graph before submitting it to GPU. // 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 graphicsQueue->SubmitCommandBuffer
( (
{ rg->GetCommandBuffer(renderContext.GetCurrentFrame()) }, { currentCmdBuffer },
{ (vpIndex == viewports.size() - 1 && renIndex == renderers.size() - 1) ? frameData.semRenderFinishHdl : graphSemaphores[!semIndex] }, { (vpIndex == viewports.size() - 1 && renIndex == renderers.size() - 1) ? frameData.semRenderFinishHdl : graphSemaphores[!semIndex] },
{ (vpIndex == 0 && renIndex == 0) ? frameData.semImgAvailableHdl : graphSemaphores[semIndex] }, { (vpIndex == 0 && renIndex == 0) ? frameData.semImgAvailableHdl : graphSemaphores[semIndex] },
{ vk::PipelineStageFlagBits::eColorAttachmentOutput }, { vk::PipelineStageFlagBits::eColorAttachmentOutput },
@ -279,7 +307,7 @@ namespace SHADE
for (auto vp : viewports) for (auto vp : viewports)
for (auto renderer : vp->GetRenderers()) for (auto renderer : vp->GetRenderers())
{ {
renderer->GetRenderGraph()->FinaliseBatch(); renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame());
} }
// Resize // Resize

View File

@ -27,7 +27,6 @@ namespace SHADE
sharedMaterial = {}; sharedMaterial = {};
material = {}; material = {};
oldMaterial = {}; oldMaterial = {};
} }
void SHRenderable::OnDestroy() void SHRenderable::OnDestroy()
@ -93,5 +92,4 @@ namespace SHADE
materialChanged = false; materialChanged = false;
oldMaterial = {}; oldMaterial = {};
} }
} }

View File

@ -66,7 +66,6 @@ namespace SHADE
/* Data Members */ /* Data Members */
/*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/
Handle<SHMesh> Mesh; Handle<SHMesh> Mesh;
SHMatrix TransformMatrix; // TODO: Replace with Transform component
private: private:
/*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/

View File

@ -20,20 +20,33 @@ of DigiPen Institute of Technology is prohibited.
#include "SHMaterial.h" #include "SHMaterial.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" #include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" #include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Buffers/SHVkBuffer.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Constructor/Destructors */ /* Constructor/Destructors */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHRenderer::SHRenderer(Handle<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph) SHRenderer::SHRenderer(Handle<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph)
: viewport { viewport } : viewport { viewport }
, renderGraph { renderGraph } , renderGraph { renderGraph }
{ {
cameraDescriptorSet = logicalDevice->CreateDescriptorSetGroup(descriptorPool, { cameraDescLayout }, { 1 }); commandBuffers.resize(static_cast<std::size_t>(numFrames));
cpuCameraData.resize(numFrames);
for (uint32_t i = 0; i < commandBuffers.size(); ++i)
commandBuffers[i] = cmdPools[i]->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
cameraDescriptorSet = descriptorPool->Allocate({ cameraDescLayout }, { 1 });
cameraDataAlignedSize = logicalDevice->PadUBOSize(sizeof(SHShaderCameraData)); cameraDataAlignedSize = logicalDevice->PadUBOSize(sizeof(SHShaderCameraData));
cameraBuffer = logicalDevice->CreateBuffer(cameraDataAlignedSize * numFrames, nullptr, cameraDataAlignedSize * numFrames, vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT);
std::array cameraBufferArray{cameraBuffer};
cameraDescriptorSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA, std::span<Handle<SHVkBuffer>>{ cameraBufferArray.data(), cameraBufferArray.size()}, 0, sizeof (SHShaderCameraData));
cameraDescriptorSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -47,21 +60,33 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Drawing Functions */ /* Drawing Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHRenderer::Draw(uint32_t frameIndex, std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> graphScopeBuffers) noexcept void SHRenderer::Draw(uint32_t frameIndex) noexcept
{ {
renderGraph->Execute(frameIndex, graphScopeBuffers); renderGraph->Execute(frameIndex, commandBuffers[frameIndex]);
} }
void SHRenderer::BindDescriptorSet(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{ {
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize }; cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 }); cmdBuffer->BindDescriptorSet(cameraDescriptorSet, vk::PipelineBindPoint::eGraphics, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
} }
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
{
}
Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept
{ {
return renderGraph; return renderGraph;
} }
Handle<SHVkCommandBuffer> SHRenderer::GetCommandBuffer(uint32_t frameIndex) const noexcept
{
return commandBuffers[frameIndex];
}
} }

View File

@ -39,6 +39,7 @@ namespace SHADE
class SHVkDescriptorSetGroup; class SHVkDescriptorSetGroup;
class SHGraphicsGlobalData; class SHGraphicsGlobalData;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHVkBuffer;
struct SHShaderCameraData struct SHShaderCameraData
{ {
@ -63,7 +64,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */ /* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
SHRenderer(Handle<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph); SHRenderer(Handle<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Camera Registration */ /* Camera Registration */
@ -73,13 +74,15 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Drawing Functions */ /* Drawing Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void Draw(uint32_t frameIndex, std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> graphScopeBuffers) noexcept; void Draw(uint32_t frameIndex) noexcept;
void BindDescriptorSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void UpdateDataAndBind (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void UpdateCameraDataToBuffer (void) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Setters and Getters */ /* Setters and Getters */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHRenderGraph> GetRenderGraph (void) const noexcept; Handle<SHRenderGraph> GetRenderGraph (void) const noexcept;
Handle<SHVkCommandBuffer> GetCommandBuffer(uint32_t frameIndex) const noexcept;
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -92,7 +95,16 @@ namespace SHADE
Handle<SHCamera> camera; Handle<SHCamera> camera;
Handle<SHRenderGraph> renderGraph; Handle<SHRenderGraph> renderGraph;
Handle<SHVkDescriptorSetGroup> cameraDescriptorSet; Handle<SHVkDescriptorSetGroup> cameraDescriptorSet;
std::vector<SHShaderCameraData> cpuCameraData; Handle<SHVkBuffer> cameraBuffer;
// we really only need 1 copy even though we need %swapchainImages copies for
// GPU.
SHShaderCameraData cpuCameraData;
//! Command buffers for the render graph
std::vector<Handle<SHVkCommandBuffer>> commandBuffers;
}; };
} }

View File

@ -49,10 +49,10 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Renderer Registration Functions */ /* Renderer Registration Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
Handle<SHRenderer> SHViewport::AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph) Handle<SHRenderer> SHViewport::AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph)
{ {
// Create the renderer // Create the renderer
auto renderer = resourceManager.Create<SHRenderer>(device, numFrames, descriptorPool, cameraDescLayout, GetHandle(), renderGraph); auto renderer = resourceManager.Create<SHRenderer>(device, numFrames, cmdPools, descriptorPool, cameraDescLayout, GetHandle(), renderGraph);
// Store // Store
renderers.emplace_back(renderer); renderers.emplace_back(renderer);

View File

@ -32,6 +32,7 @@ namespace SHADE
class SHRenderGraph; class SHRenderGraph;
class SHVkDescriptorPool; class SHVkDescriptorPool;
class SHVkDescriptorSetLayout; class SHVkDescriptorSetLayout;
class SHVkCommandPool;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -58,7 +59,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Renderers Registration Functions */ /* Renderers Registration Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHRenderer> AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph); Handle<SHRenderer> AddRenderer(ResourceManager& resourceManager, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHRenderGraph> renderGraph);
void RemoveRenderer(Handle<SHRenderer> renderer); void RemoveRenderer(Handle<SHRenderer> renderer);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -18,7 +18,7 @@ namespace SHADE
auto pipelineLayout = logicalDevice->CreatePipelineLayout(params); auto pipelineLayout = logicalDevice->CreatePipelineLayout(params);
// Create the pipeline and configure the default vertex input state // Create the pipeline and configure the default vertex input state
auto newPipeline = logicalDevice->CreatePipeline(pipelineLayout, nullptr, renderpass, subpass, SH_PIPELINE_TYPE::GRAPHICS); auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass);
newPipeline->GetPipelineState().SetVertexInputState(globalData->GetDefaultViState()); newPipeline->GetPipelineState().SetVertexInputState(globalData->GetDefaultViState());
// Actually construct the pipeline // Actually construct the pipeline

View File

@ -0,0 +1,142 @@
/************************************************************************************//*!
\file SHTextureLibrary.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 20, 2022
\brief Contains definitions for all of the functions of the classes that deal
with storage and management of buffers for textures.
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 "SHTextureLibrary.h"
#include "Graphics/SHVulkanIncludes.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Commands/SHVkCommandBuffer.h"
#include "Graphics/SHVkUtil.h"
#include "Tools/SHLogger.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHTexture> SHTextureLibrary::Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, SHTexture::TextureFormat format, uint32_t mipLevels)
{
isDirty = true;
auto handle = resourceManager.Create<SHTexture>();
addJobs.emplace_back(AddJob { pixelCount, pixelData, format, mipLevels });
return handle;
}
void SHTextureLibrary::Remove(Handle<SHTexture> texture)
{
if (!texture)
throw std::invalid_argument("Attempted to remove a Texture that did not belong to the Texture Library!");
removeJobs.emplace_back(texture);
isDirty = true;
}
void SHTextureLibrary::BuildImages(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> descLayout)
{
/* Remove Textures */
std::vector<vk::ImageMemoryBarrier> pipelineBarriers(addJobs.size());
/* Add Textures */
// Transition
for (int i = 0; auto& job : addJobs)
{
job.Image = resourceManager.Create<SHVkImage>();
job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, pipelineBarriers[i]);
++i;
}
vk::PipelineStageFlagBits srcStage = vk::PipelineStageFlagBits::eTopOfPipe;
vk::PipelineStageFlagBits dstStage = vk::PipelineStageFlagBits::eTopOfPipe;
preparePipelineBarriers(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, srcStage, dstStage, pipelineBarriers);
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers);
// Copy
for (auto& job : addJobs)
{
job.Image->TransferToDeviceResource(cmdBuffer);
}
// Transition
for (int i = 0; auto & job : addJobs)
{
// Transition
job.Image->PrepareImageTransitionInfo(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, pipelineBarriers[i]);
}
preparePipelineBarriers(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, srcStage, dstStage, pipelineBarriers);
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, pipelineBarriers);
// Execute Commands
graphicsQueue->SubmitCommandBuffer({ cmdBuffer });
device->WaitIdle();
// Create Image View
for (auto& job : addJobs)
{
const SHImageViewDetails DETAILS
{
.viewType = vk::ImageViewType::e2D,
.format = job.TextureFormat,
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.mipLevelCount = job.MipLevels,
.baseArrayLayer = 0,
.layerCount = 0
};
job.Handle->ImageView = job.Image->CreateImageView(device, job.Image, DETAILS);
}
// Build Descriptor
Handle<SHVkDescriptorSetGroup> descSetGroup = descPool->Allocate({ descLayout }, { 1 });
isDirty = false;
}
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
void SHTextureLibrary::preparePipelineBarriers(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::PipelineStageFlagBits& srcStage, vk::PipelineStageFlagBits& dstStage, std::vector<vk::ImageMemoryBarrier>& barriers)
{
if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal)
{
srcStage = vk::PipelineStageFlagBits::eTopOfPipe;
dstStage = vk::PipelineStageFlagBits::eTransfer;
for (auto& barrier : barriers)
{
barrier.srcAccessMask = vk::AccessFlagBits::eNone;
barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
}
}
else if (oldLayout == vk::ImageLayout::eTransferDstOptimal && newLayout == vk::ImageLayout::eShaderReadOnlyOptimal)
{
srcStage = vk::PipelineStageFlagBits::eTransfer;
// TODO, what if we want to access in compute shader
dstStage = vk::PipelineStageFlagBits::eFragmentShader;
for (auto& barrier : barriers)
{
barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
}
}
else
{
SHLOG_ERROR("Image layouts are invalid. ");
}
}
}

View File

@ -0,0 +1,163 @@
/************************************************************************************//*!
\file SHTextureLibrary.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 20, 2022
\brief Contains definitions for all of the classes that deal with storage and
management of textures.
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"
#include "Graphics/SHVulkanIncludes.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
class SHVkBuffer;
class SHVkLogicalDevice;
class SHVkCommandBuffer;
class SHVkImage;
class SHVkImageView;
class SHVkQueue;
class SHVkDescriptorPool;
class SHVkDescriptorSetLayout;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
class SHTexture
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
using PixelChannel = float;
using TextureFormat = vk::Format; // TODO: Change
using Index = uint32_t;
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Handle<SHVkImageView> ImageView;
Index TextureArrayIndex = std::numeric_limits<Index>::max();
};
/***********************************************************************************/
/*!
\brief
Manages storage for all textures in the Graphics System as a single set of
textures.
*/
/***********************************************************************************/
class SHTextureLibrary
{
public:
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/*******************************************************************************/
/*!
\brief
Adds a texture to the Texture Library. But this does not mean that the
textures have been added yet. A call to "BuildImages()" is required to
transfer all textures into the GPU.
\param pixelCount
Number of pixels in this Mesh.
\param positions
Pointer to the first in a contiguous array of SHMathVec3s that define vertex
positions.
\param format
Format of the texture loaded in.
\return
Handle to the created Texture. This is not valid to be used until a call to
BuildImages().
*/
/*******************************************************************************/
Handle<SHTexture> Add(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, SHTexture::TextureFormat format, uint32_t mipLevels);
/*******************************************************************************/
/*!
\brief
Removes a mesh from the Texture Library. But this does not mean that the
textures have been removed yet. A call to "BuildImages()" is required to
finalise all changes.
\param mesh
Handle to the mesh to remove.
*/
/*******************************************************************************/
void Remove(Handle<SHTexture> mesh);
/***************************************************************************/
/*!
\brief
Finalises all changes to the Texture Library 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 BuildImages(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> descLayout);
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHVkBuffer> GetTextureBuffer() const noexcept { return texStorageBuffer; }
private:
/*-----------------------------------------------------------------------------*/
/* Type Definition */
/*-----------------------------------------------------------------------------*/
struct AddJob
{
uint32_t PixelCount = 0;
const SHTexture::PixelChannel* PixelData = nullptr;
SHTexture::TextureFormat TextureFormat = {};
uint32_t MipLevels = 0;
Handle<SHVkImage> Image;
Handle<SHTexture> Handle;
};
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
// Manipulation Queues
std::vector<AddJob> addJobs;
std::vector<Handle<SHTexture>> removeJobs;
// Tracking
ResourceManager resourceManager;
std::vector<Handle<SHTexture>> texOrder;
// CPU Storage
std::vector<SHTexture::PixelChannel> texStorage;
// GPU Storage
Handle<SHVkBuffer> texStorageBuffer{};
// Flags
bool isDirty = true;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
void preparePipelineBarriers(vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::PipelineStageFlagBits& srcStage, vk::PipelineStageFlagBits& dstStage, std::vector<vk::ImageMemoryBarrier>& barriers);
};
}

View File

@ -25,6 +25,15 @@ namespace SHADE
//! want to use it for allocating descriptor sets. //! want to use it for allocating descriptor sets.
std::vector<Handle<SHVkDescriptorSetLayout>> const& globalDescSetLayouts = {}; std::vector<Handle<SHVkDescriptorSetLayout>> const& globalDescSetLayouts = {};
}; };
struct SHPipelineLayoutParamsDummy
{
/*-----------------------------------------------------------------------*/
/* MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
std::vector<Handle<SHVkDescriptorSetLayout>> const& globalDescSetLayouts = {};
};
} }
#endif #endif

View File

@ -64,7 +64,7 @@ namespace SHADE
vk::CullModeFlags cull_mode{ vk::CullModeFlagBits::eBack }; vk::CullModeFlags cull_mode{ vk::CullModeFlagBits::eBack };
//! CW or CCW //! CW or CCW
vk::FrontFace frontFacingOrientation{ vk::FrontFace::eClockwise }; vk::FrontFace frontFacingOrientation{ vk::FrontFace::eCounterClockwise };
bool depthBias{ VK_FALSE }; bool depthBias{ VK_FALSE };
}; };

View File

@ -179,7 +179,7 @@ namespace SHADE
/*! /*!
\brief \brief
Non-default ctor. Non-default ctor for creating graphics pipeline.
\param inLogicalDeviceHdl \param inLogicalDeviceHdl
Needed for creation and destruction. Needed for creation and destruction.
@ -200,14 +200,12 @@ namespace SHADE
The subpass that this pipeline will be used in. If state is not The subpass that this pipeline will be used in. If state is not
nullptr, this parameter is ignored. nullptr, this parameter is ignored.
\param type
The type of the pipeline.
*/ */
/***************************************************************************/ /***************************************************************************/
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 SHVkPipeline::SHVkPipeline(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkPipelineLayout> const& inPipelineLayout, SHVkPipelineState const* const state, Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHSubpass> subpass) noexcept
: pipelineState{ } : pipelineState{ }
, pipelineType {type} , pipelineType {SH_PIPELINE_TYPE::GRAPHICS}
, vkPipeline {VK_NULL_HANDLE} , vkPipeline {VK_NULL_HANDLE}
, logicalDeviceHdl{ inLogicalDeviceHdl } , logicalDeviceHdl{ inLogicalDeviceHdl }
, pipelineLayout { inPipelineLayout } , pipelineLayout { inPipelineLayout }
@ -250,6 +248,33 @@ namespace SHADE
vkPipeline = VK_NULL_HANDLE; vkPipeline = VK_NULL_HANDLE;
} }
/***************************************************************************/
/*!
\brief
Just to differentiate between compute and graphics pipeline, we will
have a constructor that takes in less parameters; sufficient for the
compute pipeline to be created.
\param inLogicalDeviceHdl
\param inPipelineLayout
\return
*/
/***************************************************************************/
SHVkPipeline::SHVkPipeline(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkPipelineLayout> const& inPipelineLayout) noexcept
: pipelineState{ }
, pipelineType{ SH_PIPELINE_TYPE::COMPUTE }
, vkPipeline{ VK_NULL_HANDLE }
, logicalDeviceHdl{ inLogicalDeviceHdl }
, pipelineLayout{ inPipelineLayout }
, created{ false }
{
}
/***************************************************************************/ /***************************************************************************/
/*! /*!

View File

@ -51,8 +51,10 @@ namespace SHADE
Handle<SHVkPipelineLayout> const& inPipelineLayout, Handle<SHVkPipelineLayout> const& inPipelineLayout,
SHVkPipelineState const* const state, SHVkPipelineState const* const state,
Handle<SHVkRenderpass> const& renderpassHdl, Handle<SHVkRenderpass> const& renderpassHdl,
Handle<SHSubpass> subpass, Handle<SHSubpass> subpass) noexcept;
SH_PIPELINE_TYPE type) noexcept;
SHVkPipeline(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl,
Handle<SHVkPipelineLayout> const& inPipelineLayout) noexcept;
SHVkPipeline (SHVkPipeline&& rhs) noexcept; SHVkPipeline (SHVkPipeline&& rhs) noexcept;
~SHVkPipeline (void) noexcept; ~SHVkPipeline (void) noexcept;

View File

@ -198,7 +198,7 @@ namespace SHADE
// 1 descriptor set layout for every descriptor set detected. // 1 descriptor set layout for every descriptor set detected.
for (auto const& set : setsWithBindings) for (auto const& set : setsWithBindings)
{ {
auto newDescriptorSetLayout = logicalDeviceHdl->CreateDescriptorSetLayout(set.second); auto newDescriptorSetLayout = logicalDeviceHdl->CreateDescriptorSetLayout(set.first, set.second);
descriptorSetLayoutsAllocate.push_back(newDescriptorSetLayout); descriptorSetLayoutsAllocate.push_back(newDescriptorSetLayout);
} }
@ -254,12 +254,6 @@ namespace SHADE
// Clear pc ranges // Clear pc ranges
vkPcRanges.clear(); vkPcRanges.clear();
// Kill all descriptor set layouts
for (auto& layout : descriptorSetLayoutsGlobal)
SHVkInstance::GetResourceManager().Free(layout);
descriptorSetLayoutsGlobal.clear();
for (auto& layout : descriptorSetLayoutsAllocate) for (auto& layout : descriptorSetLayoutsAllocate)
SHVkInstance::GetResourceManager().Free(layout); SHVkInstance::GetResourceManager().Free(layout);
@ -285,9 +279,9 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHVkPipelineLayout::SHVkPipelineLayout(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, SHPipelineLayoutParams& pipelineLayoutParams) noexcept SHVkPipelineLayout::SHVkPipelineLayout(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, SHPipelineLayoutParams const& pipelineLayoutParams) noexcept
: vkPipelineLayout {VK_NULL_HANDLE} : vkPipelineLayout {VK_NULL_HANDLE}
, shaderModules{std::move (pipelineLayoutParams.shaderModules)} , shaderModules{pipelineLayoutParams.shaderModules}
, logicalDeviceHdl {inLogicalDeviceHdl} , logicalDeviceHdl {inLogicalDeviceHdl}
, pushConstantInterface{} , pushConstantInterface{}
, vkPcRanges{} , vkPcRanges{}
@ -308,6 +302,46 @@ namespace SHADE
RecreateIfNeeded (); RecreateIfNeeded ();
} }
SHVkPipelineLayout::SHVkPipelineLayout(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, SHPipelineLayoutParamsDummy const& pipelineLayoutParams) noexcept
: vkPipelineLayout{ VK_NULL_HANDLE }
, shaderModules{ }
, logicalDeviceHdl{ inLogicalDeviceHdl }
, pushConstantInterface{}
, vkPcRanges{}
, descriptorSetLayoutsGlobal{}
, descriptorSetLayoutsAllocate{}
, vkDescriptorSetLayoutsAllocate{}
, vkDescriptorSetLayoutsPipeline{}
{
vkDescriptorSetLayoutsPipeline.resize(pipelineLayoutParams.globalDescSetLayouts.size());
for (uint32_t i = 0; auto& layout : vkDescriptorSetLayoutsPipeline)
{
layout = pipelineLayoutParams.globalDescSetLayouts[i]->GetVkHandle();
++i;
}
vk::PipelineLayoutCreateInfo plCreateInfo{};
// Set push constant data to pipeline layout
plCreateInfo.pushConstantRangeCount = 0;
plCreateInfo.pPushConstantRanges = nullptr;
// To initialize the descriptor set layouts for the pipeline layout.
plCreateInfo.setLayoutCount = static_cast<uint32_t>(vkDescriptorSetLayoutsPipeline.size());
plCreateInfo.pSetLayouts = vkDescriptorSetLayoutsPipeline.data();
if (auto const RESULT = logicalDeviceHdl->GetVkLogicalDevice().createPipelineLayout(&plCreateInfo, nullptr, &vkPipelineLayout); RESULT != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(RESULT, "Failed to create Pipeline Layout. ");
return;
}
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created Pipeline Layout. ");
}
/***************************************************************************/ /***************************************************************************/
/*! /*!

View File

@ -57,7 +57,8 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
SHVkPipelineLayout (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, SHPipelineLayoutParams& pipelineLayoutParams) noexcept; SHVkPipelineLayout(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, SHPipelineLayoutParams const& pipelineLayoutParams) noexcept;
SHVkPipelineLayout(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, SHPipelineLayoutParamsDummy const& pipelineLayoutParams) noexcept;
SHVkPipelineLayout (SHVkPipelineLayout&& rhs) noexcept; SHVkPipelineLayout (SHVkPipelineLayout&& rhs) noexcept;
~SHVkPipelineLayout (void) noexcept; ~SHVkPipelineLayout (void) noexcept;
SHVkPipelineLayout& operator= (SHVkPipelineLayout&& rhs) noexcept; SHVkPipelineLayout& operator= (SHVkPipelineLayout&& rhs) noexcept;

View File

@ -346,10 +346,13 @@ namespace SHADE
inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal }); inputReferences.push_back({ resourceAttachmentMapping->at(ptrToResources->at(resourceToReference).GetId().Raw), vk::ImageLayout::eShaderReadOnlyOptimal });
} }
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer) noexcept void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept
{ {
// Ensure correct transforms are provided
superBatch->UpdateTransformBuffer(frameIndex);
// Draw all the batches // Draw all the batches
superBatch->Draw(commandBuffer); superBatch->Draw(commandBuffer, frameIndex);
// Draw all the exterior draw calls // Draw all the exterior draw calls
for (auto& drawCall : exteriorDrawCalls) for (auto& drawCall : exteriorDrawCalls)
@ -588,7 +591,7 @@ namespace SHADE
for (uint32_t i = 0; i < subpasses.size(); ++i) for (uint32_t i = 0; i < subpasses.size(); ++i)
{ {
subpasses[i]->Execute(commandBuffer); subpasses[i]->Execute(commandBuffer, frameIndex);
// Go to next subpass if not last subpass // Go to next subpass if not last subpass
if (i != subpasses.size() - 1) if (i != subpasses.size() - 1)
@ -621,9 +624,9 @@ namespace SHADE
return pipeline; return pipeline;
} }
void SHRenderGraphNode::FinaliseBatch() void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex)
{ {
batcher.FinaliseBatches(logicalDeviceHdl); batcher.FinaliseBatches(logicalDeviceHdl, frameIndex);
} }
/***************************************************************************/ /***************************************************************************/
@ -946,25 +949,6 @@ namespace SHADE
} }
} }
/***************************************************************************/
/*!
\brief
Configures command pools and command buffers.
*/
/***************************************************************************/
void SHRenderGraph::ConfigureCommands(void) noexcept
{
//commandPools.resize (static_cast<std::size_t>(swapchainHdl->GetNumImages()));
commandBuffers.resize(static_cast<std::size_t>(swapchainHdl->GetNumImages()));
for (uint32_t i = 0; i < commandBuffers.size(); ++i)
{
commandBuffers[i] = commandPools[i]->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
}
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -980,12 +964,11 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHVkCommandPool>> const& cmdPools, Handle<SHGraphicsGlobalData> inGlobalData) noexcept void SHRenderGraph::Init(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, Handle<SHGraphicsGlobalData> inGlobalData) noexcept
{ {
logicalDeviceHdl = logicalDevice; logicalDeviceHdl = logicalDevice;
swapchainHdl = swapchain; swapchainHdl = swapchain;
globalData = inGlobalData; globalData = inGlobalData;
commandPools = cmdPools;
} }
/***************************************************************************/ /***************************************************************************/
@ -1087,40 +1070,24 @@ namespace SHADE
ConfigureSubpasses(); ConfigureSubpasses();
ConfigureRenderpasses(); ConfigureRenderpasses();
ConfigureFramebuffers(); ConfigureFramebuffers();
ConfigureCommands();
} }
// TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a // TODO: The graph scope buffers were meant to bind vertex buffers and index buffers for meshes. Find a
// better way to manage these // better way to manage these
void SHRenderGraph::Execute(uint32_t frameIndex, std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> graphScopeBuffers) noexcept void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer) noexcept
{ {
//commandPools[frameIndex]->Reset();
auto& cmdBuffer = commandBuffers[frameIndex];
cmdBuffer->BeginRecording();
// TODO: DON'T HARDCODE THIS // TODO: DON'T HARDCODE THIS
cmdBuffer->SetViewportScissor(1920.0f, 1080.0f, 1920, 1080); cmdBuffer->SetViewportScissor(1920.0f, 1080.0f, 1920, 1080);
for (auto& [buffer, bindingPoint]: graphScopeBuffers)
{
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) for (auto& node : nodes)
node->Execute(cmdBuffer, frameIndex); node->Execute(cmdBuffer, frameIndex);
cmdBuffer->EndRecording();
} }
void SHRenderGraph::FinaliseBatch() void SHRenderGraph::FinaliseBatch(uint32_t frameIndex)
{ {
for (auto& node : nodes) for (auto& node : nodes)
{ {
node->FinaliseBatch(); node->FinaliseBatch(frameIndex);
} }
} }
@ -1132,9 +1099,5 @@ namespace SHADE
return {}; return {};
} }
Handle<SHVkCommandBuffer> const& SHRenderGraph::GetCommandBuffer(uint32_t frameIndex) const noexcept
{
return commandBuffers[frameIndex];
}
} }

View File

@ -137,7 +137,7 @@ namespace SHADE
void AddInput(std::string resourceToReference) noexcept; void AddInput(std::string resourceToReference) noexcept;
// Runtime functions // Runtime functions
void Execute(Handle<SHVkCommandBuffer>& commandBuffer) noexcept; void Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept; void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -230,7 +230,7 @@ namespace SHADE
// TODO: RemoveSubpass() // TODO: RemoveSubpass()
void Execute (Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept; void Execute (Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept;
Handle<SHVkPipeline> GetOrCreatePipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept; Handle<SHVkPipeline> GetOrCreatePipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
void FinaliseBatch(); void FinaliseBatch(uint32_t frameIndex);
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
@ -250,7 +250,6 @@ namespace SHADE
void ConfigureSubpasses (void) noexcept; void ConfigureSubpasses (void) noexcept;
void ConfigureRenderpasses (void) noexcept; void ConfigureRenderpasses (void) noexcept;
void ConfigureFramebuffers (void) noexcept; void ConfigureFramebuffers (void) noexcept;
void ConfigureCommands (void) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */ /* PRIVATE MEMBER VARIABLES */
@ -271,12 +270,6 @@ namespace SHADE
//! Resource library for graph handles //! Resource library for graph handles
ResourceManager resourceManager; ResourceManager resourceManager;
//! 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 to global data
Handle<SHGraphicsGlobalData> globalData; Handle<SHGraphicsGlobalData> globalData;
@ -290,18 +283,17 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::vector<Handle<SHVkCommandPool>> const& cmdPools, Handle<SHGraphicsGlobalData> inGlobalData) noexcept; void Init (Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, 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 = {}); 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; Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<std::string> resourceNames, std::initializer_list<std::string> predecessorNodes) noexcept;
void Generate (void) noexcept; void Generate (void) noexcept;
void Execute (uint32_t frameIndex, std::initializer_list<std::pair<Handle<SHVkBuffer>, uint32_t>> graphScopeBuffers) noexcept; void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
void FinaliseBatch(); void FinaliseBatch(uint32_t frameIndex);
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHRenderGraphNode> GetNode (std::string const& nodeName) const noexcept; Handle<SHRenderGraphNode> GetNode (std::string const& nodeName) const noexcept;
Handle<SHVkCommandBuffer> const& GetCommandBuffer (uint32_t frameIndex) const noexcept;
}; };
} }

View File

@ -71,4 +71,14 @@ namespace SHADE
); );
} }
} }
BindingAndSetHash SHVkUtil::GenBindingSetHash(uint32_t set, uint32_t binding) noexcept
{
// Find the target writeDescSet
BindingAndSetHash writeHash = binding;
writeHash |= static_cast<uint64_t>(set) << 32;
return writeHash;
}
} }

View File

@ -76,6 +76,8 @@ namespace SHADE
*/ */
/***********************************************************************************/ /***********************************************************************************/
static void EnsureBufferAndCopyHostVisibleData(Handle<SHVkLogicalDevice> device, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage); static void EnsureBufferAndCopyHostVisibleData(Handle<SHVkLogicalDevice> device, Handle<SHVkBuffer>& bufferHandle, void* src, uint32_t size, vk::BufferUsageFlagBits usage);
static BindingAndSetHash GenBindingSetHash (uint32_t set, uint32_t binding) noexcept;
}; };
} }

View File

@ -6,6 +6,8 @@
namespace SHADE namespace SHADE
{ {
using SHQueueFamilyIndex = uint32_t; using SHQueueFamilyIndex = uint32_t;
using BindingAndSetHash = uint64_t;
using SetIndex = uint32_t;
} }

View File

@ -6,5 +6,6 @@
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
#define VULKAN_HPP_NO_NODISCARD_WARNINGS #define VULKAN_HPP_NO_NODISCARD_WARNINGS
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#include "Graphics/SHVulkanDefines.h"
#endif #endif

View File

@ -9,8 +9,6 @@
namespace SHADE namespace SHADE
{ {
using BindingAndSetHash = uint64_t;
struct SHShaderDescriptorBindingInfo struct SHShaderDescriptorBindingInfo
{ {
private: private:

View File

@ -103,17 +103,17 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Script Manipulation Functions */ /* Script Manipulation Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHScriptEngine::AddScript(const SHEntity& entity, const std::string_view& scriptName) bool SHScriptEngine::AddScript(EntityID entity, const std::string_view& scriptName)
{ {
return csScriptsAdd(entity.GetEID(), scriptName.data()); return csScriptsAdd(entity, scriptName.data());
} }
void SHScriptEngine::RemoveAllScripts(const SHEntity& entity) void SHScriptEngine::RemoveAllScripts(EntityID entity)
{ {
csScriptsRemoveAll(entity.GetEID()); csScriptsRemoveAll(entity);
} }
void SHScriptEngine::RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy) void SHScriptEngine::RemoveAllScriptsImmediately(EntityID entity, bool callOnDestroy)
{ {
csScriptsRemoveAllImmediately(entity.GetEID(), callOnDestroy); csScriptsRemoveAllImmediately(entity, callOnDestroy);
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -116,14 +116,14 @@ namespace SHADE
/// True if successfully added. False otherwise with the error logged to the /// True if successfully added. False otherwise with the error logged to the
/// console. /// console.
/// </returns> /// </returns>
bool AddScript(const SHEntity& entity, const std::string_view& scriptName); bool AddScript(EntityID entity, const std::string_view& scriptName);
/// <summary> /// <summary>
/// Removes all Scripts attached to the specified Entity. Does not do anything /// Removes all Scripts attached to the specified Entity. Does not do anything
/// if the specified Entity is invalid or does not have any Scripts /// if the specified Entity is invalid or does not have any Scripts
/// attached. /// attached.
/// </summary> /// </summary>
/// <param name="entity">The entity to remove the scripts from.</param> /// <param name="entity">The entity to remove the scripts from.</param>
void RemoveAllScripts(const SHEntity& entity); void RemoveAllScripts(EntityID entity);
/// <summary> /// <summary>
/// Removes all Scripts attached to the specified Entity. Unlike /// Removes all Scripts attached to the specified Entity. Unlike
/// RemoveAllScripts(), this removes all the scripts immediately. /// RemoveAllScripts(), this removes all the scripts immediately.
@ -135,7 +135,7 @@ namespace SHADE
/// Whether or not to call OnDestroy on the scripts. This is ignored if not in /// Whether or not to call OnDestroy on the scripts. This is ignored if not in
/// play mode. /// play mode.
/// </param> /// </param>
void RemoveAllScriptsImmediately(const SHEntity& entity, bool callOnDestroy); void RemoveAllScriptsImmediately(EntityID entity, bool callOnDestroy);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Script Serialisation Functions */ /* Script Serialisation Functions */

View File

@ -0,0 +1,11 @@
#define SET_STATIC_GLOBALS 0
#define SET_DYNAMIC_GLOBALS 1
#define SET_HIGH_FREQUENCY_GLOBALS 2
#define BINDING_GENERIC_DATA 0
#define BINDING_IMAGE_AND_SAMPLERS_DATA 1
#define BINDING_LIGHTS_DATA 0
#define BINDING_CAMERA_DATA 0
#define BINDING_BATCHED_PER_INST_DATA 0

View File

@ -1,6 +1,8 @@
#version 450 #version 450
#extension GL_KHR_vulkan_glsl : enable #extension GL_KHR_vulkan_glsl : enable
//#include "ShaderDescriptorDefinitions.glsl"
layout(location = 0) in vec3 aVertexPos; layout(location = 0) in vec3 aVertexPos;
layout(location = 1) in vec2 aUV; layout(location = 1) in vec2 aUV;
layout(location = 2) in vec3 aNormal; layout(location = 2) in vec3 aNormal;
@ -28,6 +30,12 @@ layout(location = 0) out struct
} Out; } Out;
layout(set = 2, binding = 0) uniform CameraData
{
vec4 position;
mat4 vpMat;
} cameraData;
void main() void main()
{ {
//const float gamma = testPushConstant.eyePosition.w; //const float gamma = testPushConstant.eyePosition.w;
@ -48,6 +56,7 @@ void main()
//Out.uv = aUV; //Out.uv = aUV;
// render NDC first // render NDC first
gl_Position = vec4(aVertexPos, 1.0); //gl_Position = vec4(aVertexPos, 1.0f);
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
Out.vertColor = vec4 (aVertexPos, 1.0f); Out.vertColor = vec4 (aVertexPos, 1.0f);
} }

Binary file not shown.