Merge branch 'main' into SP3-4-editor_fix

This commit is contained in:
Sri Sham Haran 2022-09-26 14:04:02 +08:00
commit 247930ea68
21 changed files with 426 additions and 164 deletions

View File

@ -36,7 +36,7 @@ namespace Sandbox
graphicsSystem->BuildMeshBuffers(); graphicsSystem->BuildMeshBuffers();
// Create Materials // Create Materials
auto matInst = graphicsSystem->AddMaterialInstance(); auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance();
// Create Stress Test Objects // Create Stress Test Objects
static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f }; static const SHVec3 TEST_OBJ_SCALE = { 0.2f, 0.2f, 0.2f };

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="SHADE::Handle&lt;*&gt;">
<DisplayString Condition="library==nullptr">NULL</DisplayString>
<DisplayString>ID = {id.Data.Index} Version = {id.Data.Version} Type = {"$T1"} </DisplayString>
<Expand>
<ExpandedItem>(*library).objects.denseArray[(*library).objects.sparseArray[id.Data.Index]]</ExpandedItem>
</Expand>
</Type>
</AutoVisualizer>

View File

@ -15,7 +15,8 @@ project "SHADE_Engine"
"%{prj.location}/src/**.hpp", "%{prj.location}/src/**.hpp",
"%{prj.location}/src/**.c", "%{prj.location}/src/**.c",
"%{prj.location}/src/**.cpp", "%{prj.location}/src/**.cpp",
"%{prj.location}/src/**.glsl" "%{prj.location}/src/**.glsl",
"%{prj.location}/**.natvis"
} }
includedirs includedirs

View File

