Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • vulkan2021/vkcv-framework
1 result
Select Git revision
Show changes
Showing
with 295 additions and 247 deletions
...@@ -14,8 +14,7 @@ layout( push_constant ) uniform constants { ...@@ -14,8 +14,7 @@ layout( push_constant ) uniform constants {
uint matrixIndex; uint matrixIndex;
}; };
// TODO: reuse mesh stage binding at location 2 after required fix in framework layout(std430, set=0, binding = 2) readonly buffer meshletBuffer {
layout(std430, set=0, binding = 5) readonly buffer meshletBuffer {
Meshlet meshlets[]; Meshlet meshlets[];
}; };
......
...@@ -302,15 +302,13 @@ int main(int argc, const char** argv) { ...@@ -302,15 +302,13 @@ int main(int argc, const char** argv) {
2, meshletBuffer.getHandle() 2, meshletBuffer.getHandle()
).writeStorageBuffer( ).writeStorageBuffer(
4, matrixBuffer.getHandle() 4, matrixBuffer.getHandle()
).writeStorageBuffer(
5, meshletBuffer.getHandle()
); );
meshShaderWrites.writeUniformBuffer(3, cameraPlaneBuffer.getHandle()); meshShaderWrites.writeUniformBuffer(3, cameraPlaneBuffer.getHandle());
core.writeDescriptorSet( meshShaderDescriptorSet, meshShaderWrites); core.writeDescriptorSet( meshShaderDescriptorSet, meshShaderWrites);
vkcv::ImageHandle depthBuffer; vkcv::ImageHandle depthBuffer;
vkcv::ImageHandle swapchainImageHandle = vkcv::ImageHandle::createSwapchainImageHandle(); vkcv::ImageHandle swapchainImageHandle = vkcv::ImageHandle::createSwapchainImageHandle();
vkcv::VertexData vertexData (vertexBufferBindings); vkcv::VertexData vertexData (vertexBufferBindings);
......
...@@ -16,12 +16,15 @@ int main(int argc, const char **argv) { ...@@ -16,12 +16,15 @@ int main(int argc, const char **argv) {
uint32_t windowWidth = 800; uint32_t windowWidth = 800;
uint32_t windowHeight = 600; uint32_t windowHeight = 600;
vkcv::Features features;
features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
vkcv::Core core = vkcv::Core::create( vkcv::Core core = vkcv::Core::create(
applicationName, applicationName,
VK_MAKE_VERSION(0, 0, 1), VK_MAKE_VERSION(0, 0, 1),
{vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute}, {vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute},
{ VK_KHR_SWAPCHAIN_EXTENSION_NAME } features
); );
vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true); vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true);
vkcv::Window& window = core.getWindow(windowHandle); vkcv::Window& window = core.getWindow(windowHandle);
......
...@@ -47,11 +47,14 @@ int main(int argc, const char** argv) { ...@@ -47,11 +47,14 @@ int main(int argc, const char** argv) {
const std::string applicationName = "Path Tracer"; const std::string applicationName = "Path Tracer";
vkcv::Features features;
features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
vkcv::Core core = vkcv::Core::create( vkcv::Core core = vkcv::Core::create(
applicationName, applicationName,
VK_MAKE_VERSION(0, 0, 1), VK_MAKE_VERSION(0, 0, 1),
{ vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute },
{ "VK_KHR_swapchain" } features
); );
const int initialWidth = 1280; const int initialWidth = 1280;
......
...@@ -35,11 +35,14 @@ int main(int argc, const char** argv) { ...@@ -35,11 +35,14 @@ int main(int argc, const char** argv) {
const int windowWidth = 800; const int windowWidth = 800;
const int windowHeight = 600; const int windowHeight = 600;
vkcv::Features features;
features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
vkcv::Core core = vkcv::Core::create( vkcv::Core core = vkcv::Core::create(
applicationName, applicationName,
VK_MAKE_VERSION(0, 0, 1), VK_MAKE_VERSION(0, 0, 1),
{ vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute },
{ "VK_KHR_swapchain" } features
); );
vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true); vkcv::WindowHandle windowHandle = core.createWindow(applicationName, windowWidth, windowHeight, true);
......
...@@ -16,12 +16,15 @@ ...@@ -16,12 +16,15 @@
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
const std::string applicationName = "SPH"; const std::string applicationName = "SPH";
vkcv::Features features;
features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
// creating core object that will handle all vulkan objects // creating core object that will handle all vulkan objects
vkcv::Core core = vkcv::Core::create( vkcv::Core core = vkcv::Core::create(
applicationName, applicationName,
VK_MAKE_VERSION(0, 0, 1), VK_MAKE_VERSION(0, 0, 1),
{ vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, { vk::QueueFlagBits::eTransfer, vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute },
{ VK_KHR_SWAPCHAIN_EXTENSION_NAME } features
); );
vkcv::WindowHandle windowHandle = core.createWindow(applicationName, 1280, 720, true); vkcv::WindowHandle windowHandle = core.createWindow(applicationName, 1280, 720, true);
......
...@@ -37,6 +37,7 @@ int main(int argc, const char** argv) { ...@@ -37,6 +37,7 @@ int main(int argc, const char** argv) {
VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,
[](vk::PhysicalDeviceDescriptorIndexingFeatures& features) { [](vk::PhysicalDeviceDescriptorIndexingFeatures& features) {
features.setDescriptorBindingPartiallyBound(true); features.setDescriptorBindingPartiallyBound(true);
features.setDescriptorBindingVariableDescriptorCount(true);
} }
); );
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <cmath> #include <cmath>
#include <cstdint>
#include <limits>
#include <vkcv/Logger.hpp>
#include "AccelerationStructureManager.hpp" #include "AccelerationStructureManager.hpp"
#include "BufferManager.hpp" #include "BufferManager.hpp"
...@@ -91,10 +94,7 @@ namespace vkcv { ...@@ -91,10 +94,7 @@ namespace vkcv {
} }
Core::Core(Context &&context) noexcept : Core::Core(Context &&context) noexcept :
m_Context(std::move(context)), m_PassManager(std::make_unique<PassManager>()), m_Context(std::move(context)),
m_GraphicsPipelineManager(std::make_unique<GraphicsPipelineManager>()),
m_ComputePipelineManager(std::make_unique<ComputePipelineManager>()),
m_RayTracingPipelineManager(std::make_unique<RayTracingPipelineManager>()),
m_DescriptorSetLayoutManager(std::make_unique<DescriptorSetLayoutManager>()), m_DescriptorSetLayoutManager(std::make_unique<DescriptorSetLayoutManager>()),
m_DescriptorSetManager(std::make_unique<DescriptorSetManager>()), m_DescriptorSetManager(std::make_unique<DescriptorSetManager>()),
m_BufferManager(std::make_unique<BufferManager>()), m_BufferManager(std::make_unique<BufferManager>()),
...@@ -103,18 +103,22 @@ namespace vkcv { ...@@ -103,18 +103,22 @@ namespace vkcv {
m_AccelerationStructureManager(std::make_unique<AccelerationStructureManager>()), m_AccelerationStructureManager(std::make_unique<AccelerationStructureManager>()),
m_CommandStreamManager { std::make_unique<CommandStreamManager>() }, m_CommandStreamManager { std::make_unique<CommandStreamManager>() },
m_WindowManager(std::make_unique<WindowManager>()), m_WindowManager(std::make_unique<WindowManager>()),
m_SwapchainManager(std::make_unique<SwapchainManager>()), m_CommandPools(), m_SwapchainManager(std::make_unique<SwapchainManager>()),
m_RenderFinished(), m_SwapchainImageAcquired(), m_downsampler(nullptr) { m_PassManager(std::make_unique<PassManager>()),
m_GraphicsPipelineManager(std::make_unique<GraphicsPipelineManager>()),
m_ComputePipelineManager(std::make_unique<ComputePipelineManager>()),
m_RayTracingPipelineManager(std::make_unique<RayTracingPipelineManager>()),
m_CommandPools(),
m_RenderFinished(),
m_SwapchainImagesAcquired(),
m_currentSwapchainImageIndex(std::numeric_limits<uint32_t>::max()),
m_currentSwapchainSemaphoreIndex(0),
m_downsampler(nullptr) {
m_CommandPools = createCommandPools( m_CommandPools = createCommandPools(
m_Context.getDevice(), generateQueueFamilyIndexSet(m_Context.getQueueManager())); m_Context.getDevice(), generateQueueFamilyIndexSet(m_Context.getQueueManager()));
m_RenderFinished = m_Context.getDevice().createSemaphore({}); m_RenderFinished = m_Context.getDevice().createSemaphore({});
m_SwapchainImageAcquired = m_Context.getDevice().createSemaphore({});
m_PassManager->init(*this);
m_GraphicsPipelineManager->init(*this);
m_ComputePipelineManager->init(*this);
m_RayTracingPipelineManager->init(*this);
m_DescriptorSetLayoutManager->init(*this); m_DescriptorSetLayoutManager->init(*this);
m_DescriptorSetManager->init(*this, *m_DescriptorSetLayoutManager); m_DescriptorSetManager->init(*this, *m_DescriptorSetLayoutManager);
m_BufferManager->init(*this); m_BufferManager->init(*this);
...@@ -123,6 +127,10 @@ namespace vkcv { ...@@ -123,6 +127,10 @@ namespace vkcv {
m_AccelerationStructureManager->init(*this, *m_BufferManager); m_AccelerationStructureManager->init(*this, *m_BufferManager);
m_CommandStreamManager->init(*this); m_CommandStreamManager->init(*this);
m_SwapchainManager->init(*this); m_SwapchainManager->init(*this);
m_PassManager->init(*this);
m_GraphicsPipelineManager->init(*this);
m_ComputePipelineManager->init(*this);
m_RayTracingPipelineManager->init(*this);
m_downsampler = std::unique_ptr<Downsampler>(new BlitDownsampler(*this, *m_ImageManager)); m_downsampler = std::unique_ptr<Downsampler>(new BlitDownsampler(*this, *m_ImageManager));
} }
...@@ -134,7 +142,10 @@ namespace vkcv { ...@@ -134,7 +142,10 @@ namespace vkcv {
} }
m_Context.getDevice().destroySemaphore(m_RenderFinished); m_Context.getDevice().destroySemaphore(m_RenderFinished);
m_Context.getDevice().destroySemaphore(m_SwapchainImageAcquired);
for (auto& semaphore : m_SwapchainImagesAcquired) {
m_Context.getDevice().destroySemaphore(semaphore);
}
} }
GraphicsPipelineHandle Core::createGraphicsPipeline(const GraphicsPipelineConfig &config) { GraphicsPipelineHandle Core::createGraphicsPipeline(const GraphicsPipelineConfig &config) {
...@@ -219,14 +230,25 @@ namespace vkcv { ...@@ -219,14 +230,25 @@ namespace vkcv {
} }
Result Core::acquireSwapchainImage(const SwapchainHandle &swapchainHandle) { Result Core::acquireSwapchainImage(const SwapchainHandle &swapchainHandle) {
uint32_t imageIndex; uint32_t imageIndex, semaphoreIndex;
vk::Result result; vk::Result result;
if (m_SwapchainImagesAcquired.size() <= 0) {
vkcv_log(LogLevel::ERROR, "Semaphores not available");
return Result::ERROR;
}
semaphoreIndex = m_currentSwapchainSemaphoreIndex % m_SwapchainImagesAcquired.size();
try { try {
result = m_Context.getDevice().acquireNextImageKHR( result = m_Context.getDevice().acquireNextImageKHR(
m_SwapchainManager->getSwapchain(swapchainHandle).m_Swapchain, m_SwapchainManager->getSwapchain(swapchainHandle).m_Swapchain,
std::numeric_limits<uint64_t>::max(), m_SwapchainImageAcquired, nullptr, std::numeric_limits<uint64_t>::max(),
&imageIndex, {}); m_SwapchainImagesAcquired[semaphoreIndex],
nullptr,
&imageIndex,
{}
);
} catch (const vk::OutOfDateKHRError &e) { } catch (const vk::OutOfDateKHRError &e) {
result = vk::Result::eErrorOutOfDateKHR; result = vk::Result::eErrorOutOfDateKHR;
} catch (const vk::DeviceLostError &e) { } catch (const vk::DeviceLostError &e) {
...@@ -261,6 +283,17 @@ namespace vkcv { ...@@ -261,6 +283,17 @@ namespace vkcv {
setSwapchainImages(swapchainHandle); setSwapchainImages(swapchainHandle);
} }
const uint32_t count = m_SwapchainManager->getImageCount(swapchainHandle);
const uint32_t initialized = m_SwapchainImagesAcquired.size();
if (count > initialized) {
m_SwapchainImagesAcquired.resize(count);
for (uint32_t i = initialized; i < count; i++) {
m_SwapchainImagesAcquired[i] = m_Context.getDevice().createSemaphore({});
}
}
const auto &extent = m_SwapchainManager->getExtent(swapchainHandle); const auto &extent = m_SwapchainManager->getExtent(swapchainHandle);
width = extent.width; width = extent.width;
...@@ -276,9 +309,6 @@ namespace vkcv { ...@@ -276,9 +309,6 @@ namespace vkcv {
m_currentSwapchainImageIndex = std::numeric_limits<uint32_t>::max(); m_currentSwapchainImageIndex = std::numeric_limits<uint32_t>::max();
} }
m_Context.getDevice().waitIdle(); // TODO: this is a sin against graphics programming, but
// its getting late - Alex
m_ImageManager->setCurrentSwapchainImageIndex(m_currentSwapchainImageIndex); m_ImageManager->setCurrentSwapchainImageIndex(m_currentSwapchainImageIndex);
return (m_currentSwapchainImageIndex != std::numeric_limits<uint32_t>::max()); return (m_currentSwapchainImageIndex != std::numeric_limits<uint32_t>::max());
...@@ -286,8 +316,8 @@ namespace vkcv { ...@@ -286,8 +316,8 @@ namespace vkcv {
static std::array<uint32_t, 2> static std::array<uint32_t, 2>
getWidthHeightFromRenderTargets(const Vector<ImageHandle> &renderTargets, getWidthHeightFromRenderTargets(const Vector<ImageHandle> &renderTargets,
const vk::Extent2D &swapchainExtent, const vk::Extent2D &swapchainExtent,
const ImageManager &imageManager) { const ImageManager &imageManager) {
std::array<uint32_t, 2> widthHeight; std::array<uint32_t, 2> widthHeight;
...@@ -831,17 +861,26 @@ namespace vkcv { ...@@ -831,17 +861,26 @@ namespace vkcv {
void Core::endFrame(const WindowHandle &windowHandle) { void Core::endFrame(const WindowHandle &windowHandle) {
SwapchainHandle swapchainHandle = m_WindowManager->getWindow(windowHandle).getSwapchain(); SwapchainHandle swapchainHandle = m_WindowManager->getWindow(windowHandle).getSwapchain();
if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { if ((m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) ||
(m_SwapchainImagesAcquired.size() <= 0)) {
return; return;
} }
const std::array<vk::Semaphore, 2> waitSemaphores { m_RenderFinished, const uint32_t semaphoreIndex = m_currentSwapchainSemaphoreIndex % m_SwapchainImagesAcquired.size();
m_SwapchainImageAcquired }; m_currentSwapchainSemaphoreIndex = (m_currentSwapchainSemaphoreIndex + 1) % m_SwapchainImagesAcquired.size();
const std::array<vk::Semaphore, 2> waitSemaphores {
m_RenderFinished,
m_SwapchainImagesAcquired[semaphoreIndex]
};
const vk::SwapchainKHR &swapchain = const vk::SwapchainKHR &swapchain =
m_SwapchainManager->getSwapchain(swapchainHandle).m_Swapchain; m_SwapchainManager->getSwapchain(swapchainHandle).m_Swapchain;
const vk::PresentInfoKHR presentInfo(waitSemaphores, swapchain, const vk::PresentInfoKHR presentInfo(
m_currentSwapchainImageIndex); waitSemaphores,
swapchain,
m_currentSwapchainImageIndex
);
vk::Result result; vk::Result result;
......
...@@ -34,8 +34,8 @@ namespace vkcv { ...@@ -34,8 +34,8 @@ namespace vkcv {
DescriptorSetLayoutManager::~DescriptorSetLayoutManager() noexcept { DescriptorSetLayoutManager::~DescriptorSetLayoutManager() noexcept {
for (uint64_t id = 0; id < getCount(); id++) { for (uint64_t id = 0; id < getCount(); id++) {
// Resets the usage count to zero for destruction. // Resets the usage count to one for destruction.
getById(id).layoutUsageCount = 0; getById(id).layoutUsageCount = 1;
} }
clear(); clear();
......
#include "DescriptorSetManager.hpp" #include "DescriptorSetManager.hpp"
#include "vkcv/Core.hpp" #include "vkcv/Core.hpp"
#include <vulkan/vulkan_core.h>
namespace vkcv { namespace vkcv {
...@@ -16,27 +17,48 @@ namespace vkcv { ...@@ -16,27 +17,48 @@ namespace vkcv {
m_DescriptorSetLayoutManager = &descriptorSetLayoutManager; m_DescriptorSetLayoutManager = &descriptorSetLayoutManager;
const auto& featureManager = core.getContext().getFeatureManager();
/** /**
* Allocate the set size for the descriptor pools, namely 1000 units of each descriptor type * Allocate the set size for the descriptor pools, namely 1000 units of each descriptor type
* below. Finally, create an initial pool. * below. Finally, create an initial pool.
*/ */
m_PoolSizes.clear(); m_PoolSizes.clear();
m_PoolSizes.emplace_back(vk::DescriptorType::eSampler, 1000); m_PoolSizes.emplace_back(vk::DescriptorType::eSampler, 1000);
m_PoolSizes.emplace_back(vk::DescriptorType::eCombinedImageSampler, 1000);
m_PoolSizes.emplace_back(vk::DescriptorType::eSampledImage, 1000); m_PoolSizes.emplace_back(vk::DescriptorType::eSampledImage, 1000);
m_PoolSizes.emplace_back(vk::DescriptorType::eStorageImage, 1000);
m_PoolSizes.emplace_back(vk::DescriptorType::eUniformTexelBuffer, 1000);
m_PoolSizes.emplace_back(vk::DescriptorType::eStorageTexelBuffer, 1000);
m_PoolSizes.emplace_back(vk::DescriptorType::eUniformBuffer, 1000); m_PoolSizes.emplace_back(vk::DescriptorType::eUniformBuffer, 1000);
m_PoolSizes.emplace_back(vk::DescriptorType::eStorageBuffer, 1000); m_PoolSizes.emplace_back(vk::DescriptorType::eStorageBuffer, 1000);
m_PoolSizes.emplace_back(vk::DescriptorType::eUniformBufferDynamic, 1000); m_PoolSizes.emplace_back(vk::DescriptorType::eUniformBufferDynamic, 1000);
m_PoolSizes.emplace_back(vk::DescriptorType::eStorageBufferDynamic, 1000); m_PoolSizes.emplace_back(vk::DescriptorType::eStorageBufferDynamic, 1000);
m_PoolSizes.emplace_back(vk::DescriptorType::eInputAttachment, 1000);
if (featureManager.isExtensionActive(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME)) {
m_PoolSizes.emplace_back(vk::DescriptorType::eInlineUniformBlock, 1000);
}
if (core.getContext().getFeatureManager().isExtensionActive(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME)) { if (featureManager.isExtensionActive(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME)) {
m_PoolSizes.emplace_back(vk::DescriptorType::eAccelerationStructureKHR, 1000); m_PoolSizes.emplace_back(vk::DescriptorType::eAccelerationStructureKHR, 1000);
} }
m_PoolInfo = vk::DescriptorPoolCreateInfo( m_PoolInfo = vk::DescriptorPoolCreateInfo(
vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1000, vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
static_cast<uint32_t>(m_PoolSizes.size()), m_PoolSizes.data() 1000,
static_cast<uint32_t>(m_PoolSizes.size()),
m_PoolSizes.data()
); );
if (featureManager.isExtensionActive(VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME)) {
m_InlineUniformBlockInfo = vk::DescriptorPoolInlineUniformBlockCreateInfo(
1000
);
m_PoolInfo.setPNext(&m_InlineUniformBlockInfo);
}
return allocateDescriptorPool(); return allocateDescriptorPool();
} }
...@@ -50,19 +72,27 @@ namespace vkcv { ...@@ -50,19 +72,27 @@ namespace vkcv {
} }
void DescriptorSetManager::destroyById(uint64_t id) { void DescriptorSetManager::destroyById(uint64_t id) {
const auto& device = getCore().getContext().getDevice();
auto &set = getById(id); auto &set = getById(id);
if (set.vulkanHandle) { if (set.vulkanHandle) {
getCore().getContext().getDevice().freeDescriptorSets(m_Pools [set.poolIndex], 1, device.freeDescriptorSets(
&(set.vulkanHandle)); m_Pools[set.poolIndex],
set.setLayoutHandle = DescriptorSetLayoutHandle(); 1,
&(set.vulkanHandle)
);
set.vulkanHandle = nullptr; set.vulkanHandle = nullptr;
} }
set.setLayoutHandle = DescriptorSetLayoutHandle();
} }
bool DescriptorSetManager::allocateDescriptorPool() { bool DescriptorSetManager::allocateDescriptorPool() {
const auto& device = getCore().getContext().getDevice();
vk::DescriptorPool pool; vk::DescriptorPool pool;
if (getCore().getContext().getDevice().createDescriptorPool(&m_PoolInfo, nullptr, &pool) if (device.createDescriptorPool(&m_PoolInfo, nullptr, &pool)
!= vk::Result::eSuccess) { != vk::Result::eSuccess) {
vkcv_log(LogLevel::WARNING, "Failed to allocate descriptor pool"); vkcv_log(LogLevel::WARNING, "Failed to allocate descriptor pool");
return false; return false;
...@@ -76,11 +106,13 @@ namespace vkcv { ...@@ -76,11 +106,13 @@ namespace vkcv {
HandleManager<DescriptorSetEntry, DescriptorSetHandle>() {} HandleManager<DescriptorSetEntry, DescriptorSetHandle>() {}
DescriptorSetManager::~DescriptorSetManager() noexcept { DescriptorSetManager::~DescriptorSetManager() noexcept {
const auto& device = getCore().getContext().getDevice();
clear(); clear();
for (const auto &pool : m_Pools) { for (const auto &pool : m_Pools) {
if (pool) { if (pool) {
getCore().getContext().getDevice().destroy(pool); device.destroy(pool);
} }
} }
} }
...@@ -89,9 +121,15 @@ namespace vkcv { ...@@ -89,9 +121,15 @@ namespace vkcv {
DescriptorSetManager::createDescriptorSet(const DescriptorSetLayoutHandle &layout) { DescriptorSetManager::createDescriptorSet(const DescriptorSetLayoutHandle &layout) {
// create and allocate the set based on the layout provided // create and allocate the set based on the layout provided
const auto &setLayout = m_DescriptorSetLayoutManager->getDescriptorSetLayout(layout); const auto &setLayout = m_DescriptorSetLayoutManager->getDescriptorSetLayout(layout);
const auto &device = getCore().getContext().getDevice();
vk::DescriptorSet vulkanHandle; vk::DescriptorSet vulkanHandle;
vk::DescriptorSetAllocateInfo allocInfo(m_Pools.back(), 1, &setLayout.vulkanHandle); vk::DescriptorSetAllocateInfo allocInfo(
m_Pools.back(),
1,
&setLayout.vulkanHandle
);
uint32_t sumVariableDescriptorCounts = 0; uint32_t sumVariableDescriptorCounts = 0;
for (auto bindingElem : setLayout.descriptorBindings) { for (auto bindingElem : setLayout.descriptorBindings) {
...@@ -108,15 +146,21 @@ namespace vkcv { ...@@ -108,15 +146,21 @@ namespace vkcv {
allocInfo.setPNext(&variableAllocInfo); allocInfo.setPNext(&variableAllocInfo);
} }
auto result = auto result = device.allocateDescriptorSets(
getCore().getContext().getDevice().allocateDescriptorSets(&allocInfo, &vulkanHandle); &allocInfo,
&vulkanHandle
);
if (result != vk::Result::eSuccess) { if (result != vk::Result::eSuccess) {
// create a new descriptor pool if the previous one ran out of memory // create a new descriptor pool if the previous one ran out of memory
if (result == vk::Result::eErrorOutOfPoolMemory) { if ((result == vk::Result::eErrorOutOfPoolMemory) &&
allocateDescriptorPool(); (allocateDescriptorPool())) {
allocInfo.setDescriptorPool(m_Pools.back()); allocInfo.setDescriptorPool(m_Pools.back());
result = getCore().getContext().getDevice().allocateDescriptorSets(&allocInfo,
&vulkanHandle); result = device.allocateDescriptorSets(
&allocInfo,
&vulkanHandle
);
} }
if (result != vk::Result::eSuccess) { if (result != vk::Result::eSuccess) {
......
...@@ -38,6 +38,7 @@ namespace vkcv { ...@@ -38,6 +38,7 @@ namespace vkcv {
Vector<vk::DescriptorPool> m_Pools; Vector<vk::DescriptorPool> m_Pools;
Vector<vk::DescriptorPoolSize> m_PoolSizes; Vector<vk::DescriptorPoolSize> m_PoolSizes;
vk::DescriptorPoolCreateInfo m_PoolInfo; vk::DescriptorPoolCreateInfo m_PoolInfo;
vk::DescriptorPoolInlineUniformBlockCreateInfo m_InlineUniformBlockInfo;
bool init(Core &core) override; bool init(Core &core) override;
bool init(Core &core, DescriptorSetLayoutManager &descriptorSetLayoutManager); bool init(Core &core, DescriptorSetLayoutManager &descriptorSetLayoutManager);
......
...@@ -5,12 +5,7 @@ ...@@ -5,12 +5,7 @@
namespace vkcv { namespace vkcv {
Handle::Handle() : m_id(std::numeric_limits<uint64_t>::max()), m_rc(nullptr), m_destroy(nullptr) {} void Handle::destroy() {
Handle::Handle(uint64_t id, const HandleDestroyFunction &destroy) :
m_id(id), m_rc(new uint64_t(1)), m_destroy(destroy) {}
Handle::~Handle() {
if ((m_rc) && (*m_rc > 0) && (--(*m_rc) == 0)) { if ((m_rc) && (*m_rc > 0) && (--(*m_rc) == 0)) {
if (m_destroy) { if (m_destroy) {
m_destroy(m_id); m_destroy(m_id);
...@@ -20,6 +15,15 @@ namespace vkcv { ...@@ -20,6 +15,15 @@ namespace vkcv {
} }
} }
Handle::Handle() : m_id(std::numeric_limits<uint64_t>::max()), m_rc(nullptr), m_destroy(nullptr) {}
Handle::Handle(uint64_t id, const HandleDestroyFunction &destroy) :
m_id(id), m_rc(new uint64_t(1)), m_destroy(destroy) {}
Handle::~Handle() {
destroy();
}
Handle::Handle(const Handle &other) : Handle::Handle(const Handle &other) :
m_id(other.m_id), m_rc(other.m_rc), m_destroy(other.m_destroy) { m_id(other.m_id), m_rc(other.m_rc), m_destroy(other.m_destroy) {
if (m_rc) { if (m_rc) {
...@@ -38,6 +42,8 @@ namespace vkcv { ...@@ -38,6 +42,8 @@ namespace vkcv {
return *this; return *this;
} }
destroy();
m_id = other.m_id; m_id = other.m_id;
m_rc = other.m_rc; m_rc = other.m_rc;
m_destroy = other.m_destroy; m_destroy = other.m_destroy;
...@@ -50,6 +56,8 @@ namespace vkcv { ...@@ -50,6 +56,8 @@ namespace vkcv {
} }
Handle &Handle::operator=(Handle &&other) noexcept { Handle &Handle::operator=(Handle &&other) noexcept {
destroy();
m_id = other.m_id; m_id = other.m_id;
m_rc = other.m_rc; m_rc = other.m_rc;
m_destroy = other.m_destroy; m_destroy = other.m_destroy;
......
...@@ -516,7 +516,7 @@ namespace vkcv { ...@@ -516,7 +516,7 @@ namespace vkcv {
} }
void ImageManager::switchImageLayoutImmediate(const ImageHandle &handle, void ImageManager::switchImageLayoutImmediate(const ImageHandle &handle,
vk::ImageLayout newLayout) { vk::ImageLayout newLayout) {
auto &image = (*this) [handle]; auto &image = (*this) [handle];
const auto transitionBarriers = createImageLayoutTransitionBarriers(image, 0, 0, newLayout, false); const auto transitionBarriers = createImageLayoutTransitionBarriers(image, 0, 0, newLayout, false);
...@@ -540,7 +540,7 @@ namespace vkcv { ...@@ -540,7 +540,7 @@ namespace vkcv {
); );
if (vk::Result::eSuccess != result) { if (vk::Result::eSuccess != result) {
// TODO: warning? vkcv_log(LogLevel::WARNING, "Transition to new layout failed");
break; break;
} }
} }
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include "vkcv/File.hpp" #include "vkcv/File.hpp"
#include "vkcv/Logger.hpp" #include "vkcv/Logger.hpp"
#include <cstddef>
#include <cstdint>
#include <limits>
namespace vkcv { namespace vkcv {
...@@ -79,164 +82,71 @@ namespace vkcv { ...@@ -79,164 +82,71 @@ namespace vkcv {
return true; return true;
} }
void ShaderProgram::reflectShader(ShaderStage shaderStage) { static void reflectShaderDescriptorSets(Dictionary<uint32_t, DescriptorBindings> &descriptorSets,
auto shaderCode = m_Shaders.at(shaderStage); ShaderStage shaderStage,
DescriptorType descriptorType,
spirv_cross::Compiler comp(shaderCode); const spirv_cross::Compiler &comp,
spirv_cross::ShaderResources resources = comp.get_shader_resources(); const spirv_cross::ShaderResources &resources) {
const spirv_cross::SmallVector<spirv_cross::Resource> *res = nullptr;
// reflect vertex input
if (shaderStage == ShaderStage::VERTEX) { switch (descriptorType) {
// spirv-cross API (hopefully) returns the stage_inputs in order case DescriptorType::UNIFORM_BUFFER:
for (uint32_t i = 0; i < resources.stage_inputs.size(); i++) { res = &(resources.uniform_buffers);
// spirv-cross specific objects break;
auto &stage_input = resources.stage_inputs [i]; case DescriptorType::STORAGE_BUFFER:
const spirv_cross::SPIRType &base_type = comp.get_type(stage_input.base_type_id); res = &(resources.storage_buffers);
break;
// vertex input location case DescriptorType::SAMPLER:
const uint32_t attachment_loc = res = &(resources.separate_samplers);
comp.get_decoration(stage_input.id, spv::DecorationLocation); break;
// vertex input name case DescriptorType::IMAGE_SAMPLED:
const std::string attachment_name = stage_input.name; res = &(resources.separate_images);
// vertex input format (implies its size) break;
const VertexAttachmentFormat attachment_format = case DescriptorType::IMAGE_STORAGE:
convertFormat(base_type.basetype, base_type.vecsize); res = &(resources.storage_images);
break;
m_VertexAttachments.push_back( case DescriptorType::UNIFORM_BUFFER_DYNAMIC:
{ attachment_loc, attachment_name, attachment_format, 0 }); res = &(resources.uniform_buffers);
} break;
case DescriptorType::STORAGE_BUFFER_DYNAMIC:
res = &(resources.storage_buffers);
break;
case DescriptorType::ACCELERATION_STRUCTURE_KHR:
res = &(resources.acceleration_structures);
break;
default:
break;
} }
// reflect descriptor sets (uniform buffer, storage buffer, sampler, sampled image, storage if (nullptr == res) {
// image) return;
Vector<std::pair<uint32_t, DescriptorBinding>> bindings;
for (uint32_t i = 0; i < resources.uniform_buffers.size(); i++) {
auto &u = resources.uniform_buffers [i];
const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id);
const spirv_cross::SPIRType &type = comp.get_type(u.type_id);
uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet);
uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding);
uint32_t descriptorCount = base_type.vecsize;
bool variableCount = false;
// query whether reflected resources are qualified as one-dimensional array
if (type.array_size_literal [0]) {
descriptorCount = type.array [0];
if (type.array [0] == 0)
variableCount = true;
}
DescriptorBinding binding {
bindingID, DescriptorType::UNIFORM_BUFFER, descriptorCount, shaderStage,
variableCount,
variableCount // partialBinding == variableCount
};
auto insertionResult =
m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding));
if (!insertionResult.second) {
insertionResult.first->second.shaderStages |= shaderStage;
vkcv_log(LogLevel::WARNING,
"Attempting to overwrite already existing binding %u at set ID %u.",
bindingID, setID);
}
} }
for (uint32_t i = 0; i < resources.storage_buffers.size(); i++) { for (uint32_t i = 0; i < res->size(); i++) {
auto &u = resources.storage_buffers [i]; const spirv_cross::Resource &u = (*res)[i];
const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id); const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id);
const spirv_cross::SPIRType &type = comp.get_type(u.type_id);
uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet);
uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding);
uint32_t descriptorCount = base_type.vecsize; uint32_t descriptorCount = base_type.vecsize;
bool variableCount = false;
// query whether reflected resources are qualified as one-dimensional array
if (type.array_size_literal [0]) {
descriptorCount = type.array [0];
if (type.array [0] == 0)
variableCount = true;
}
DescriptorBinding binding {
bindingID, DescriptorType::STORAGE_BUFFER, descriptorCount, shaderStage,
variableCount,
variableCount // partialBinding == variableCount
};
auto insertionResult =
m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding));
if (!insertionResult.second) {
insertionResult.first->second.shaderStages |= shaderStage;
vkcv_log(LogLevel::WARNING,
"Attempting to overwrite already existing binding %u at set ID %u.",
bindingID, setID);
}
}
for (uint32_t i = 0; i < resources.separate_samplers.size(); i++) {
auto &u = resources.separate_samplers [i];
const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id);
const spirv_cross::SPIRType &type = comp.get_type(u.type_id);
uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet);
uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding);
uint32_t descriptorCount = base_type.vecsize;
bool variableCount = false; bool variableCount = false;
// query whether reflected resources are qualified as one-dimensional array // query whether reflected resources are qualified as one-dimensional array
if (type.array_size_literal [0]) { if (descriptorCount == 0) {
descriptorCount = type.array [0]; variableCount = true;
if (type.array [0] == 0)
variableCount = true;
} }
DescriptorBinding binding { DescriptorBinding binding {
bindingID, DescriptorType::SAMPLER, descriptorCount, shaderStage, variableCount, bindingID,
variableCount // partialBinding == variableCount descriptorType,
}; descriptorCount,
shaderStage,
auto insertionResult =
m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding));
if (!insertionResult.second) {
insertionResult.first->second.shaderStages |= shaderStage;
vkcv_log(LogLevel::WARNING,
"Attempting to overwrite already existing binding %u at set ID %u.",
bindingID, setID);
}
}
for (uint32_t i = 0; i < resources.separate_images.size(); i++) {
auto &u = resources.separate_images [i];
const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id);
const spirv_cross::SPIRType &type = comp.get_type(u.type_id);
uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet);
uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding);
uint32_t descriptorCount = base_type.vecsize;
bool variableCount = false;
// query whether reflected resources are qualified as one-dimensional array
if (type.array_size_literal [0]) {
descriptorCount = type.array [0];
if (type.array [0] == 0)
variableCount = true;
}
DescriptorBinding binding {
bindingID, DescriptorType::IMAGE_SAMPLED, descriptorCount, shaderStage,
variableCount, variableCount,
variableCount // partialBinding == variableCount variableCount // partialBinding == variableCount
}; };
auto insertionResult = auto insertionResult = descriptorSets[setID].insert(std::make_pair(bindingID, binding));
m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding));
if (!insertionResult.second) { if (!insertionResult.second) {
insertionResult.first->second.shaderStages |= shaderStage; insertionResult.first->second.shaderStages |= shaderStage;
...@@ -245,63 +155,96 @@ namespace vkcv { ...@@ -245,63 +155,96 @@ namespace vkcv {
bindingID, setID); bindingID, setID);
} }
} }
}
for (uint32_t i = 0; i < resources.storage_images.size(); i++) { void ShaderProgram::reflectShader(ShaderStage shaderStage) {
auto &u = resources.storage_images [i]; auto shaderCode = m_Shaders.at(shaderStage);
const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id);
const spirv_cross::SPIRType &type = comp.get_type(u.type_id);
uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); spirv_cross::Compiler comp(shaderCode);
uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); spirv_cross::ShaderResources resources = comp.get_shader_resources();
uint32_t descriptorCount = base_type.vecsize; // reflect vertex input
bool variableCount = false; if (shaderStage == ShaderStage::VERTEX) {
// query whether reflected resources are qualified as one-dimensional array // spirv-cross API (hopefully) returns the stage_inputs in order
if (type.array_size_literal [0]) { for (uint32_t i = 0; i < resources.stage_inputs.size(); i++) {
descriptorCount = type.array [0]; // spirv-cross specific objects
if (type.array [0] == 0) auto &stage_input = resources.stage_inputs [i];
variableCount = true; const spirv_cross::SPIRType &base_type = comp.get_type(stage_input.base_type_id);
}
DescriptorBinding binding { // vertex input location
bindingID, DescriptorType::IMAGE_STORAGE, descriptorCount, shaderStage, const uint32_t attachment_loc =
variableCount, comp.get_decoration(stage_input.id, spv::DecorationLocation);
variableCount // partialBinding == variableCount // vertex input name
}; const std::string attachment_name = stage_input.name;
// vertex input format (implies its size)
const VertexAttachmentFormat attachment_format =
convertFormat(base_type.basetype, base_type.vecsize);
auto insertionResult = m_VertexAttachments.push_back(
m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding)); { attachment_loc, attachment_name, attachment_format, 0 });
if (!insertionResult.second) {
insertionResult.first->second.shaderStages |= shaderStage;
vkcv_log(LogLevel::WARNING,
"Attempting to overwrite already existing binding %u at set ID %u.",
bindingID, setID);
} }
} }
// Used to reflect acceleration structure bindings for RTX. reflectShaderDescriptorSets(
for (uint32_t i = 0; i < resources.acceleration_structures.size(); i++) { m_DescriptorSets,
auto &u = resources.acceleration_structures [i]; shaderStage,
const spirv_cross::SPIRType &base_type = comp.get_type(u.base_type_id); DescriptorType::UNIFORM_BUFFER,
comp,
resources
);
reflectShaderDescriptorSets(
m_DescriptorSets,
shaderStage,
DescriptorType::STORAGE_BUFFER,
comp,
resources
);
reflectShaderDescriptorSets(
m_DescriptorSets,
shaderStage,
DescriptorType::SAMPLER,
comp,
resources
);
reflectShaderDescriptorSets(
m_DescriptorSets,
shaderStage,
DescriptorType::IMAGE_SAMPLED,
comp,
resources
);
reflectShaderDescriptorSets(
m_DescriptorSets,
shaderStage,
DescriptorType::IMAGE_STORAGE,
comp,
resources
);
reflectShaderDescriptorSets(
m_DescriptorSets,
shaderStage,
DescriptorType::ACCELERATION_STRUCTURE_KHR,
comp,
resources
);
for (auto &descriptorSet : m_DescriptorSets) {
uint32_t maxVariableBindingID = 0;
for (const auto &binding : descriptorSet.second) {
maxVariableBindingID = std::max(maxVariableBindingID, binding.first);
}
uint32_t setID = comp.get_decoration(u.id, spv::DecorationDescriptorSet); for (auto &binding : descriptorSet.second) {
uint32_t bindingID = comp.get_decoration(u.id, spv::DecorationBinding); if (binding.first < maxVariableBindingID) {
auto binding = DescriptorBinding { bindingID, binding.second.variableCount &= false;
DescriptorType::ACCELERATION_STRUCTURE_KHR, binding.second.partialBinding &= false;
base_type.vecsize, }
shaderStage,
false,
false };
auto insertionResult =
m_DescriptorSets [setID].insert(std::make_pair(bindingID, binding));
if (!insertionResult.second) {
insertionResult.first->second.shaderStages |= shaderStage;
vkcv_log(LogLevel::WARNING,
"Attempting to overwrite already existing binding %u at set ID %u.",
bindingID, setID);
} }
} }
......
...@@ -207,7 +207,7 @@ namespace vkcv { ...@@ -207,7 +207,7 @@ namespace vkcv {
vk::CompositeAlphaFlagBitsKHR::eOpaque, chosenPresentMode, true, entry.m_Swapchain); vk::CompositeAlphaFlagBitsKHR::eOpaque, chosenPresentMode, true, entry.m_Swapchain);
entry.m_Swapchain = device.createSwapchainKHR(swapchainCreateInfo); entry.m_Swapchain = device.createSwapchainKHR(swapchainCreateInfo);
return true; return entry.m_Swapchain? true : false;
} }
SwapchainHandle SwapchainManager::createSwapchain(Window &window) { SwapchainHandle SwapchainManager::createSwapchain(Window &window) {
......
...@@ -122,6 +122,9 @@ namespace vkcv { ...@@ -122,6 +122,9 @@ namespace vkcv {
Window::e_char.unlock(); Window::e_char.unlock();
Window::e_gamepad.unlock(); Window::e_gamepad.unlock();
Window::e_resize.remove(m_resizeHandle); Window::e_resize.remove(m_resizeHandle);
m_swapchainHandle = SwapchainHandle();
if (m_window) { if (m_window) {
s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window)); s_Windows.erase(std::find(s_Windows.begin(), s_Windows.end(), m_window));
glfwDestroyWindow(m_window); glfwDestroyWindow(m_window);
......