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

Target

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