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

Window resize, minimize and close fix. Destruction mem leaks for vulkan are gone
This commit is contained in:
XiaoQiDigipen 2022-10-02 03:12:35 +08:00 committed by GitHub
commit 530db8b7d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 610 additions and 170 deletions

View File

@ -145,6 +145,9 @@ namespace Sandbox
SHADE::SHSystemManager::RunRoutines(false, 0.016f);
}
// Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution();
}

View File

@ -163,8 +163,8 @@ project "SHADE_Engine"
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
excludes
{
"%{prj.location}/src/Editor/**.cpp",
"%{prj.location}/src/Editor/**.h",
"%{prj.location}/src/Editor/**.hpp",
-- "%{prj.location}/src/Editor/**.cpp",
-- "%{prj.location}/src/Editor/**.h",
-- "%{prj.location}/src/Editor/**.hpp",
}
links{"fmodstudio_vc.lib", "fmod_vc.lib"}

View File

@ -24,7 +24,7 @@ namespace SHADE
/***************************************************************************/
SHVkCommandBuffer::~SHVkCommandBuffer(void) noexcept
{
if (vkCommandBuffer)
if (vkCommandBuffer && parentPool)
parentPool->GetLogicalDevice()->GetVkLogicalDevice().freeCommandBuffers(parentPool->GetVkCommandPool(), commandBufferCount, &vkCommandBuffer);
}

View File

@ -102,8 +102,6 @@ namespace SHADE
logicalDeviceHdl = rhs.logicalDeviceHdl;
transient = rhs.transient;
static_cast<ISelfHandle<SHVkCommandPool>&>(*this) = static_cast<ISelfHandle<SHVkCommandPool>&>(rhs);
rhs.vkCommandPool = VK_NULL_HANDLE;
return *this;

View File

@ -208,7 +208,7 @@ namespace SHADE
BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding);
// to index a set
uint32_t setIndex = setIndexing[bsHash];
uint32_t setIndex = setIndexing[set];
// to index a write for a binding
uint32_t writeInfoIndex = updater.writeHashMap[bsHash];
@ -233,7 +233,7 @@ namespace SHADE
BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding);
// to index a set
uint32_t setIndex = setIndexing[bsHash];
uint32_t setIndex = setIndexing[set];
// to index a write for a binding
uint32_t writeInfoIndex = updater.writeHashMap[bsHash];

View File

@ -92,7 +92,7 @@ namespace SHADE
//uint32_t minBuffer
if (alignmentSize > 0)
{
alignedSize = (alignedSize + alignmentSize - 1) & ~(alignmentSize - 1);
alignedSize = (alignedSize + static_cast<uint32_t>(alignmentSize) - 1) & ~(alignmentSize - 1);
}
return alignedSize;
}
@ -195,6 +195,8 @@ namespace SHADE
vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{};
descIndexingFeature.descriptorBindingVariableDescriptorCount = true;
descIndexingFeature.shaderSampledImageArrayNonUniformIndexing = true;
descIndexingFeature.runtimeDescriptorArray = true;
// Prepare to create the device
vk::DeviceCreateInfo deviceCreateInfo
@ -249,6 +251,22 @@ namespace SHADE
vkLogicalDevice.destroy(nullptr);
}
SHVkLogicalDevice& SHVkLogicalDevice::operator=(SHVkLogicalDevice&& rhs) noexcept
{
if (this == &rhs)
return *this;
vkLogicalDevice = std::move (rhs.vkLogicalDevice);
queueFamilyIndices = std::move (rhs.queueFamilyIndices);
vmaAllocator = rhs.vmaAllocator;
nonDedicatedBestIndex = 0;
parentPhysicalDeviceHdl = rhs.parentPhysicalDeviceHdl;
rhs.vkLogicalDevice = VK_NULL_HANDLE;
return *this;
}
/***************************************************************************/
/*!

View File

@ -115,7 +115,7 @@ namespace SHADE
~SHVkLogicalDevice (void) noexcept;
SHVkLogicalDevice& operator= (SHVkLogicalDevice const& rhs) noexcept = default;
SHVkLogicalDevice& operator= (SHVkLogicalDevice&& rhs) noexcept = default;
SHVkLogicalDevice& operator= (SHVkLogicalDevice&& rhs) noexcept;
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER VARIABLES */

View File