@ -192,7 +192,7 @@ namespace SHADE
} }
// Begin the render pass // Begin the render pass
vkCommandBuffer.beginRenderPass (&renderPassInfo, vk::SubpassContents::eInline); vkCommandBuffer.beginRenderPass(&renderPassInfo, vk::SubpassContents::eInline);
} }
@ -321,14 +321,14 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::BindVertexBuffer (uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept void SHVkCommandBuffer::BindVertexBuffer(uint32_t bindingPoint, Handle<SHVkBuffer> const& buffer, vk::DeviceSize offset) noexcept
{ {
if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING) if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING)
{ {
if (buffer) if (buffer)
{ {
auto bufferHandle = buffer->GetVkBuffer(); auto bufferHandle = buffer->GetVkBuffer();
vkCommandBuffer.bindVertexBuffers (bindingPoint, 1, &bufferHandle, &offset); vkCommandBuffer.bindVertexBuffers(bindingPoint, 1, &bufferHandle, &offset);
} }
} }
} }
@ -354,13 +354,13 @@ namespace SHADE
if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING) if (cmdBufferState == SH_CMD_BUFFER_STATE::RECORDING)
{ {
auto bufferHandle = buffer->GetVkBuffer(); auto bufferHandle = buffer->GetVkBuffer();
vkCommandBuffer.bindIndexBuffer (bufferHandle, sizeof (uint32_t) * startingIndex, vk::IndexType::eUint32); vkCommandBuffer.bindIndexBuffer(bufferHandle, sizeof(uint32_t) * startingIndex, vk::IndexType::eUint32);
} }
} }
void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets) void SHVkCommandBuffer::BindDescriptorSet(Handle<SHVkDescriptorSetGroup> descSetGroup, vk::PipelineBindPoint bindPoint, uint32_t firstSet, std::span<uint32_t> dynamicOffsets)
{ {
vkCommandBuffer.bindDescriptorSets (bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets); vkCommandBuffer.bindDescriptorSets(bindPoint, boundPipelineLayoutHdl->GetVkPipelineLayout(), firstSet, descSetGroup->GetVkHandle(), dynamicOffsets);
} }
/***************************************************************************/ /***************************************************************************/
@ -390,7 +390,7 @@ namespace SHADE
SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. "); SHLOG_ERROR("Command buffer must have started recording before a pipeline can be bound. ");
return; return;
} }
vkCommandBuffer.draw (vertexCount, instanceCount, firstVertex, firstInstance); vkCommandBuffer.draw(vertexCount, instanceCount, firstVertex, firstInstance);
} }
/***************************************************************************/ /***************************************************************************/
@ -413,7 +413,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHVkCommandBuffer::DrawIndexed (uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept void SHVkCommandBuffer::DrawIndexed(uint32_t indexCount, uint32_t firstIndex, uint32_t vertexOffset) const noexcept
{ {
if (cmdBufferState != SH_CMD_BUFFER_STATE::RECORDING) if (cmdBufferState != SH_CMD_BUFFER_STATE::RECORDING)
{ {
@ -454,30 +454,30 @@ namespace SHADE
void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo) void SHVkCommandBuffer::CopyBufferToImage(const vk::Buffer& src, const vk::Image& dst, const std::vector<vk::BufferImageCopy>& copyInfo)
{ {
vkCommandBuffer.copyBufferToImage vkCommandBuffer.copyBufferToImage
( (
src, dst, vk::ImageLayout::eTransferDstOptimal, src, dst, vk::ImageLayout::eTransferDstOptimal,
static_cast<uint32_t>(copyInfo.size()), copyInfo.data() static_cast<uint32_t>(copyInfo.size()), copyInfo.data()
); );
} }
void SHVkCommandBuffer::PipelineBarrier( void SHVkCommandBuffer::PipelineBarrier(
vk::PipelineStageFlags srcStage, vk::PipelineStageFlags srcStage,
vk::PipelineStageFlags dstStage, vk::PipelineStageFlags dstStage,
vk::DependencyFlags deps, vk::DependencyFlags deps,
std::vector<vk::MemoryBarrier> const& memoryBarriers, std::vector<vk::MemoryBarrier> const& memoryBarriers,
std::vector<vk::BufferMemoryBarrier> const& bufferMemoryBarriers, std::vector<vk::BufferMemoryBarrier> const& bufferMemoryBarriers,
std::vector<vk::ImageMemoryBarrier> const& imageMemoryBarriers std::vector<vk::ImageMemoryBarrier> const& imageMemoryBarriers
) const noexcept ) const noexcept
{ {
vkCommandBuffer.pipelineBarrier ( vkCommandBuffer.pipelineBarrier(
srcStage, srcStage,
dstStage, dstStage,
deps, deps,
memoryBarriers, memoryBarriers,
bufferMemoryBarriers, bufferMemoryBarriers,
imageMemoryBarriers imageMemoryBarriers
); );
} }
bool SHVkCommandBuffer::IsReadyToSubmit(void) const noexcept bool SHVkCommandBuffer::IsReadyToSubmit(void) const noexcept
@ -620,7 +620,7 @@ namespace SHADE
, parentPoolResetMode{ SH_CMD_POOL_RESET::POOL_BASED } , parentPoolResetMode{ SH_CMD_POOL_RESET::POOL_BASED }
, usageFlags{} , usageFlags{}
, commandBufferCount{ 0 } , commandBufferCount{ 0 }
, parentPool{commandPool} , parentPool{ commandPool }
, pushConstantData{} , pushConstantData{}
{ {
@ -661,14 +661,14 @@ namespace SHADE
commandBufferType = type; commandBufferType = type;
commandBufferCount = allocateInfo.commandBufferCount; commandBufferCount = allocateInfo.commandBufferCount;
if (parentPool->GetIsTransient ()) if (parentPool->GetIsTransient())
usageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit; usageFlags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
if (commandBufferType == SH_CMD_BUFFER_TYPE::SECONDARY) if (commandBufferType == SH_CMD_BUFFER_TYPE::SECONDARY)
usageFlags |= vk::CommandBufferUsageFlagBits::eRenderPassContinue; usageFlags |= vk::CommandBufferUsageFlagBits::eRenderPassContinue;
// Reset all the push constant data to 0 // Reset all the push constant data to 0
memset (pushConstantData, 0, PUSH_CONSTANT_SIZE); memset(pushConstantData, 0, PUSH_CONSTANT_SIZE);
} }
/***************************************************************************/ /***************************************************************************/
@ -683,16 +683,16 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
SHVkCommandBuffer::SHVkCommandBuffer(SHVkCommandBuffer&& rhs) noexcept SHVkCommandBuffer::SHVkCommandBuffer(SHVkCommandBuffer&& rhs) noexcept
: vkCommandBuffer {std::move (rhs.vkCommandBuffer)} : vkCommandBuffer{ std::move(rhs.vkCommandBuffer) }
, cmdBufferState {rhs.cmdBufferState} , cmdBufferState{ rhs.cmdBufferState }
, commandBufferType {rhs.commandBufferType} , commandBufferType{ rhs.commandBufferType }
, parentPoolResetMode {rhs.parentPoolResetMode} , parentPoolResetMode{ rhs.parentPoolResetMode }
, usageFlags {rhs.usageFlags} , usageFlags{ rhs.usageFlags }
, commandBufferCount {rhs.commandBufferCount} , commandBufferCount{ rhs.commandBufferCount }
, parentPool {rhs.parentPool} , parentPool{ rhs.parentPool }
, boundPipelineLayoutHdl{rhs.boundPipelineLayoutHdl } , boundPipelineLayoutHdl{ rhs.boundPipelineLayoutHdl }
{ {
memcpy (pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE); memcpy(pushConstantData, rhs.pushConstantData, PUSH_CONSTANT_SIZE);
rhs.vkCommandBuffer = VK_NULL_HANDLE; rhs.vkCommandBuffer = VK_NULL_HANDLE;
} }

View File

@ -39,7 +39,8 @@ namespace SHADE
std::vector<vk::DescriptorPoolSize> Limits = std::vector<vk::DescriptorPoolSize> Limits =
{ {
{ vk::DescriptorType::eCombinedImageSampler, 100 }, { vk::DescriptorType::eCombinedImageSampler, 100 },
{ vk::DescriptorType::eUniformBuffer, 100 } { vk::DescriptorType::eUniformBuffer, 100 },
{ vk::DescriptorType::eUniformBufferDynamic, 100 }
}; };
/// <summary> /// <summary>
/// Maximum number of descriptor sets allowed /// Maximum number of descriptor sets allowed

View File

@ -58,6 +58,9 @@ namespace SHADE
// Add renderable in // Add renderable in
subBatch->Renderables.insert(renderable); subBatch->Renderables.insert(renderable);
// Also add material instance in
referencedMatInstances.insert(renderable->GetMaterial());
// Mark all as dirty // Mark all as dirty
setAllDirtyFlags(); setAllDirtyFlags();
} }
@ -67,8 +70,8 @@ namespace SHADE
// Check if we have a SubBatch with the same mesh yet // Check if we have a SubBatch with the same mesh yet
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch) auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
{ {
return batch.Mesh == renderable->Mesh; return batch.Mesh == renderable->Mesh;
}); });
// Attempt to remove if it exists // Attempt to remove if it exists
if (subBatch == subBatches.end()) if (subBatch == subBatches.end())
@ -76,6 +79,22 @@ namespace SHADE
subBatch->Renderables.erase(renderable); subBatch->Renderables.erase(renderable);
// Check if other renderables in subBatches contain the same material instance
bool matUnused = true;
for (const auto& sb : subBatches)
for (const auto& rend : sb.Renderables)
{
if (rend->GetMaterial() == renderable->GetMaterial())
{
matUnused = false;
break;
}
}
// Material is no longer in this library, so we remove it
if (matUnused)
referencedMatInstances.erase(renderable->GetMaterial());
// Mark all as dirty // Mark all as dirty
for (bool& dirt : isDirty) for (bool& dirt : isDirty)
dirt = true; dirt = true;
@ -101,7 +120,61 @@ namespace SHADE
} }
} }
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex) void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex)
{
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
return;
}
// Check if there are even material properties to update
if (!matPropsData)
return;
// Check if any materials have changed
bool hasChanged = false;
for (const auto& material : referencedMatInstances)
{
if (material->HasChanged())
{
hasChanged = true;
break;
}
}
// We need to update all the material buffers if the materials have changed
if (hasChanged)
{
for (auto& dirt : matBufferDirty)
dirt = true;
}
// Check if this frame's buffer is dirty
if (!matBufferDirty[frameIndex])
return;
// Build CPI Buffer
char* propsCurrPtr = matPropsData.get();
for (auto& subBatch : subBatches)
for (const SHRenderable* renderable : subBatch.Renderables)
{
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
propsCurrPtr += singleMatPropSize;
}
// Transfer to GPU
SHVkUtil::EnsureBufferAndCopyHostVisibleData
(
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
vk::BufferUsageFlagBits::eStorageBuffer
);
// This frame is updated
matBufferDirty[frameIndex] = false;
}
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
{ {
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{ {
@ -131,10 +204,10 @@ namespace SHADE
// Transfer to GPU // Transfer to GPU
if (transformDataBuffer[frameIndex]) if (transformDataBuffer[frameIndex])
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), transformData.size() * sizeof(SHMatrix), 0, 0); transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
} }
void SHBatch::Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) void SHBatch::Build(Handle<SHVkLogicalDevice> _device, uint32_t frameIndex)
{ {
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS) if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
{ {
@ -170,7 +243,6 @@ namespace SHADE
vk::ShaderStageFlagBits::eFragment vk::ShaderStageFlagBits::eFragment
); );
const bool EMPTY_MAT_PROPS = !SHADER_INFO; const bool EMPTY_MAT_PROPS = !SHADER_INFO;
Byte singleMatPropSize = 0;
Byte matPropTotalBytes = 0; Byte matPropTotalBytes = 0;
if (!EMPTY_MAT_PROPS) if (!EMPTY_MAT_PROPS)
{ {
@ -232,14 +304,14 @@ namespace SHADE
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[frameIndex], drawData.data(), DRAW_DATA_BYTES, _device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
BuffUsage::eIndirectBuffer BuffUsage::eIndirectBuffer
); );
// - Transform Buffer // - Transform Buffer
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[frameIndex], transformData.data(), TF_DATA_BYTES, _device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
BuffUsage::eVertexBuffer BuffUsage::eVertexBuffer
); );
// - Material Properties Buffer // - Material Properties Buffer
@ -247,12 +319,15 @@ namespace SHADE
{ {
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize), _device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
BuffUsage::eStorageBuffer BuffUsage::eStorageBuffer
); );
} }
isDirty[frameIndex] = false; isDirty[frameIndex] = false;
// Save logical device
this->device = _device;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -34,6 +34,7 @@ namespace SHADE
class SHMesh; class SHMesh;
class SHRenderable; class SHRenderable;
class SHVkLogicalDevice; class SHVkLogicalDevice;
class SHMaterialInstance;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -73,6 +74,7 @@ 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 UpdateMaterialBuffer(uint32_t frameIndex);
void UpdateTransformBuffer(uint32_t frameIndex); void UpdateTransformBuffer(uint32_t frameIndex);
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex); void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex); void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
@ -86,8 +88,12 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
// Resources
Handle<SHVkLogicalDevice> device;
// Batch Properties // Batch Properties
Handle<SHVkPipeline> pipeline; Handle<SHVkPipeline> pipeline;
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> matBufferDirty;
// Batch Tree // Batch Tree
std::vector<SHSubBatch> subBatches; std::vector<SHSubBatch> subBatches;
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> isDirty; std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> isDirty;
@ -96,6 +102,7 @@ namespace SHADE
std::vector<SHMatrix> transformData; std::vector<SHMatrix> transformData;
std::unique_ptr<char> matPropsData; std::unique_ptr<char> matPropsData;
Byte matPropsDataSize = 0; Byte matPropsDataSize = 0;
Byte singleMatPropSize = 0;
bool isCPUBuffersDirty = true; bool isCPUBuffersDirty = true;
// GPU Buffers // GPU Buffers
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer; std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer;

