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); 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"} links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
excludes excludes
{ {
"%{prj.location}/src/Editor/**.cpp", -- "%{prj.location}/src/Editor/**.cpp",
"%{prj.location}/src/Editor/**.h", -- "%{prj.location}/src/Editor/**.h",
"%{prj.location}/src/Editor/**.hpp", -- "%{prj.location}/src/Editor/**.hpp",
} }
links{"fmodstudio_vc.lib", "fmod_vc.lib"} links{"fmodstudio_vc.lib", "fmod_vc.lib"}

View File

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

View File

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

View File

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

View File

@ -92,7 +92,7 @@ namespace SHADE
//uint32_t minBuffer //uint32_t minBuffer
if (alignmentSize > 0) if (alignmentSize > 0)
{ {
alignedSize = (alignedSize + alignmentSize - 1) & ~(alignmentSize - 1); alignedSize = (alignedSize + static_cast<uint32_t>(alignmentSize) - 1) & ~(alignmentSize - 1);
} }
return alignedSize; return alignedSize;
} }
@ -195,6 +195,8 @@ namespace SHADE
vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{}; vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{};
descIndexingFeature.descriptorBindingVariableDescriptorCount = true; descIndexingFeature.descriptorBindingVariableDescriptorCount = true;
descIndexingFeature.shaderSampledImageArrayNonUniformIndexing = true;
descIndexingFeature.runtimeDescriptorArray = true;
// Prepare to create the device // Prepare to create the device
vk::DeviceCreateInfo deviceCreateInfo vk::DeviceCreateInfo deviceCreateInfo
@ -249,6 +251,22 @@ namespace SHADE
vkLogicalDevice.destroy(nullptr); 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 (void) noexcept;
SHVkLogicalDevice& operator= (SHVkLogicalDevice const& rhs) noexcept = default; SHVkLogicalDevice& operator= (SHVkLogicalDevice const& rhs) noexcept = default;
SHVkLogicalDevice& operator= (SHVkLogicalDevice&& rhs) noexcept = default; SHVkLogicalDevice& operator= (SHVkLogicalDevice&& rhs) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER VARIABLES */ /* PUBLIC MEMBER VARIABLES */

View File

@ -98,6 +98,51 @@ namespace SHADE
return *this; 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(SHVkFramebuffer&& rhs) noexcept;
SHVkFramebuffer& operator=(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 */ /* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -79,6 +79,41 @@ namespace SHADE
vmaUnmapMemory(*vmaAllocator, stagingAlloc); 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( SHVkImage::SHVkImage(
VmaAllocator const* allocator, VmaAllocator const* allocator,
SHImageCreateParams const& imageDetails, SHImageCreateParams const& imageDetails,
@ -196,37 +231,7 @@ namespace SHADE
, createFlags {create} , createFlags {create}
, vmaAllocator {allocator} , vmaAllocator {allocator}
{ {
vk::ImageCreateInfo imageCreateInfo{}; CreateFramebufferImage();
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. ");
} }
Handle<SHVkImageView> SHVkImage::CreateImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) const noexcept 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; 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 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; vkImage = inVkImage;

View File

@ -108,7 +108,7 @@ namespace SHADE
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept; void PrepStagingBuffer(const void* data, uint32_t srcSize) noexcept;
void CreateFramebufferImage (void) noexcept;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -137,7 +137,8 @@ namespace SHADE
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 (Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept; void TransferToDeviceResource (Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept;
void PrepareImageTransitionInfo (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) 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 */ /* GETTERS AND SETTERS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -6,6 +6,67 @@
namespace SHADE 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 SHVkImageView::SHVkImageView(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, Handle<SHVkImage> const& parent, SHImageViewDetails const& createParams) noexcept
: parentImage{ } : parentImage{ parent }
, vkImageView{} , vkImageView{}
, imageViewDetails{} , imageViewDetails{createParams}
, logicalDeviceHdl {inLogicalDeviceHdl} , logicalDeviceHdl {inLogicalDeviceHdl}
{ {
auto parentImageCreateFlags = parent->GetImageeCreateFlags(); Create();
// 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;
} }
SHVkImageView::SHVkImageView(SHVkImageView&& rhs) noexcept 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 Handle<SHVkImage> const& SHVkImageView::GetParentImage(void) const noexcept
{ {
return parentImage; return parentImage;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -65,6 +65,7 @@ namespace SHADE
/* Constructor/Destructors */ /* 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(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 */ /* Camera Registration */

View File

@ -73,4 +73,16 @@ namespace SHADE
iter->Free(); iter->Free();
renderers.erase(iter); 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); 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);
/*-----------------------------------------------------------------------------*/
/* Setters */
/*-----------------------------------------------------------------------------*/
void SetWidth(float w) noexcept;
void SetHeight (float h) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Getters */ /* Getters */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

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