@ -98,6 +98,51 @@ namespace SHADE
return *this;
}
void SHVkFramebuffer::HandleResize(Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept
{
width = inWidth;
height = inHeight;
for (auto& attachment : attachments)
{
// Not sure if its an error to pass in diff dimension images.
if (attachment->GetParentImage()->GetWidth() != (*attachments.begin())->GetParentImage()->GetWidth() || attachment->GetParentImage()->GetHeight() != (*attachments.begin())->GetParentImage()->GetHeight())
{
SHLOG_ERROR("Dimensions of images not same as each other. Cannot create framebuffer.");
return;
}
}
std::vector<vk::ImageView> vkAttachments(attachments.size());
uint32_t i = 0;
for(auto const& attachment : attachments)
{
vkAttachments[i] = attachment->GetImageView();
++i;
}
vk::FramebufferCreateInfo createInfo
{
.renderPass = renderpassHdl->GetVkRenderpass(),
.attachmentCount = static_cast<uint32_t>(vkAttachments.size()),
.pAttachments = vkAttachments.data(),
.width = width,
.height = height,
.layers = 1 // TODO: Find out why this is 1
};
if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createFramebuffer(&createInfo, nullptr, &vkFramebuffer); result != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(result, "Failed to create framebuffer. ");
return;
}
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created framebuffer. ");
}
}
/***************************************************************************/
/*!

View File

@ -37,6 +37,8 @@ namespace SHADE
SHVkFramebuffer(SHVkFramebuffer&& rhs) noexcept;
SHVkFramebuffer& operator=(SHVkFramebuffer&& rhs) noexcept;
void HandleResize (Handle<SHVkRenderpass> const& renderpassHdl, std::vector<Handle<SHVkImageView>> const& attachments, uint32_t inWidth, uint32_t inHeight) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/

View File

@ -79,6 +79,41 @@ namespace SHADE
vmaUnmapMemory(*vmaAllocator, stagingAlloc);
}
void SHVkImage::CreateFramebufferImage(void) noexcept
{
vk::ImageCreateInfo imageCreateInfo{};
imageCreateInfo.imageType = vk::ImageType::e2D;
imageCreateInfo.extent.width = width;
imageCreateInfo.extent.height = height;
imageCreateInfo.extent.depth = depth;
imageCreateInfo.mipLevels = mipLevelCount;
imageCreateInfo.arrayLayers = layerCount;
imageCreateInfo.format = imageFormat;
imageCreateInfo.tiling = vk::ImageTiling::eOptimal;
imageCreateInfo.initialLayout = vk::ImageLayout::eUndefined;
imageCreateInfo.usage = usageFlags;
imageCreateInfo.sharingMode = vk::SharingMode::eExclusive;
imageCreateInfo.samples = vk::SampleCountFlagBits::e1;
imageCreateInfo.flags = createFlags;
// Prepare allocation parameters for call to create images later
VmaAllocationCreateInfo allocCreateInfo{};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocCreateInfo.flags = {}; // TODO: Make sure the vk::MemoryPropertyFlags returned from vmaGetAllocationMemoryProperties has the device local bit set
VmaAllocationInfo allocInfo{};
VkImage tempImage;
auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo);
vkImage = tempImage;
if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. ");
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image. ");
}
SHVkImage::SHVkImage(
VmaAllocator const* allocator,
SHImageCreateParams const& imageDetails,
@ -196,37 +231,7 @@ namespace SHADE
, createFlags {create}
, vmaAllocator {allocator}
{
vk::ImageCreateInfo imageCreateInfo{};
imageCreateInfo.imageType = vk::ImageType::e2D;
imageCreateInfo.extent.width = width;
imageCreateInfo.extent.height = height;
imageCreateInfo.extent.depth = depth;
imageCreateInfo.mipLevels = mipLevelCount;
imageCreateInfo.arrayLayers = layerCount;
imageCreateInfo.format = imageFormat;
imageCreateInfo.tiling = vk::ImageTiling::eOptimal;
imageCreateInfo.initialLayout = vk::ImageLayout::eUndefined;
imageCreateInfo.usage = usageFlags;
imageCreateInfo.sharingMode = vk::SharingMode::eExclusive;
imageCreateInfo.samples = vk::SampleCountFlagBits::e1;
imageCreateInfo.flags = createFlags;
// Prepare allocation parameters for call to create images later
VmaAllocationCreateInfo allocCreateInfo{};
allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
allocCreateInfo.flags = {}; // TODO: Make sure the vk::MemoryPropertyFlags returned from vmaGetAllocationMemoryProperties has the device local bit set
VmaAllocationInfo allocInfo{};
VkImage tempImage;
auto result = vmaCreateImage(*vmaAllocator, &imageCreateInfo.operator VkImageCreateInfo & (), &allocCreateInfo, &tempImage, &alloc, &allocInfo);
vkImage = tempImage;
if (result != VK_SUCCESS)
SHVulkanDebugUtil::ReportVkError(vk::Result(result), "Failed to create vulkan image. ");
else
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image. ");
CreateFramebufferImage();
}
Handle<SHVkImageView> SHVkImage::CreateImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept
@ -288,6 +293,16 @@ namespace SHADE
barrier.subresourceRange.layerCount = layerCount;
}
void SHVkImage::HandleResizeFramebufferImage(uint32_t newWidth, uint32_t newHeight) noexcept
{
vmaDestroyImage(*vmaAllocator, vkImage, alloc);
width = newWidth;
height = newHeight;
CreateFramebufferImage();
}
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
{
vkImage = inVkImage;

View File

@ -108,7 +108,7 @@ namespace SHADE
/* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept;
void CreateFramebufferImage (void) noexcept;
public:
/*-----------------------------------------------------------------------*/
@ -137,7 +137,8 @@ namespace SHADE
Handle<SHVkImageView> CreateImageView (Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept;
void TransferToDeviceResource (Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept;
void PrepareImageTransitionInfo (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept;
void HandleResizeFramebufferImage(uint32_t newWidth, uint32_t newHeight) noexcept;
/*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/

View File

@ -6,6 +6,67 @@
namespace SHADE
{
void SHVkImageView::Create(void) noexcept
{
auto parentImageCreateFlags = parentImage->GetImageeCreateFlags();
// 2D array image type means parent image must be 2D array compatible
if (imageViewDetails.viewType == vk::ImageViewType::e2DArray)
{
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::e2DArrayCompatible))
{
SHLOG_ERROR("Failed to create image view. Parent image not 2D array compatible. ");
return;
}
}
// Check if its possible for the image view to have different format than parent image
if (imageViewDetails.format != parentImage->GetImageFormat())
{
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::eMutableFormat))
{
SHLOG_ERROR("Failed to create image view. Format for image view not same as image but image not initialized with mutable format bit. ");
return;
}
}
vk::ImageViewCreateInfo viewCreateInfo
{
.pNext = nullptr, // Can be used to override with a VkImageViewUsageCreateInfo to override usage. See Vulkan spec page 877 for more information
.image = parentImage->GetVkImage(),
.viewType = imageViewDetails.viewType,
.format = imageViewDetails.format,
.components
{
.r = vk::ComponentSwizzle::eR,
.g = vk::ComponentSwizzle::eG,
.b = vk::ComponentSwizzle::eB,
.a = vk::ComponentSwizzle::eA,
},
.subresourceRange
{
.aspectMask = imageViewDetails.imageAspectFlags,
.baseMipLevel = imageViewDetails.baseMipLevel,
.levelCount = imageViewDetails.mipLevelCount,
.baseArrayLayer = imageViewDetails.baseArrayLayer,
.layerCount = imageViewDetails.layerCount,
},
};
if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createImageView(&viewCreateInfo, nullptr, &vkImageView); result != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(result, "Failed to create image view! ");
return;
}
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image view. ");
}
}
/***************************************************************************/
/*!
@ -18,70 +79,12 @@ namespace SHADE
*/
/***************************************************************************/
SHVkImageView::SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept
: parentImage{ }
: parentImage{ parent }
, vkImageView{}
, imageViewDetails{}
, imageViewDetails{createParams}
, logicalDeviceHdl {inLogicalDeviceHdl}
{
auto parentImageCreateFlags = parent->GetImageeCreateFlags();
// 2D array image type means parent image must be 2D array compatible
if (createParams.viewType == vk::ImageViewType::e2DArray)
{
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::e2DArrayCompatible))
{
SHLOG_ERROR("Failed to create image view. Parent image not 2D array compatible. ");
return;
}
}
// Check if its possible for the image view to have different format than parent image
if (createParams.format != parent->GetImageFormat())
{
if (!(parentImageCreateFlags & vk::ImageCreateFlagBits::eMutableFormat))
{
SHLOG_ERROR("Failed to create image view. Format for image view not same as image but image not initialized with mutable format bit. ");
return;
}
}
vk::ImageViewCreateInfo viewCreateInfo
{
.pNext = nullptr, // Can be used to override with a VkImageViewUsageCreateInfo to override usage. See Vulkan spec page 877 for more information
.image = parent->GetVkImage(),
.viewType = createParams.viewType,
.format = createParams.format,
.components
{
.r = vk::ComponentSwizzle::eR,
.g = vk::ComponentSwizzle::eG,
.b = vk::ComponentSwizzle::eB,
.a = vk::ComponentSwizzle::eA,
},
.subresourceRange
{
.aspectMask = createParams.imageAspectFlags,
.baseMipLevel = createParams.baseMipLevel,
.levelCount = createParams.mipLevelCount,
.baseArrayLayer = createParams.baseArrayLayer,
.layerCount = createParams.layerCount,
},
};
if (auto result = inLogicalDeviceHdl->GetVkLogicalDevice().createImageView(&viewCreateInfo, nullptr, &vkImageView); result != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(result, "Failed to create image view! ");
return;
}
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created image view. ");
}
// After success, THEN assign variables
parentImage = parent;
imageViewDetails = createParams;
Create();
}
SHVkImageView::SHVkImageView(SHVkImageView&& rhs) noexcept
@ -94,6 +97,17 @@ namespace SHADE
}
void SHVkImageView::ViewNewImage(Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept
{
imageViewDetails = createParams;
parentImage = parent;
if (vkImageView)
logicalDeviceHdl->GetVkLogicalDevice().destroyImageView(vkImageView, nullptr);
Create();
}
Handle<SHVkImage> const& SHVkImageView::GetParentImage(void) const noexcept
{
return parentImage;

View File

@ -25,12 +25,17 @@ namespace SHADE
//! Logical Device needed for creation and destruction
Handle<SHVkLogicalDevice> logicalDeviceHdl;
//! Create new image view
void Create (void) noexcept;
public:
SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept;
~SHVkImageView(void) noexcept;
SHVkImageView(SHVkImageView&& rhs) noexcept;
SHVkImageView& operator=(SHVkImageView&& rhs) noexcept;
void ViewNewImage (Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept;
/*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/

View File

@ -249,7 +249,7 @@ namespace SHADE
if (!EMPTY_MAT_PROPS)
{
singleMatPropSize = SHADER_INFO->GetBytesRequired();
singleMatPropAlignedSize = device->PadSSBOSize(singleMatPropSize);
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
if (matPropsDataSize < matPropTotalBytes)
{
@ -386,7 +386,7 @@ namespace SHADE
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
bufferList,
0, matPropsDataSize
0, static_cast<uint32_t>(matPropsDataSize)
);
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
(

View File

@ -69,7 +69,7 @@ namespace SHADE
SHMatrix inverseViewMatrix;
SHMatrix inverseProjMatrix;
SHMatrix inverseVpMatrix;
bool isDirty;
bool isDirty = true;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */

View File

@ -67,9 +67,17 @@ namespace SHADE
// Register callback to notify render context upon a window resize
window->RegisterWindowSizeCallback([&]([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height)
{
if (width == 0 || height == 0)
return;
renderContext.SetIsResized(true);
});
window->RegisterWindowCloseCallback([&](void)
{
renderContext.SetWindowIsDead(true);
}
);
// Create graphics queue
graphicsQueue = device->GetQueue(SH_Q_FAM::GRAPHICS, 0);
transferQueue = device->GetQueue(SH_Q_FAM::TRANSFER, 0);
@ -116,8 +124,8 @@ namespace SHADE
screenCamera = resourceManager.Create<SHCamera>();
screenCamera->SetLookAt(SHVec3(0.0f, 0.0f, -1.0f), SHVec3(0.0f, 0.0f, 1.0f), SHVec3(0.0f, 1.0f, 0.0f));
screenCamera->SetOrthographic(static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.01f, 100.0f);
worldCamera = resourceManager.Create<SHCamera>();
//worldCamera->SetLookAt(SHVec3(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, 0.0f, 0.0f), SHVec3(0.0f, 0.0f, -2.0f), SHVec3(0.0f, 1.0f, 0.0f));
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
@ -125,7 +133,7 @@ namespace SHADE
defaultViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
// Get render graph from default viewport world renderer
auto worldRenderGraph = resourceManager.Create<SHRenderGraph>();
worldRenderGraph = resourceManager.Create<SHRenderGraph>();
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{swapchain->GetNumImages()};
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
@ -210,6 +218,15 @@ namespace SHADE
/***************************************************************************/
void SHGraphicsSystem::Run(double) noexcept
{
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
// Frame data for the current frame
auto const& frameData = renderContext.GetCurrentFrameData();
uint32_t frameIndex = renderContext.GetCurrentFrame();
@ -249,6 +266,10 @@ namespace SHADE
// Begin recording the command buffer
currentCmdBuffer->BeginRecording();
uint32_t w = static_cast<uint32_t>(viewports[vpIndex]->GetWidth());
uint32_t h = static_cast<uint32_t>(viewports[vpIndex]->GetHeight());
currentCmdBuffer->SetViewportScissor (static_cast<float>(w), static_cast<float>(h), w, h);
currentCmdBuffer->ForceSetPipelineLayout(SHGraphicsGlobalData::GetDummyPipelineLayout());
// Bind all the buffers required for meshes
@ -304,13 +325,6 @@ namespace SHADE
void SHGraphicsSystem::Exit(void)
{
renderContext.Destroy();
graphicsQueue.Free();
swapchain.Free();
surface.Free();
device.Free();
SHVkInstance::Destroy();
}
/*---------------------------------------------------------------------------------*/
@ -328,6 +342,9 @@ namespace SHADE
/***************************************************************************/
void SHGraphicsSystem::BeginRender()
{
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
// Finalise all batches
for (auto vp : viewports)
for (auto renderer : vp->GetRenderers())
@ -341,10 +358,7 @@ namespace SHADE
{
device->WaitIdle();
// Resize the swapchain
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
HandleResize();
}
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
@ -377,6 +391,16 @@ namespace SHADE
/***************************************************************************/
void SHGraphicsSystem::EndRender()
{
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
if (renderContext.GetResized())
{
return;
}
const uint32_t CURR_FRAME_IDX = renderContext.GetCurrentFrame();
auto& currFrameData = renderContext.GetCurrentFrameData();
@ -387,10 +411,8 @@ namespace SHADE
// If swapchain is incompatible/outdated
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR)
{
auto windowDims = window->GetWindowSize();
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
HandleResize();
}
}
@ -509,25 +531,79 @@ namespace SHADE
);
}
void SHGraphicsSystem::HandleResize(void) noexcept
{
if (window->IsMinimized() || renderContext.GetWindowIsDead())
return;
auto windowDims = window->GetWindowSize();
// Resize the swapchain
swapchain->Resize(surface, windowDims.first, windowDims.second);
renderContext.HandleResize();
worldRenderGraph->HandleResize(windowDims.first, windowDims.second);
defaultViewport->SetWidth(static_cast<float>(windowDims.first));
defaultViewport->SetHeight(static_cast<float>(windowDims.second));
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
}
void SHGraphicsSystem::AwaitGraphicsExecution()
{
device->WaitIdle();
}
void SHGraphicsSystem::SetWindow(SHWindow* wind) noexcept
{
window = wind;
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BeginRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BeginRoutine::BeginRoutine()
: SHSystemRoutine("Graphics System Frame Set Up", false)
{}
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - RenderRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::RenderRoutine::RenderRoutine()
: SHSystemRoutine("Graphics System Render", false)
{}
void SHGraphicsSystem::RenderRoutine::Execute(double dt) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->Run(dt);
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - EndRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::EndRoutine::EndRoutine()
: SHSystemRoutine("Graphics System Frame Clean Up", false)
{}
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BatcherDispatcherRoutine */
/*-----------------------------------------------------------------------------------*/
SHGraphicsSystem::BatcherDispatcherRoutine::BatcherDispatcherRoutine()
: SHSystemRoutine("Graphics System Batcher Dispatcher", false)
{}
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
{
auto& renderables = SHComponentManager::GetDense<SHRenderable>();

View File

@ -69,21 +69,25 @@ namespace SHADE
class SH_API BeginRoutine final : public SHSystemRoutine
{
public:
BeginRoutine();
virtual void Execute(double dt) noexcept override final;
};
class SH_API RenderRoutine final : public SHSystemRoutine
{
public:
RenderRoutine();
virtual void Execute(double dt) noexcept override final;
};
class SH_API EndRoutine final : public SHSystemRoutine
{
public:
EndRoutine();
virtual void Execute(double dt) noexcept override final;
};
class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine
{
public:
BatcherDispatcherRoutine();
virtual void Execute(double dt) noexcept override final;
};
@ -246,6 +250,9 @@ namespace SHADE
/***************************************************************************/
void BuildTextures();
void HandleResize(void) noexcept;
void AwaitGraphicsExecution();
/*-----------------------------------------------------------------------------*/
/* Setters */
/*-----------------------------------------------------------------------------*/
@ -279,7 +286,6 @@ namespace SHADE
Handle<SHVkQueue> transferQueue;
Handle<SHVkDescriptorPool> descPool;
Handle<SHVkCommandPool> graphicsCmdPool;
Handle<SHVkCommandPool> transferCmdPool;
Handle<SHVkCommandBuffer> transferCmdBuffer;
Handle<SHVkCommandBuffer> graphicsTexCmdBuffer;
SHRenderContext renderContext;
@ -314,5 +320,7 @@ namespace SHADE
// Temp Materials
Handle<SHMaterial> defaultMaterial;
Handle<SHRenderGraph> worldRenderGraph;
};
}

View File

@ -63,7 +63,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
Handle<SHVkPipeline> pipeline;
std::unique_ptr<char> propMemory;
Byte propMemorySize;
Byte propMemorySize = 0;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */

View File

@ -49,6 +49,14 @@ namespace SHADE
cameraDescriptorSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA);
}
SHRenderer::~SHRenderer(void)
{
//for (auto& cmdBuffer : commandBuffers)
//{
// cmdBuffer.Free();
//}
}
/*-----------------------------------------------------------------------------------*/
/* Camera Registration */
/*-----------------------------------------------------------------------------------*/

View File

@ -65,6 +65,7 @@ namespace SHADE
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHRenderer(Handle<SHVkLogicalDevice> logicalDevice, uint32_t numFrames, std::vector<Handle<SHVkCommandPool>>& cmdPools, Handle<SHVkDescriptorPool> descriptorPool, Handle<SHVkDescriptorSetLayout> cameraDescLayout, Handle<SHViewport> viewport, Handle<SHRenderGraph> renderGraph);
~SHRenderer(void);
/*-----------------------------------------------------------------------------*/
/* Camera Registration */

View File

@ -73,4 +73,16 @@ namespace SHADE
iter->Free();
renderers.erase(iter);
}
void SHViewport::SetWidth(float w) noexcept
{
viewport.width = w;
}
void SHViewport::SetHeight(float h) noexcept
{
viewport.height = h;
}
}