View File

@ -109,11 +109,11 @@ namespace SHADE
superBatches.clear(); superBatches.clear();
} }
void SHBatcher::UpdateTransformBuffer(uint32_t frameIndex) void SHBatcher::UpdateBuffers(uint32_t frameIndex)
{ {
for (auto& batch : superBatches) for (auto& batch : superBatches)
{ {
batch->UpdateTransformBuffer(frameIndex); batch->UpdateBuffers(frameIndex);
} }
} }

View File

@ -53,7 +53,7 @@ namespace SHADE
void RemoveFromBatch(SHRenderable const* renderable); void RemoveFromBatch(SHRenderable const* renderable);
void FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex); void FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
void ClearBatches(); void ClearBatches();
void UpdateTransformBuffer(uint32_t frameIndex); void UpdateBuffers(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,10 +78,11 @@ namespace SHADE
batches.clear(); batches.clear();
} }
void SHSuperBatch::UpdateTransformBuffer(uint32_t frameIndex) void SHSuperBatch::UpdateBuffers(uint32_t frameIndex)
{ {
for (auto& batch : batches) for (auto& batch : batches)
{ {
batch.UpdateMaterialBuffer(frameIndex);
batch.UpdateTransformBuffer(frameIndex); batch.UpdateTransformBuffer(frameIndex);
} }
} }