View File

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

View File

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

View File

@ -149,7 +149,7 @@ namespace SHADE
{ {
texOrder.emplace_back(job.TextureHandle); texOrder.emplace_back(job.TextureHandle);
combinedImageSamplers.emplace_back(std::make_tuple(job.TextureHandle->ImageView, job.Sampler, vk::ImageLayout::eShaderReadOnlyOptimal)); 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(); addJobs.clear();

View File

@ -46,7 +46,7 @@ namespace SHADE
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1)) if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
{ {
w = swapchainHdl->GetSwapchainImage(0)->GetWidth(); w = swapchainHdl->GetSwapchainImage(0)->GetWidth();
w = swapchainHdl->GetSwapchainImage(0)->GetHeight(); h = swapchainHdl->GetSwapchainImage(0)->GetHeight();
format = swapchainHdl->GetSurfaceFormatKHR().format; format = swapchainHdl->GetSurfaceFormatKHR().format;
} }
@ -465,9 +465,6 @@ namespace SHADE
// better way to manage these // better way to manage these
void SHRenderGraph::Execute(uint32_t frameIndex, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkDescriptorPool> descPool) noexcept 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) for (auto& node : nodes)
node->Execute(cmdBuffer, descPool, frameIndex); 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 Handle<SHRenderGraphNode> SHRenderGraph::GetNode(std::string const& nodeName) const noexcept
{ {
if (nodeIndexing.contains(nodeName)) if (nodeIndexing.contains(nodeName))

View File

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

View File

@ -3,6 +3,7 @@
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Images/SHVkImageView.h" #include "Graphics/Images/SHVkImageView.h"
#include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Framebuffer/SHVkFramebuffer.h"
#include "SHRenderGraphResource.h" #include "SHRenderGraphResource.h"
#include "SHSubpass.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 CreateRenderpass(void) noexcept;
void CreateFramebuffer(void) noexcept; void CreateFramebuffer(void) noexcept;
void HandleResize (void) noexcept;
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@ -2,9 +2,11 @@
#include "SHRenderGraphResource.h" #include "SHRenderGraphResource.h"
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Swapchain/SHVkSwapchain.h" #include "Graphics/Swapchain/SHVkSwapchain.h"
#include "Graphics/Images/SHVkImageView.h"
namespace SHADE 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 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 } , resourceFormat{ format }
, images{} , images{}
, imageViews{} , imageViews{}
@ -52,10 +56,10 @@ namespace SHADE
, resourceName{ name } , resourceName{ name }
{ {
// If the resource type is an arbitrary image and not swapchain image // 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; imageAspectFlags = vk::ImageAspectFlags{};
vk::ImageUsageFlags usage = {}; usage = {};
// Check the resource type and set image usage flags and image aspect flags accordingly // Check the resource type and set image usage flags and image aspect flags accordingly
switch (resourceType) switch (resourceType)
@ -142,6 +146,7 @@ namespace SHADE
, width{ rhs.width } , width{ rhs.width }
, height{ rhs.height } , height{ rhs.height }
, mipLevels{ rhs.mipLevels } , mipLevels{ rhs.mipLevels }
, imageAspectFlags{ rhs.imageAspectFlags }
{ {
} }
@ -172,6 +177,7 @@ namespace SHADE
width = rhs.width; width = rhs.width;
height = rhs.height; height = rhs.height;
mipLevels = rhs.mipLevels; mipLevels = rhs.mipLevels;
imageAspectFlags = rhs.imageAspectFlags;
return *this; 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 */ /* PRIVATE MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// for creation/recreation
Handle<SHVkLogicalDevice> logicalDevice;
// for creation/recreation
Handle<SHVkSwapchain> swapchain;
//! Name of the resource //! Name of the resource
std::string resourceName; std::string resourceName;
@ -47,6 +53,14 @@ namespace SHADE
//! Number of mipmap levels //! Number of mipmap levels
uint8_t mipLevels; uint8_t mipLevels;
//! image aspect flags
vk::ImageAspectFlags imageAspectFlags;
//! usage flags
vk::ImageUsageFlags usage = {};
public: public:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */ /* CTORS AND DTORS */
@ -56,6 +70,8 @@ namespace SHADE
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept; SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource(void) noexcept; ~SHRenderGraphResource(void) noexcept;
void HandleResize (uint32_t newWidth, uint32_t newHeight) noexcept;
friend class SHRenderGraphNode; friend class SHRenderGraphNode;
friend class SHRenderGraph; 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 SHVkRenderpass::SHVkRenderpass(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, std::span<vk::AttachmentDescription> const vkDescriptions, std::vector<SHVkSubpassParams> const& subpasses) noexcept
: logicalDeviceHdl {inLogicalDeviceHdl} : logicalDeviceHdl {inLogicalDeviceHdl}
, numAttDescs {static_cast<uint32_t>(vkDescriptions.size())} , numAttDescs {static_cast<uint32_t>(vkDescriptions.size())}
, vkSubpassDescriptions{}
, vkSubpassDeps{}
, clearColors{} , clearColors{}
, vkAttachmentDescriptions{}
{ {
for (uint32_t i = 0; i < vkDescriptions.size(); ++i) for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
{ {
@ -42,7 +45,6 @@ namespace SHADE
vk::RenderPassCreateInfo renderPassCreateInfo{}; vk::RenderPassCreateInfo renderPassCreateInfo{};
std::vector<vk::SubpassDependency> subpassDeps;
// For validating the depth ref // For validating the depth ref
auto isValidDepthRef = [&](vk::AttachmentReference const& depthRef) -> bool 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); 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; uint32_t subpassIndex = 0;
if (!subpasses.empty()) if (!subpasses.empty())
{ {
for (auto& subpass : subpasses) for (auto& subpass : subpasses)
{ {
subpassDescriptions.emplace_back(); vkSubpassDescriptions.emplace_back();
auto& spDesc = subpassDescriptions.back(); auto& spDesc = vkSubpassDescriptions.back();
spDesc.pColorAttachments = subpass.colorRefs.data(); spDesc.pColorAttachments = subpass.colorRefs.data();
spDesc.colorAttachmentCount = static_cast<uint32_t>(subpass.colorRefs.size()); spDesc.colorAttachmentCount = static_cast<uint32_t>(subpass.colorRefs.size());
@ -88,18 +93,18 @@ namespace SHADE
}; };
// Push a new dependency // Push a new dependency
subpassDeps.push_back(dependency); vkSubpassDeps.push_back(dependency);
++subpassIndex; ++subpassIndex;
} }
// Renderpass create info for render pass creation // Renderpass create info for render pass creation
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkDescriptions.size()); renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkAttachmentDescriptions.size());
renderPassCreateInfo.pAttachments = vkDescriptions.data(); renderPassCreateInfo.pAttachments = vkAttachmentDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(subpassDescriptions.size()); renderPassCreateInfo.subpassCount = static_cast<uint32_t>(vkSubpassDescriptions.size());
renderPassCreateInfo.pSubpasses = subpassDescriptions.data(); renderPassCreateInfo.pSubpasses = vkSubpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(subpassDeps.size()); renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(vkSubpassDeps.size());
renderPassCreateInfo.pDependencies = subpassDeps.data(); renderPassCreateInfo.pDependencies = vkSubpassDeps.data();
} }
// No subpasses passed in, create a default one. // No subpasses passed in, create a default one.
@ -172,6 +177,8 @@ namespace SHADE
: logicalDeviceHdl{ inLogicalDeviceHdl } : logicalDeviceHdl{ inLogicalDeviceHdl }
, numAttDescs{ static_cast<uint32_t>(vkDescriptions.size()) } , numAttDescs{ static_cast<uint32_t>(vkDescriptions.size()) }
, clearColors{} , clearColors{}
, vkSubpassDescriptions{ }
, vkSubpassDeps{ }
{ {
for (uint32_t i = 0; i < vkDescriptions.size(); ++i) 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}} }; clearColors[i].color = { {{0.0f, 0.0f, 0.0f, 1.0f}} };
} }
subpassDescriptions.resize (spDescs.size()); vkAttachmentDescriptions.resize(vkDescriptions.size());
for (uint32_t i = 0; i < subpassDescriptions.size(); ++i) for (uint32_t i = 0; i < vkDescriptions.size(); ++i)
{ vkAttachmentDescriptions[i] = vkDescriptions[i];
subpassDescriptions[i] = spDescs[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{}; vk::RenderPassCreateInfo renderPassCreateInfo{};
renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkDescriptions.size()); renderPassCreateInfo.attachmentCount = static_cast<uint32_t>(vkDescriptions.size());
renderPassCreateInfo.pAttachments = vkDescriptions.data(); renderPassCreateInfo.pAttachments = vkDescriptions.data();
renderPassCreateInfo.subpassCount = static_cast<uint32_t>(subpassDescriptions.size()); renderPassCreateInfo.subpassCount = static_cast<uint32_t>(vkSubpassDescriptions.size());
renderPassCreateInfo.pSubpasses = subpassDescriptions.data(); renderPassCreateInfo.pSubpasses = vkSubpassDescriptions.data();
renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(spDeps.size()); renderPassCreateInfo.dependencyCount = static_cast<uint32_t>(spDeps.size());
renderPassCreateInfo.pDependencies = spDeps.data(); renderPassCreateInfo.pDependencies = spDeps.data();
@ -210,8 +223,11 @@ namespace SHADE
SHVkRenderpass::SHVkRenderpass(SHVkRenderpass&& rhs) noexcept SHVkRenderpass::SHVkRenderpass(SHVkRenderpass&& rhs) noexcept
: vkRenderpass {rhs.vkRenderpass} : vkRenderpass {rhs.vkRenderpass}
, logicalDeviceHdl {rhs.logicalDeviceHdl} , logicalDeviceHdl {rhs.logicalDeviceHdl}
, subpassDescriptions {std::move (rhs.subpassDescriptions)} , vkSubpassDescriptions{ std::move(rhs.vkSubpassDescriptions) }
, clearColors {std::move (rhs.clearColors)} , vkSubpassDeps{ std::move(rhs.vkSubpassDeps) }
, clearColors{ std::move(rhs.clearColors) }
, vkAttachmentDescriptions{ std::move(rhs.vkAttachmentDescriptions) }
, numAttDescs{rhs.numAttDescs}
{ {
rhs.vkRenderpass = VK_NULL_HANDLE; rhs.vkRenderpass = VK_NULL_HANDLE;
} }
@ -224,8 +240,11 @@ namespace SHADE
vkRenderpass = rhs.vkRenderpass; vkRenderpass = rhs.vkRenderpass;
logicalDeviceHdl = rhs.logicalDeviceHdl; logicalDeviceHdl = rhs.logicalDeviceHdl;
subpassDescriptions = std::move(rhs.subpassDescriptions); vkSubpassDescriptions = std::move(rhs.vkSubpassDescriptions);
vkSubpassDeps = std::move(rhs.vkSubpassDeps);
clearColors = std::move(rhs.clearColors); clearColors = std::move(rhs.clearColors);
vkAttachmentDescriptions = std::move(rhs.vkAttachmentDescriptions);
numAttDescs = std::move(rhs.numAttDescs);
rhs.vkRenderpass = VK_NULL_HANDLE; 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 vk::RenderPass SHVkRenderpass::GetVkRenderpass(void) const noexcept
{ {
return vkRenderpass; return vkRenderpass;

View File

@ -29,7 +29,13 @@ namespace SHADE
Handle<SHVkLogicalDevice> logicalDeviceHdl; Handle<SHVkLogicalDevice> logicalDeviceHdl;
//! Container of subpass information used to construct subpasses //! 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 //! Clear colors for the color and depth
std::array<vk::ClearValue, NUM_CLEAR_COLORS> clearColors; std::array<vk::ClearValue, NUM_CLEAR_COLORS> clearColors;
@ -49,6 +55,8 @@ namespace SHADE
SHVkRenderpass(SHVkRenderpass&& rhs) noexcept; SHVkRenderpass(SHVkRenderpass&& rhs) noexcept;
SHVkRenderpass& operator=(SHVkRenderpass&& rhs) noexcept; SHVkRenderpass& operator=(SHVkRenderpass&& rhs) noexcept;
void HandleResize (void) noexcept;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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