View File

@ -62,6 +62,12 @@ namespace SHADE
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);
/*-----------------------------------------------------------------------------*/
/* Setters */
/*-----------------------------------------------------------------------------*/
void SetWidth(float w) noexcept;
void SetHeight (float h) noexcept;
/*-----------------------------------------------------------------------------*/
/* Getters */
/*-----------------------------------------------------------------------------*/

View File

@ -196,12 +196,12 @@ namespace SHADE
static SHMeshData meshData = Cube();
return meshLibrary.AddMesh
(
meshData.VertexPositions.size(),
static_cast<uint32_t>(meshData.VertexPositions.size()),
meshData.VertexPositions.data(),
meshData.VertexTexCoords.data(),
meshData.VertexTangents.data(),
meshData.VertexNormals.data(),
meshData.Indices.size(),
static_cast<uint32_t>(meshData.Indices.size()),
meshData.Indices.data()
);
}
@ -211,12 +211,12 @@ namespace SHADE
static SHMeshData meshData = Cube();
return gfxSystem.AddMesh
(
meshData.VertexPositions.size(),
static_cast<uint32_t>(meshData.VertexPositions.size()),
meshData.VertexPositions.data(),
meshData.VertexTexCoords.data(),
meshData.VertexTangents.data(),
meshData.VertexNormals.data(),
meshData.Indices.size(),
static_cast<uint32_t>(meshData.Indices.size()),
meshData.Indices.data()
);
}