View File

@ -54,8 +54,8 @@ 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 UpdateTransformBuffer(uint32_t frameIndex); void UpdateBuffers(uint32_t frameIndex);
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept; void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept;
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept; void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;

View File

@ -151,11 +151,10 @@ namespace SHADE
//compositeSubpass->AddInput("Normals"); //compositeSubpass->AddInput("Normals");
//compositeSubpass->AddInput("Position"); //compositeSubpass->AddInput("Position");
//#ifdef SHEDITOR // TODO: Use macro to add this node when SH_EDITOR is enabled
auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {}); auto imguiNode = worldRenderGraph->AddNode("ImGui Node", { "Present" }, {"G-Buffer"});
auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw"); auto imguiSubpass = imguiNode->AddSubpass("ImGui Draw");
imguiSubpass->AddColorOutput("Present"); imguiSubpass->AddColorOutput("Present");
//#endif
worldRenderGraph->Generate(); worldRenderGraph->Generate();
@ -418,14 +417,19 @@ namespace SHADE
resourceManager.Free(material); resourceManager.Free(material);
} }
Handle<SHMaterialInstance> SHGraphicsSystem::AddMaterialInstance(Handle<SHMaterial> material) Handle<SHMaterialInstance> SHGraphicsSystem::AddOrGetBaseMaterialInstance(Handle<SHMaterial> material)
{ {
return resourceManager.Create<SHMaterialInstance>(material); return materialInstanceCache.CreateOrGet(resourceManager, material);
} }
SHADE::Handle<SHADE::SHMaterialInstance> SHGraphicsSystem::AddMaterialInstance() SHADE::Handle<SHADE::SHMaterialInstance> SHGraphicsSystem::AddOrGetBaseMaterialInstance()
{ {
return AddMaterialInstance(defaultMaterial); return AddOrGetBaseMaterialInstance(defaultMaterial);
}
SHADE::Handle<SHADE::SHMaterialInstance> SHGraphicsSystem::AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst)
{
return resourceManager.Create<SHMaterialInstance>(materialInst->GetBaseMaterial());
} }
void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance) void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance)