View File

@ -168,6 +168,11 @@ namespace SHADE
isResized = resized;
}
void SHRenderContext::SetWindowIsDead(bool dead) noexcept
{
windowIsDead = dead;
}
/***************************************************************************/
/*!
@ -197,6 +202,11 @@ namespace SHADE
return currentFrame;
}
bool SHRenderContext::GetResized(void) noexcept
{
return isResized;
}
bool SHRenderContext::GetResizeAndReset(void) noexcept
{
bool b = isResized;
@ -204,4 +214,9 @@ namespace SHADE
return b;
}
bool SHRenderContext::GetWindowIsDead(void) const noexcept
{
return windowIsDead;
}
}

View File

@ -36,6 +36,7 @@ namespace SHADE
uint32_t currentFrame;
bool isResized{ false };
bool windowIsDead {false};
public:
SHRenderContext(void) noexcept;
@ -51,12 +52,15 @@ namespace SHADE
bool WaitForFence (void) noexcept;
void ResetFence (void) noexcept;
void SetIsResized (bool resized) noexcept;
void SetIsResized (bool resized) noexcept;
void SetWindowIsDead (bool dead) noexcept;
SHPerFrameData& GetCurrentFrameData(void) noexcept;
SHPerFrameData& GetFrameData (uint32_t index) noexcept;
uint32_t GetCurrentFrame (void) const noexcept;
bool GetResized (void) noexcept;
bool GetResizeAndReset (void) noexcept;
bool GetWindowIsDead (void) const noexcept;
};
}

View File

@ -149,7 +149,7 @@ namespace SHADE
{
texOrder.emplace_back(job.TextureHandle);
combinedImageSamplers.emplace_back(std::make_tuple(job.TextureHandle->ImageView, job.Sampler, vk::ImageLayout::eShaderReadOnlyOptimal));
job.TextureHandle->TextureArrayIndex = texOrder.size() - 1;
job.TextureHandle->TextureArrayIndex = static_cast<uint32_t>(texOrder.size()) - 1U;
}
addJobs.clear();

View File

@ -46,7 +46,7 @@ namespace SHADE
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
{
w = swapchainHdl->GetSwapchainImage(0)->GetWidth();
w = swapchainHdl->GetSwapchainImage(0)->GetHeight();
h = swapchainHdl->GetSwapchainImage(0)->GetHeight();
format = swapchainHdl->GetSurfaceFormatKHR().format;
}
@ -465,9 +465,6 @@ namespace SHADE
// better way to manage these
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept
{
// TODO: DON'T HARDCODE THIS
cmdBuffer->SetViewportScissor(1920.0f, 1080.0f, 1920, 1080);
for (auto& node : nodes)
node->Execute(cmdBuffer, descPool, frameIndex);
}
@ -480,6 +477,18 @@ namespace SHADE
}
}
void SHRenderGraph::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
{
// resize resources
for (auto& [name, resource]: graphResources)
resource->HandleResize(newWidth, newHeight);
for (auto& node : nodes)
{
node->HandleResize();
}
}
Handle<SHRenderGraphNode> SHRenderGraph::GetNode(std::string const& nodeName) const noexcept
{
if (nodeIndexing.contains(nodeName))

View File

@ -80,6 +80,7 @@ namespace SHADE
void Generate (void) noexcept;
void Execute (uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept;
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */

View File

@ -3,6 +3,7 @@
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "SHRenderGraphResource.h"
#include "SHSubpass.h"
@ -56,6 +57,33 @@ namespace SHADE
}
}
void SHRenderGraphNode::HandleResize(void) noexcept
{
renderpass->HandleResize();
for (uint32_t i = 0; i < framebuffers.size(); ++i)
{
std::vector<Handle<SHVkImageView>> imageViews(attResources.size());
uint32_t fbWidth = std::numeric_limits<uint32_t>::max();
uint32_t fbHeight = std::numeric_limits<uint32_t>::max();
for (uint32_t j = 0; j < attResources.size(); ++j)
{
uint32_t imageViewIndex = (attResources[j]->resourceType == SH_ATT_DESC_TYPE::COLOR_PRESENT) ? i : 0;
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
if (fbWidth > attResources[j]->width)
fbWidth = attResources[j]->width;
if (fbHeight > attResources[j]->height)
fbHeight = attResources[j]->height;
}
framebuffers[i]->HandleResize(renderpass, imageViews, fbWidth, fbHeight);
}
}
/***************************************************************************/
/*!

View File

@ -81,6 +81,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
void CreateRenderpass(void) noexcept;
void CreateFramebuffer(void) noexcept;
void HandleResize (void) noexcept;
public:
/*-----------------------------------------------------------------------*/

View File

@ -2,9 +2,11 @@
#include "SHRenderGraphResource.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Images/SHVkImageView.h"
namespace SHADE
{
/***************************************************************************/
/*!
@ -42,7 +44,9 @@ namespace SHADE
*/
/***************************************************************************/
SHRenderGraphResource::SHRenderGraphResource(Handle<SHVkLogicalDevice> const& logicalDevice, Handle<SHVkSwapchain> const& swapchain, std::string const& name, SH_ATT_DESC_TYPE type, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageCreateFlagBits createFlags) noexcept
: resourceType{ type }
: logicalDevice {logicalDevice}
, swapchain{ swapchain }
, resourceType{ type }
, resourceFormat{ format }
, images{}
, imageViews{}
@ -52,10 +56,10 @@ namespace SHADE
, resourceName{ name }
{
// If the resource type is an arbitrary image and not swapchain image
if (type != SH_ATT_DESC_TYPE::COLOR_PRESENT)
if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT)
{
vk::ImageAspectFlags imageAspectFlags;
vk::ImageUsageFlags usage = {};
imageAspectFlags = vk::ImageAspectFlags{};
usage = {};
// Check the resource type and set image usage flags and image aspect flags accordingly
switch (resourceType)
@ -142,6 +146,7 @@ namespace SHADE
, width{ rhs.width }
, height{ rhs.height }
, mipLevels{ rhs.mipLevels }
, imageAspectFlags{ rhs.imageAspectFlags }
{
}
@ -172,6 +177,7 @@ namespace SHADE
width = rhs.width;
height = rhs.height;
mipLevels = rhs.mipLevels;
imageAspectFlags = rhs.imageAspectFlags;
return *this;
}
@ -189,4 +195,51 @@ namespace SHADE
}
void SHRenderGraphResource::HandleResize(uint32_t newWidth, uint32_t newHeight) noexcept
{
width = newWidth;
height = newHeight;
if (resourceType != SH_ATT_DESC_TYPE::COLOR_PRESENT)
{
// prepare image view details
SHImageViewDetails viewDetails
{
.viewType = vk::ImageViewType::e2D,
.format = images[0]->GetImageFormat(),
.imageAspectFlags = imageAspectFlags,
.baseMipLevel = 0,
.mipLevelCount = mipLevels,
.baseArrayLayer = 0,
.layerCount = 1,
};
for (uint32_t i = 0; i < images.size(); ++i)
{
images[i]->HandleResizeFramebufferImage(width, height);
imageViews[i]->ViewNewImage(images[i], viewDetails);
}
}
else
{
// Prepare image view details
SHImageViewDetails viewDetails
{
.viewType = vk::ImageViewType::e2D,
.format = swapchain->GetSurfaceFormatKHR().format,
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.mipLevelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
for (uint32_t i = 0; i < swapchain->GetNumImages(); ++i)
{
images[i] = swapchain->GetSwapchainImage(i);
imageViews[i]->ViewNewImage(images[i], viewDetails);
}
}
}
}

View File

@ -20,6 +20,12 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
// for creation/recreation
Handle<SHVkLogicalDevice> logicalDevice;
// for creation/recreation
Handle<SHVkSwapchain> swapchain;
//! Name of the resource
std::string resourceName;
@ -47,6 +53,14 @@ namespace SHADE
//! Number of mipmap levels
uint8_t mipLevels;
//! image aspect flags
vk::ImageAspectFlags imageAspectFlags;
//! usage flags
vk::ImageUsageFlags usage = {};
public:
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
@ -56,6 +70,8 @@ namespace SHADE
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource(void) noexcept;
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
friend class SHRenderGraphNode;
friend class SHRenderGraph;
};

View File