View File

@ -28,6 +28,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Shaders/SHShaderSourceLibrary.h" #include "Graphics/MiddleEnd/Shaders/SHShaderSourceLibrary.h"
#include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h" #include "Graphics/MiddleEnd/Shaders/SHShaderModuleLibrary.h"
#include "SHMeshLibrary.h" #include "SHMeshLibrary.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialInstanceCache.h"
namespace SHADE namespace SHADE
{ {
@ -119,9 +120,10 @@ namespace SHADE
/* Material Creation Functions */ /* Material Creation Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHMaterial> AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass); Handle<SHMaterial> AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass);
void RemoveMaterial(Handle<SHMaterial> material);; void RemoveMaterial(Handle<SHMaterial> material);
Handle<SHMaterialInstance> AddMaterialInstance(); Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance();
Handle<SHMaterialInstance> AddMaterialInstance(Handle<SHMaterial> material); Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance(Handle<SHMaterial> material);
Handle<SHMaterialInstance> AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst);
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance); void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -229,8 +231,9 @@ namespace SHADE
Handle<SHGraphicsGlobalData> globalData; Handle<SHGraphicsGlobalData> globalData;
// Middle End Resources // Middle End Resources
ResourceManager resourceManager; ResourceManager resourceManager;
SHMeshLibrary meshLibrary; SHMeshLibrary meshLibrary;
SHMaterialInstanceCache materialInstanceCache;
// Viewports // Viewports
Handle<SHViewport> defaultViewport; // Whole screen Handle<SHViewport> defaultViewport; // Whole screen
std::vector<Handle<SHViewport>> viewports; // Additional viewports std::vector<Handle<SHViewport>> viewports; // Additional viewports

View File

@ -38,7 +38,7 @@ namespace SHADE
dataStore.reset(); dataStore.reset();
} }
void SHMaterialInstance::ExportProperties(void* dest) const void SHMaterialInstance::ExportProperties(void* dest)
{ {
assert(dataStore != nullptr); assert(dataStore != nullptr);
@ -62,6 +62,9 @@ namespace SHADE
const auto DATA_OFFSET = variable->offset; const auto DATA_OFFSET = variable->offset;
memcpy(static_cast<char*>(dest) + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize); memcpy(static_cast<char*>(dest) + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize);
} }
// Data was exported so unflag
dataWasChanged = false;
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -62,12 +62,13 @@ namespace SHADE
template<typename T> template<typename T>
const T& GetProperty(const std::string& key) const; const T& GetProperty(const std::string& key) const;
void ResetProperties() noexcept; void ResetProperties() noexcept;
void ExportProperties(void* dest) const; void ExportProperties(void* dest);
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHMaterial> GetBaseMaterial() const { return baseMaterial; } Handle<SHMaterial> GetBaseMaterial() const noexcept { return baseMaterial; }
bool HasChanged() const noexcept { return dataWasChanged; }
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -77,6 +78,7 @@ namespace SHADE
std::vector<OverrideData> overrideData; std::vector<OverrideData> overrideData;
std::unique_ptr<char> dataStore; std::unique_ptr<char> dataStore;
size_t dataStoreSize = 0; size_t dataStoreSize = 0;
bool dataWasChanged = false;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */

View File

@ -53,6 +53,9 @@ namespace SHADE
// Save the override data information // Save the override data information
overrideData.emplace_back(std::move(od)); overrideData.emplace_back(std::move(od));
// Flag
dataWasChanged = true;
} }
template<typename T> template<typename T>
T& SHMaterialInstance::GetProperty(const std::string& key) T& SHMaterialInstance::GetProperty(const std::string& key)

View File

@ -81,7 +81,7 @@ namespace SHADE
if (!material) if (!material)
{ {
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>(); SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
material = gfxSystem->AddMaterialInstance(sharedMaterial->GetBaseMaterial()); material = gfxSystem->AddOrGetBaseMaterialInstance(sharedMaterial->GetBaseMaterial());
} }
return material; return material;

View File

@ -0,0 +1,47 @@
/************************************************************************************//*!
\file SHMaterialInstanceCache.cpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 25, 2022
\brief Contains the definition of SHMaterialInstanceCache's functions.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#include "SHpch.h"
#include "SHMaterialInstanceCache.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Resource/ResourceLibrary.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
SHADE::Handle<SHADE::SHMaterialInstance> SHMaterialInstanceCache::CreateOrGet(ResourceManager& manager, Handle<SHMaterial> material)
{
// Check if there is already an existing instance
auto matInst = cache.find(material);
if (matInst == cache.end())
{
// Create and return
return cache.emplace(material, manager.Create<SHMaterialInstance>(material)).first->second;
}
return matInst->second;
}
void SHMaterialInstanceCache::Remove(Handle<SHMaterial> material)
{
cache.erase(material);
}
void SHMaterialInstanceCache::Clear()
{
cache.clear();
}
}

View File

@ -0,0 +1,93 @@
/************************************************************************************//*!
\file SHMaterialInstanceCache.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 25, 2022
\brief Contains the definition of SHMaterialInstanceCache.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
#pragma once
// STL Includes
#include <unordered_map>
// Project Includes
#include "Resource/Handle.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHMaterial;
class SHMaterialInstance;
class ResourceManager;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*************************************************************************************/
/*!
\brief
Creates and caches base SHMaterialInstances. Note that base SHMaterialInstances
refer to SHMaterialInstances with no overrides.
*/
/*************************************************************************************/
class SHMaterialInstanceCache
{
public:
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
/***********************************************************************************/
/*!
\brief
\param material
Material to get the SHMaterialInstance for.
\return
Handle to the base SHMaterialInstance that is mapped to SHMaterial.
*/
/***********************************************************************************/
Handle<SHMaterialInstance> CreateOrGet(ResourceManager& manager, Handle<SHMaterial> material);
/***********************************************************************************/
/*!
\brief
Removes a SHMaterialInstance from the cache with a matching material.
\param material
Handle to a SHMaterial that is used to check for removal.
*/
/***********************************************************************************/
void Remove(Handle<SHMaterial> material);
/***********************************************************************************/
/*!
\brief
Removes all SHMaterialInstances in the cache.
*/
/***********************************************************************************/
void Clear();
private:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using MaterialMap = std::unordered_map<Handle<SHMaterial>, Handle<SHMaterialInstance>>;
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
MaterialMap cache;
};
}