@ -30,7 +30,10 @@ namespace SHADE
SHVkRenderpass::SHVkRenderpass(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept
: logicalDeviceHdl {inLogicalDeviceHdl}
, numAttDescs {static_cast<uint32_t>(vkDescriptions.size())}
, vkSubpassDescriptions{}
, vkSubpassDeps{}
, clearColors{}
, vkAttachmentDescriptions{}
{
for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
{
@ -42,7 +45,6 @@ namespace SHADE
vk::RenderPassCreateInfo renderPassCreateInfo{};
std::vector<vk::SubpassDependency> subpassDeps;
// For validating the depth ref
auto isValidDepthRef = [&](vk::AttachmentReference const& depthRef) -> bool
@ -50,13 +52,16 @@ namespace SHADE
return !(depthRef.attachment == static_cast<uint32_t> (-1) && depthRef.layout == vk::ImageLayout::eUndefined);
};
for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
vkAttachmentDescriptions[i] = vkDescriptions[i];
uint32_t subpassIndex = 0;
if (!subpasses.empty())
{
for (auto& subpass : subpasses)
{
subpassDescriptions.emplace_back();
auto& spDesc = subpassDescriptions.back();
vkSubpassDescriptions.emplace_back();
auto& spDesc = vkSubpassDescriptions.back();
spDesc.pColorAttachments = subpass.colorRefs.data();
spDesc.colorAttachmentCount = static_cast<uint32_t>(subpass.colorRefs.size());
@ -88,18 +93,18 @@ namespace SHADE
};
// Push a new dependency
subpassDeps.push_back(dependency);
vkSubpassDeps.push_back(dependency);
++subpassIndex;
}
// Renderpass create info for render pass creation
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkDescriptions.size());
renderPassCreateInfo.pAttachments = vkDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(subpassDescriptions.size());
renderPassCreateInfo.pSubpasses = subpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(subpassDeps.size());
renderPassCreateInfo.pDependencies = subpassDeps.data();
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkAttachmentDescriptions.size());
renderPassCreateInfo.pAttachments = vkAttachmentDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(vkSubpassDescriptions.size());
renderPassCreateInfo.pSubpasses = vkSubpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(vkSubpassDeps.size());
renderPassCreateInfo.pDependencies = vkSubpassDeps.data();
}
// No subpasses passed in, create a default one.
@ -172,6 +177,8 @@ namespace SHADE
: logicalDeviceHdl{ inLogicalDeviceHdl }
, numAttDescs{ static_cast<uint32_t>(vkDescriptions.size()) }
, clearColors{}
, vkSubpassDescriptions{ }
, vkSubpassDeps{ }
{
for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
{
@ -181,18 +188,24 @@ namespace SHADE
clearColors[i].color = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
}
subpassDescriptions.resize (spDescs.size());
for (uint32_t i = 0; i < subpassDescriptions.size(); ++i)
{
subpassDescriptions[i] = spDescs[i];
}
vkAttachmentDescriptions.resize(vkDescriptions.size());
for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
vkAttachmentDescriptions[i] = vkDescriptions[i];
vkSubpassDescriptions.resize (spDescs.size());
for (uint32_t i = 0; i < vkSubpassDescriptions.size(); ++i)
vkSubpassDescriptions[i] = spDescs[i];
vkSubpassDeps.resize(spDeps.size());
for (uint32_t i = 0; i < vkSubpassDeps.size(); ++i)
vkSubpassDeps[i] = spDeps[i];
vk::RenderPassCreateInfo renderPassCreateInfo{};
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkDescriptions.size());
renderPassCreateInfo.pAttachments = vkDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(subpassDescriptions.size());
renderPassCreateInfo.pSubpasses = subpassDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(vkSubpassDescriptions.size());
renderPassCreateInfo.pSubpasses = vkSubpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(spDeps.size());
renderPassCreateInfo.pDependencies = spDeps.data();
@ -210,8 +223,11 @@ namespace SHADE
SHVkRenderpass::SHVkRenderpass(SHVkRenderpass&& rhs) noexcept
: vkRenderpass {rhs.vkRenderpass}
, logicalDeviceHdl {rhs.logicalDeviceHdl}
, subpassDescriptions {std::move (rhs.subpassDescriptions)}
, clearColors {std::move (rhs.clearColors)}
, vkSubpassDescriptions{ std::move(rhs.vkSubpassDescriptions) }
, vkSubpassDeps{ std::move(rhs.vkSubpassDeps) }
, clearColors{ std::move(rhs.clearColors) }
, vkAttachmentDescriptions{ std::move(rhs.vkAttachmentDescriptions) }
, numAttDescs{rhs.numAttDescs}
{
rhs.vkRenderpass = VK_NULL_HANDLE;
}
@ -224,8 +240,11 @@ namespace SHADE
vkRenderpass = rhs.vkRenderpass;
logicalDeviceHdl = rhs.logicalDeviceHdl;
subpassDescriptions = std::move(rhs.subpassDescriptions);
vkSubpassDescriptions = std::move(rhs.vkSubpassDescriptions);
vkSubpassDeps = std::move(rhs.vkSubpassDeps);
clearColors = std::move(rhs.clearColors);
vkAttachmentDescriptions = std::move(rhs.vkAttachmentDescriptions);
numAttDescs = std::move(rhs.numAttDescs);
rhs.vkRenderpass = VK_NULL_HANDLE;
@ -238,6 +257,31 @@ namespace SHADE
}
void SHVkRenderpass::HandleResize(void) noexcept
{
logicalDeviceHdl->GetVkLogicalDevice().destroyRenderPass(vkRenderpass, nullptr);
vk::RenderPassCreateInfo renderPassCreateInfo{};
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkAttachmentDescriptions.size());
renderPassCreateInfo.pAttachments = vkAttachmentDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(vkSubpassDescriptions.size());
renderPassCreateInfo.pSubpasses = vkSubpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(vkSubpassDeps.size());
renderPassCreateInfo.pDependencies = vkSubpassDeps.data();
if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createRenderPass(&renderPassCreateInfo, nullptr, &vkRenderpass); result != vk::Result::eSuccess)
{
SHVulkanDebugUtil::ReportVkError(result, "Failed to create Renderpass. ");
}
else
{
SHVulkanDebugUtil::ReportVkSuccess("Successfully created Renderpass. ");
}
}
vk::RenderPass SHVkRenderpass::GetVkRenderpass(void) const noexcept
{
return vkRenderpass;

View File

@ -29,7 +29,13 @@ namespace SHADE
Handle<SHVkLogicalDevice> logicalDeviceHdl;
//! Container of subpass information used to construct subpasses
std::vector<vk::SubpassDescription> subpassDescriptions;
std::vector<vk::SubpassDescription> vkSubpassDescriptions;
//! Container of subpass dependencies used to create renderpass
std::vector<vk::SubpassDependency> vkSubpassDeps;
//! Attachment descriptions
std::vector<vk::AttachmentDescription> vkAttachmentDescriptions;
//! Clear colors for the color and depth
std::array<vk::ClearValue, NUM_CLEAR_COLORS> clearColors;
@ -49,6 +55,8 @@ namespace SHADE
SHVkRenderpass(SHVkRenderpass&& rhs) noexcept;
SHVkRenderpass& operator=(SHVkRenderpass&& rhs) noexcept;
void HandleResize (void) noexcept;
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/

View File

@ -272,6 +272,17 @@ namespace SHADE
windowResizeCallbacks.erase(callbackid);
}
SHWindow::CALLBACKID SHWindow::RegisterWindowCloseCallback(WindowCloseCallbackFn windowCloseCallback)
{
windowCloseCallbacks.try_emplace(windowResizeCallbackCount, windowCloseCallback);
return windowCloseCallbackCount++;
}
void SHWindow::UnregisterWindowCloseCallback(CALLBACKID const& callbackid)
{
windowCloseCallbacks.erase(callbackid);
}
LRESULT SHWindow::WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
auto window = windowMap.GetWindow(hwnd);
@ -307,6 +318,8 @@ namespace SHADE
case WM_CREATE:
OnCreate(hwnd, reinterpret_cast<LPCREATESTRUCT>(wparam));
break;
case WM_CLOSE:
case WM_DESTROY:
OnDestroy();
return 0;
@ -362,8 +375,17 @@ namespace SHADE
}
void SHADE::SHWindow::OnClose()
{
for (const auto& callbackFn : windowCloseCallbacks | std::views::values)
{
callbackFn();
}
}
void SHWindow::OnDestroy()
{
OnClose();
this->Destroy();
}
@ -375,6 +397,14 @@ namespace SHADE
{
wndData.width = static_cast<unsigned>(size.cx);
wndData.height = static_cast<unsigned>(size.cy);
if (type == SIZE_MINIMIZED)
{
wndData.isMinimised = true;
}
else
wndData.isMinimised = false;
for (auto const& entry : windowResizeCallbacks)
{
entry.second(static_cast<uint32_t>(wndData.width), static_cast<uint32_t>(wndData.height));

View File

@ -18,7 +18,7 @@ namespace SHADE
};
struct WindowData
{
{
unsigned x = 0;
unsigned y = 0;
@ -42,7 +42,7 @@ namespace SHADE
bool closable = true;
bool minimizable = true;
bool maximizable = true;
//bool canFullscreen = true;
@ -56,11 +56,13 @@ namespace SHADE
bool shadowEnabled = true;
bool isVisible = true;
bool isFullscreen = false;
bool modal = false;
bool isMinimised = false;
std::wstring title = L"SHADE ENGINE";
std::wstring name = L"SHADEEngineApp";
@ -73,6 +75,7 @@ namespace SHADE
public:
using SHVec2 = std::pair<uint32_t, uint32_t>;
typedef std::function<void(uint32_t width, uint32_t height)> WindowResizeCallbackFn;
typedef std::function<void(void)> WindowCloseCallbackFn;
typedef uint16_t CALLBACKID;
SHWindow();
@ -103,7 +106,7 @@ namespace SHADE
void SetMousePosition(unsigned x, unsigned y);
//unsigned GetBGColor();
void SetBGColor(unsigned color);
void Minimize();
@ -123,6 +126,9 @@ namespace SHADE
CALLBACKID RegisterWindowSizeCallback(WindowResizeCallbackFn);
void UnregisterWindowSizeCallback(CALLBACKID const& callbackid);
CALLBACKID RegisterWindowCloseCallback(WindowCloseCallbackFn);
void UnregisterWindowCloseCallback(CALLBACKID const& callbackid);
bool IsMinimized() const { return wndData.isMinimised; }
protected:
static LRESULT CALLBACK WndProcStatic(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
@ -154,10 +160,13 @@ namespace SHADE
HFONT font;
std::unordered_map<CALLBACKID, WindowResizeCallbackFn> windowResizeCallbacks;
std::unordered_map<CALLBACKID, WindowCloseCallbackFn> windowCloseCallbacks;
CALLBACKID windowResizeCallbackCount{};
CALLBACKID windowCloseCallbackCount{};
//TODO: Shift to events abstraction
void OnCreate(HWND hwnd, LPCREATESTRUCT create_struct);
void OnClose();
void OnDestroy();
//void OnFileDrop(HDROP drop);
void OnSize(UINT msg, UINT type, SIZE size);

View File

@ -8,9 +8,9 @@ namespace SHADE
ResourceManager::~ResourceManager()
{
// Delete all resources libraries
for (const auto& deleter : deleters)
for (auto iter = deleters.rbegin(); iter != deleters.rend(); ++iter)
{
deleter();
(*iter)();
}
deleters.clear();
}

View File

@ -118,7 +118,7 @@ namespace SHADE
/// <param name="handle">Handle to the resource object.</param>
/// <returns>Read-only reference to the resource object.</returns>
template<typename T>
const T& Get(Handle<T> handle) const;
const T& Get(Handle<T> handle) const;
private:
/*-----------------------------------------------------------------------------*/

View File

@ -90,10 +90,15 @@ namespace SHADE
#endif
// Go through the map and release all the nodes
for (auto* node : entityNodeMap | std::views::values)
ReleaseNode(node);
for (auto*& node : entityNodeMap | std::views::values)
{
delete node;
node = nullptr;
}
delete root;
entityNodeMap.clear();
//delete root;
#ifdef _DEBUG
SHLOG_INFO("Scene Graph Destroyed Successfully!")

View File

@ -86,3 +86,8 @@ project "SHADE_Managed"
optimize "On"
defines{"_RELEASE"}
links{"librttr_core.lib"}
filter "configurations:Publish"
optimize "On"
defines{"_RELEASE"}
links{"librttr_core.lib"}