View File

@ -220,7 +220,6 @@ namespace SHADE
, depthReferences{} , depthReferences{}
, inputReferences{} , inputReferences{}
{ {
superBatch = rm.Create<SHSuperBatch>(GetHandle());
} }
/***************************************************************************/ /***************************************************************************/
@ -349,7 +348,7 @@ namespace SHADE
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept
{ {
// Ensure correct transforms are provided // Ensure correct transforms are provided
superBatch->UpdateTransformBuffer(frameIndex); superBatch->UpdateBuffers(frameIndex);
// Draw all the batches // Draw all the batches
superBatch->Draw(commandBuffer, frameIndex); superBatch->Draw(commandBuffer, frameIndex);
@ -366,6 +365,12 @@ namespace SHADE
exteriorDrawCalls.push_back(newDrawCall); exteriorDrawCalls.push_back(newDrawCall);
} }
void SHSubpass::Init(ResourceManager& resourceManager) noexcept
{
superBatch = resourceManager.Create<SHSuperBatch>(GetHandle());
}
/***************************************************************************/ /***************************************************************************/
/*! /*!
@ -524,7 +529,9 @@ namespace SHADE
, configured{ rhs.configured } , configured{ rhs.configured }
, executed{ rhs.executed } , executed{ rhs.executed }
, ptrToResources{ rhs.ptrToResources } , ptrToResources{ rhs.ptrToResources }
, pipelineLibrary{ std::move (rhs.pipelineLibrary) } , pipelineLibrary{ std::move(rhs.pipelineLibrary) }
, batcher { std::move(rhs.batcher) }
{ {
rhs.renderpass = {}; rhs.renderpass = {};
} }
@ -545,7 +552,8 @@ namespace SHADE
resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping); resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
subpassIndexing = std::move(rhs.subpassIndexing); subpassIndexing = std::move(rhs.subpassIndexing);
ptrToResources = std::move(rhs.ptrToResources); ptrToResources = std::move(rhs.ptrToResources);
pipelineLibrary = std::move (rhs.pipelineLibrary); pipelineLibrary = std::move(rhs.pipelineLibrary);
batcher = std::move(rhs.batcher);
rhs.renderpass = {}; rhs.renderpass = {};
@ -579,6 +587,7 @@ namespace SHADE
subpasses.emplace_back(resourceManager.Create<SHSubpass>(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources)); subpasses.emplace_back(resourceManager.Create<SHSubpass>(resourceManager, GetHandle(), subpasses.size(), &resourceAttachmentMapping, ptrToResources));
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u); subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
Handle<SHSubpass> subpass = subpasses.back(); Handle<SHSubpass> subpass = subpasses.back();
subpass->Init(resourceManager);
// Register the SuperBatch // Register the SuperBatch
batcher.RegisterSuperBatch(subpass->GetSuperBatch()); batcher.RegisterSuperBatch(subpass->GetSuperBatch());
@ -627,7 +636,7 @@ namespace SHADE
} }
void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex) void SHRenderGraphNode::FinaliseBatch(uint32_t frameIndex)
{ {
batcher.FinaliseBatches(logicalDeviceHdl, frameIndex); batcher.FinaliseBatches(logicalDeviceHdl, frameIndex);
} }
@ -707,7 +716,7 @@ namespace SHADE
// First we want to take all the attachment descriptions and initialize the // First we want to take all the attachment descriptions and initialize the
// finalLayout to whatever layout is specified in the last subpass that references the attachment. // finalLayout to whatever layout is specified in the last subpass that references the attachment.
for (auto& node : nodes) for (uint32_t i = 0; auto& node : nodes)
{ {
// key is handle ID, value is pair (first is initial layout, second is final layout). // key is handle ID, value is pair (first is initial layout, second is final layout).
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttLayouts; std::unordered_map<uint32_t, vk::ImageLayout> resourceAttLayouts;
@ -721,7 +730,7 @@ namespace SHADE
{ {
for (auto& color : subpass->colorReferences) for (auto& color : subpass->colorReferences)
{ {
if (node->attResources[color.attachment]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) if (i == nodes.size() - 1 && node->attResources[color.attachment]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT)
resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR; resourceAttLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
else else
resourceAttLayouts[color.attachment] = color.layout; resourceAttLayouts[color.attachment] = color.layout;
@ -740,6 +749,7 @@ namespace SHADE
att.initialLayout = vk::ImageLayout::eUndefined; att.initialLayout = vk::ImageLayout::eUndefined;
att.finalLayout = resourceAttLayouts[i]; att.finalLayout = resourceAttLayouts[i];
} }
++i;
} }
// at this point all attachment descs will have their final layouts initialized as if they were standalone and did // at this point all attachment descs will have their final layouts initialized as if they were standalone and did
@ -848,7 +858,7 @@ namespace SHADE
for (auto& inputAtt : subpass->inputReferences) for (auto& inputAtt : subpass->inputReferences)
{ {
auto resource = node->attResources[inputAtt.attachment]; auto resource = node->attResources[inputAtt.attachment];
if (resource->resourceType == SH_ATT_DESC_TYPE::COLOR) if (resource->resourceType == SH_ATT_DESC_TYPE::COLOR || resource->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT)
colorRead |= (1 << i); colorRead |= (1 << i);
else if (resource->resourceType == SH_ATT_DESC_TYPE::DEPTH_STENCIL) else if (resource->resourceType == SH_ATT_DESC_TYPE::DEPTH_STENCIL)
depthRead |= (1 << i); depthRead |= (1 << i);
@ -997,12 +1007,12 @@ namespace SHADE
SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept SHRenderGraph::SHRenderGraph(SHRenderGraph&& rhs) noexcept
: logicalDeviceHdl{ rhs.logicalDeviceHdl } : logicalDeviceHdl{ rhs.logicalDeviceHdl }
, swapchainHdl{ rhs.swapchainHdl} , swapchainHdl{ rhs.swapchainHdl }
, nodeIndexing {std::move (rhs.nodeIndexing)} , nodeIndexing{ std::move(rhs.nodeIndexing) }
, nodes{ std::move (rhs.nodes)} , nodes{ std::move(rhs.nodes) }
, graphResources{std::move(rhs.graphResources)} , graphResources{ std::move(rhs.graphResources) }
, resourceManager{std::move (rhs.resourceManager)} , resourceManager{ std::move(rhs.resourceManager) }
, globalData {rhs.globalData} , globalData{ rhs.globalData }
{ {
} }
@ -1020,7 +1030,7 @@ namespace SHADE
resourceManager = std::move(rhs.resourceManager); resourceManager = std::move(rhs.resourceManager);
globalData = rhs.globalData; globalData = rhs.globalData;
return *this; return *this;
} }
/***************************************************************************/ /***************************************************************************/
@ -1114,7 +1124,7 @@ namespace SHADE
} }
void SHRenderGraph::FinaliseBatch(uint32_t frameIndex) void SHRenderGraph::FinaliseBatch(uint32_t frameIndex)
{ {
for (auto& node : nodes) for (auto& node : nodes)
{ {
node->FinaliseBatch(frameIndex); node->FinaliseBatch(frameIndex);

View File

@ -140,6 +140,8 @@ namespace SHADE
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) 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;
void Init (ResourceManager& resourceManager) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */ /* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/