diff --git a/samples/14_InitPipeline/14_InitPipeline.cpp b/samples/14_InitPipeline/14_InitPipeline.cpp index 74f5d35..ad89c74 100644 --- a/samples/14_InitPipeline/14_InitPipeline.cpp +++ b/samples/14_InitPipeline/14_InitPipeline.cpp @@ -37,7 +37,6 @@ int main(int /*argc*/, char ** /*argv*/) std::vector physicalDevices = instance->enumeratePhysicalDevices(); assert(!physicalDevices.empty()); - vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500)); diff --git a/samples/15_DrawCube/15_DrawCube.cpp b/samples/15_DrawCube/15_DrawCube.cpp index 167dab8..cb335d0 100644 --- a/samples/15_DrawCube/15_DrawCube.cpp +++ b/samples/15_DrawCube/15_DrawCube.cpp @@ -37,7 +37,6 @@ int main(int /*argc*/, char ** /*argv*/) std::vector physicalDevices = instance->enumeratePhysicalDevices(); assert(!physicalDevices.empty()); - vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500)); @@ -77,7 +76,7 @@ int main(int /*argc*/, char ** /*argv*/) std::vector descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 1, &descriptorSetLayout.get())); vk::DescriptorBufferInfo descriptorBufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); - vk::su::updateDescriptorSets(device, descriptorSets[0], &descriptorBufferInfo); + vk::su::updateDescriptorSets(device, descriptorSets[0], vk::DescriptorType::eUniformBuffer, &descriptorBufferInfo); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, vertexShaderModule, fragmentShaderModule, sizeof(coloredCubeData[0]), pipelineLayout, renderPass); diff --git a/samples/DrawTexturedCube/DrawTexturedCube.cpp b/samples/DrawTexturedCube/DrawTexturedCube.cpp index 59737b5..b2e000d 100644 --- a/samples/DrawTexturedCube/DrawTexturedCube.cpp +++ b/samples/DrawTexturedCube/DrawTexturedCube.cpp @@ -134,7 +134,6 @@ int main(int /*argc*/, char ** /*argv*/) std::vector physicalDevices = instance->enumeratePhysicalDevices(); assert(!physicalDevices.empty()); - vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500)); @@ -160,7 +159,7 @@ int main(int /*argc*/, char ** /*argv*/) vk::su::BufferData uniformBufferData(physicalDevices[0], device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix()); - vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, textured); + vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, vk::DescriptorType::eUniformBuffer, textured); vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surfaceData.surface.get())), depthBufferData.format); @@ -175,12 +174,12 @@ int main(int /*argc*/, char ** /*argv*/) vk::su::BufferData vertexBufferData(physicalDevices[0], device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); - vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, textured); + vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, vk::DescriptorType::eUniformBuffer, textured); std::vector descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 1, &descriptorSetLayout.get())); vk::DescriptorBufferInfo bufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); vk::DescriptorImageInfo imageInfo(textureData.textureSampler.get(), textureData.imageData->imageView.get(), vk::ImageLayout::eShaderReadOnlyOptimal); - vk::su::updateDescriptorSets(device, descriptorSets[0], &bufferInfo, &imageInfo); + vk::su::updateDescriptorSets(device, descriptorSets[0], vk::DescriptorType::eUniformBuffer, &bufferInfo, &imageInfo); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, vertexShaderModule, fragmentShaderModule, sizeof(texturedCubeData[0]), pipelineLayout, renderPass); diff --git a/samples/DynamicUniform/CMakeLists.txt b/samples/DynamicUniform/CMakeLists.txt new file mode 100644 index 0000000..204a734 --- /dev/null +++ b/samples/DynamicUniform/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.2) + +project(DynamicUniform) + +set(HEADERS + ../utils/geometries.hpp + ../utils/math.hpp + ../utils/shaders.hpp + ../utils/utils.hpp +) + +set(SOURCES + DynamicUniform.cpp + ../utils/math.cpp + ../utils/shaders.cpp + ../utils/utils.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(DynamicUniform + ${HEADERS} + ${SOURCES} +) + +set_target_properties(DynamicUniform PROPERTIES FOLDER "Samples") +target_include_directories(DynamicUniform PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(DynamicUniform PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/DynamicUniform/DynamicUniform.cpp b/samples/DynamicUniform/DynamicUniform.cpp new file mode 100644 index 0000000..f614b7c --- /dev/null +++ b/samples/DynamicUniform/DynamicUniform.cpp @@ -0,0 +1,186 @@ +// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// VulkanHpp Samples : DynamicUniform +// Draw 2 Cubes using dynamic uniform buffer + +#include "../utils/geometries.hpp" +#include "../utils/math.hpp" +#include "../utils/shaders.hpp" +#include "../utils/utils.hpp" +#include "vulkan/vulkan.hpp" +#include "SPIRV/GlslangToSpv.h" +#include + +static char const* AppName = "DynamicUniform"; +static char const* EngineName = "Vulkan.hpp"; + +int main(int /*argc*/, char ** /*argv*/) +{ + try + { + vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions()); +#if !defined(NDEBUG) + vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance); +#endif + + std::vector physicalDevices = instance->enumeratePhysicalDevices(); + assert(!physicalDevices.empty()); + + vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500)); + + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.surface); + vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); + + vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); + std::vector commandBuffers = device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)); + + vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); + vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); + + vk::su::SwapChainData swapChainData(physicalDevices[0], device, surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc + , graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); + + vk::su::DepthBufferData depthBufferData(physicalDevices[0], device, vk::Format::eD16Unorm, surfaceData.extent); + + vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surfaceData.surface.get())), depthBufferData.format); + + glslang::InitializeProcess(); + vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C); + vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C); + glslang::FinalizeProcess(); + + std::vector framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); + + vk::su::BufferData vertexBufferData(physicalDevices[0], device, sizeof(coloredCubeData), vk::BufferUsageFlagBits::eVertexBuffer); + vk::su::copyToDevice(device, vertexBufferData.deviceMemory, coloredCubeData, sizeof(coloredCubeData) / sizeof(coloredCubeData[0])); + + /* VULKAN_KEY_START */ + + vk::PhysicalDeviceLimits limits = physicalDevices[0].getProperties().limits; + if (limits.maxDescriptorSetUniformBuffersDynamic < 1) + { + std::cout << "No dynamic uniform buffers supported\n"; + exit(-1); + } + + /* Set up uniform buffer with 2 transform matrices in it */ + glm::mat4x4 mvpcs[2]; + glm::mat4x4 model = glm::mat4x4(1.0f); + glm::mat4x4 view = glm::lookAt(glm::vec3(0.0f, 3.0f, -10.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)); + glm::mat4x4 projection = glm::perspective(glm::radians(45.0f), 1.0f, 0.1f, 100.0f); + glm::mat4x4 clip = glm::mat4x4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f); // vulkan clip space has inverted y and half z ! + mvpcs[0] = clip * projection * view * model; + + model = glm::translate(model, glm::vec3(-1.5f, -1.5f, -1.5f)); + mvpcs[1] = clip * projection * view * model; + + VkDeviceSize bufferSize = sizeof(glm::mat4x4); + if (limits.minUniformBufferOffsetAlignment) + { + bufferSize = (bufferSize + limits.minUniformBufferOffsetAlignment - 1) & ~(limits.minUniformBufferOffsetAlignment - 1); + } + + vk::su::BufferData uniformBufferData(physicalDevices[0], device, 2 * bufferSize, vk::BufferUsageFlagBits::eUniformBuffer); + vk::su::copyToDevice(device, uniformBufferData.deviceMemory, mvpcs, 2, bufferSize); + + // create a DescriptorSetLayout with vk::DescriptorType::eUniformBufferDynamic + vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, vk::DescriptorType::eUniformBufferDynamic); + vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); + + // create a DescriptorPool with vk::DescriptorType::eUniformBufferDynamic + vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, vk::DescriptorType::eUniformBufferDynamic); + std::vector descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 1, &descriptorSetLayout.get())); + + vk::DescriptorBufferInfo descriptorBufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); + vk::su::updateDescriptorSets(device, descriptorSets[0], vk::DescriptorType::eUniformBufferDynamic, &descriptorBufferInfo); + + vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); + vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, vertexShaderModule, fragmentShaderModule, sizeof(coloredCubeData[0]), pipelineLayout, renderPass); + + // Get the index of the next available swapchain image: + vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); + vk::ResultValue currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); + assert(currentBuffer.result == vk::Result::eSuccess); + assert(currentBuffer.value < framebuffers.size()); + + commandBuffers[0]->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags())); + + vk::ClearValue clearValues[2]; + clearValues[0].color = vk::ClearColorValue(std::array({ 0.2f, 0.2f, 0.2f, 0.2f })); + clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); + vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); + commandBuffers[0]->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); + commandBuffers[0]->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); + + vk::Viewport viewport(0.0f, 0.0f, static_cast(surfaceData.extent.width), static_cast(surfaceData.extent.height), 0.0f, 1.0f); + commandBuffers[0]->setViewport(0, viewport); + + vk::Rect2D scissor(vk::Offset2D(0, 0), surfaceData.extent); + commandBuffers[0]->setScissor(0, scissor); + + /* The first draw should use the first matrix in the buffer */ + uint32_t dynamicOffset = 0; + commandBuffers[0]->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSets[0].get(), dynamicOffset); + + vk::DeviceSize vertexOffset = 0; + commandBuffers[0]->bindVertexBuffers(0, vertexBufferData.buffer.get(), vertexOffset); + commandBuffers[0]->draw(12 * 3, 1, 0, 0); + + // the second draw should use the second matrix in the buffer; + dynamicOffset = (uint32_t)bufferSize; + commandBuffers[0]->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSets[0].get(), dynamicOffset); + commandBuffers[0]->draw(12 * 3, 1, 0, 0); + + commandBuffers[0]->endRenderPass(); + commandBuffers[0]->end(); + + vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); + + vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); + vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffers[0].get()); + graphicsQueue.submit(submitInfo, drawFence.get()); + + while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) + ; + + presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), ¤tBuffer.value)); + Sleep(1000); + + /* VULKAN_KEY_END */ + + device->waitIdle(); +#if defined(VK_USE_PLATFORM_WIN32_KHR) + DestroyWindow(surfaceData.window); +#else +#pragma error "unhandled platform" +#endif + } + catch (vk::SystemError err) + { + std::cout << "vk::SystemError: " << err.what() << std::endl; + exit(-1); + } + catch (std::runtime_error err) + { + std::cout << "std::runtime_error: " << err.what() << std::endl; + exit(-1); + } + catch (...) + { + std::cout << "unknown error\n"; + exit(-1); + } + return 0; +} diff --git a/samples/EnableValidationWithCallback/CMakeLists.txt b/samples/EnableValidationWithCallback/CMakeLists.txt new file mode 100644 index 0000000..3dc4146 --- /dev/null +++ b/samples/EnableValidationWithCallback/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.2) + +project(EnableValidationWithCallback) + +set(HEADERS +) + +set(SOURCES + EnableValidationWithCallback.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(EnableValidationWithCallback + ${HEADERS} + ${SOURCES} +) + +set_target_properties(EnableValidationWithCallback PROPERTIES FOLDER "Samples") +target_include_directories(EnableValidationWithCallback PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(EnableValidationWithCallback PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/EnableValidationWithCallback/EnableValidationWithCallback.cpp b/samples/EnableValidationWithCallback/EnableValidationWithCallback.cpp new file mode 100644 index 0000000..6107413 --- /dev/null +++ b/samples/EnableValidationWithCallback/EnableValidationWithCallback.cpp @@ -0,0 +1,178 @@ +// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// VulkanHpp Samples : EnableValidationWithCallback +// Show how to enable validation layers and provide callback + +#include "../utils/utils.hpp" +#include "vulkan/vulkan.hpp" +#include +#include +#include + +static char const* AppName = "EnableValidationWithCallback"; +static char const* EngineName = "Vulkan.hpp"; + +PFN_vkCreateDebugReportCallbackEXT pfnVkCreateDebugReportCallbackEXT; +PFN_vkDestroyDebugReportCallbackEXT pfnVkDestroyDebugReportCallbackEXT; + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback) +{ + return pfnVkCreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback); +} + +VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator) +{ + pfnVkDestroyDebugReportCallbackEXT(instance, callback, pAllocator); +} + + +VKAPI_ATTR VkBool32 VKAPI_CALL dbgFunc(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT /*objType*/, uint64_t /*srcObject*/, size_t /*location*/, int32_t msgCode, const char *pLayerPrefix, const char *pMsg, void * /*pUserData*/) +{ + std::ostringstream message; + + switch (flags) + { + case VK_DEBUG_REPORT_INFORMATION_BIT_EXT: + message << "INFORMATION: "; + break; + case VK_DEBUG_REPORT_WARNING_BIT_EXT: + message << "WARNING: "; + break; + case VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT: + message << "PERFORMANCE WARNING: "; + break; + case VK_DEBUG_REPORT_ERROR_BIT_EXT: + message << "ERROR: "; + break; + case VK_DEBUG_REPORT_DEBUG_BIT_EXT: + message << "DEBUG: "; + break; + default: + message << "unknown flag (" << flags << "): "; + break; + } + message << "[" << pLayerPrefix << "] Code " << msgCode << " : " << pMsg; + +#ifdef _WIN32 + MessageBox(NULL, message.str().c_str(), "Alert", MB_OK); +#else + std::cout << message.str() << std::endl; +#endif + + return false; +} + +bool checkLayers(std::vector const& layers, std::vector const& properties) +{ + // return true if all layers are listed in the properties + return std::all_of(layers.begin(), layers.end(), [&properties](char const* name) + { + return std::find_if(properties.begin(), properties.end(), [&name](vk::LayerProperties const& property) { return strcmp(property.layerName, name) == 0; }) != properties.end(); + }); +} + +int main(int /*argc*/, char ** /*argv*/) +{ + try + { + std::vector instanceLayerProperties = vk::enumerateInstanceLayerProperties(); + + /* VULKAN_KEY_START */ + + // Use standard_validation meta layer that enables all recommended validation layers + std::vector instanceLayerNames; + instanceLayerNames.push_back("VK_LAYER_LUNARG_standard_validation"); + if (!checkLayers(instanceLayerNames, instanceLayerProperties)) + { + // If standard validation is not present, search instead for the individual layers that make it up, in the correct order. + instanceLayerNames.clear(); + instanceLayerNames.push_back("VK_LAYER_GOOGLE_threading"); + instanceLayerNames.push_back("VK_LAYER_LUNARG_parameter_validation"); + instanceLayerNames.push_back("VK_LAYER_LUNARG_object_tracker"); + instanceLayerNames.push_back("VK_LAYER_LUNARG_core_validation"); + instanceLayerNames.push_back("VK_LAYER_GOOGLE_unique_objects"); + + if (!checkLayers(instanceLayerNames, instanceLayerProperties)) + { + std::cout << "Set the environment variable VK_LAYER_PATH to point to the location of your layers" << std::endl; + exit(1); + } + } + + /* Enable debug callback extension */ + std::vector instanceExtensionNames; + instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); + + vk::ApplicationInfo applicationInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_0); + vk::InstanceCreateInfo instanceCreateInfo( vk::InstanceCreateFlags(), &applicationInfo, vk::su::checked_cast(instanceLayerNames.size()), instanceLayerNames.data(), + vk::su::checked_cast(instanceExtensionNames.size()) , instanceExtensionNames.data() ); + vk::UniqueInstance instance = vk::createInstanceUnique(instanceCreateInfo); + + std::vector physicalDevices = instance->enumeratePhysicalDevices(); + assert(!physicalDevices.empty()); + + std::vector queueFamilyProperties = physicalDevices[0].getQueueFamilyProperties(); + assert(!queueFamilyProperties.empty()); + + auto qfpIt = std::find_if(queueFamilyProperties.begin(), queueFamilyProperties.end(), [](vk::QueueFamilyProperties const& qfp) { return !!(qfp.queueFlags & vk::QueueFlagBits::eGraphics); }); + assert(qfpIt != queueFamilyProperties.end()); + uint32_t queueFamilyIndex = static_cast(std::distance(queueFamilyProperties.begin(), qfpIt)); + + float queuePriority = 0.0f; + vk::DeviceQueueCreateInfo deviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), queueFamilyIndex, 1, &queuePriority); + vk::UniqueDevice device = physicalDevices[0].createDeviceUnique(vk::DeviceCreateInfo(vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo)); + + pfnVkCreateDebugReportCallbackEXT = reinterpret_cast(instance->getProcAddr("vkCreateDebugReportCallbackEXT")); + if (!pfnVkCreateDebugReportCallbackEXT) + { + std::cout << "GetInstanceProcAddr: Unable to find vkCreateDebugReportCallbackEXT function." << std::endl; + exit(1); + } + pfnVkDestroyDebugReportCallbackEXT = reinterpret_cast(instance->getProcAddr("vkDestroyDebugReportCallbackEXT")); + if (!pfnVkDestroyDebugReportCallbackEXT) + { + std::cout << "GetInstanceProcAddr: Unable to find vkDestroyDebugReportCallbackEXT function." << std::endl; + exit(1); + } + + vk::UniqueDebugReportCallbackEXT debugReportCallback = instance->createDebugReportCallbackEXTUnique(vk::DebugReportCallbackCreateInfoEXT(vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eWarning, dbgFunc)); + + // Create a command pool (not a UniqueCommandPool, for testing purposes! + vk::CommandPool commandPool = device->createCommandPool(vk::CommandPoolCreateInfo(vk::CommandPoolCreateFlags(), queueFamilyIndex)); + + // The commandPool is not destroyed automatically (as it's not a UniqueCommandPool. + // That is, the device is destroyed before the commmand pool and will trigger a validation error. + std::cout << "*** INTENTIONALLY calling vkDestroyDevice before destroying command pool ***\n"; + std::cout << "*** The following error message is EXPECTED ***\n"; + + /* VULKAN_KEY_END */ + } + catch (vk::SystemError err) + { + std::cout << "vk::SystemError: " << err.what() << std::endl; + exit(-1); + } + catch (std::runtime_error err) + { + std::cout << "std::runtime_error: " << err.what() << std::endl; + exit(-1); + } + catch (...) + { + std::cout << "unknown error\n"; + exit(-1); + } + return 0; +} diff --git a/samples/EnumerateDevicesAdvanced/CMakeLists.txt b/samples/EnumerateDevicesAdvanced/CMakeLists.txt new file mode 100644 index 0000000..b23a4ce --- /dev/null +++ b/samples/EnumerateDevicesAdvanced/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright(c) 2018-2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.2) + +project(EnumerateDevicesAdvanced) + +set(HEADERS + ../utils/utils.hpp +) + +set(SOURCES + EnumerateDevicesAdvanced.cpp + ../utils/utils.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(EnumerateDevicesAdvanced + ${HEADERS} + ${SOURCES} +) + +set_target_properties(EnumerateDevicesAdvanced PROPERTIES FOLDER "Samples") +target_link_libraries(EnumerateDevicesAdvanced "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib") diff --git a/samples/EnumerateDevicesAdvanced/EnumerateDevicesAdvanced.cpp b/samples/EnumerateDevicesAdvanced/EnumerateDevicesAdvanced.cpp new file mode 100644 index 0000000..e3aa089 --- /dev/null +++ b/samples/EnumerateDevicesAdvanced/EnumerateDevicesAdvanced.cpp @@ -0,0 +1,94 @@ +// Copyright(c) 2018-2019, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// VulkanHpp Samples : EnumerateDevicesAdvanced +// Enumerate physical devices + +#include "../utils/utils.hpp" +#include "vulkan/vulkan.hpp" +#include +#include + +static char const* AppName = "EnumerateDevicesAdvanced"; +static char const* EngineName = "Vulkan.hpp"; + +void print_UUID(uint8_t *pipelineCacheUUID) +{ + for (int j = 0; j < VK_UUID_SIZE; ++j) + { + std::cout << std::setw(2) << (uint32_t)pipelineCacheUUID[j]; + if (j == 3 || j == 5 || j == 7 || j == 9) + { + std::cout << '-'; + } + } +} + +int main(int /*argc*/, char ** /*argv*/) +{ + try + { + vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); +#if !defined(NDEBUG) + vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance); +#endif + + /* VULKAN_HPP_KEY_START */ + + // enumerate the physicalDevices + std::vector physicalDevices = instance->enumeratePhysicalDevices(); + + for (auto const& physicalDevice : physicalDevices) + { + vk::PhysicalDeviceProperties properties = physicalDevice.getProperties(); + + std::cout << "apiVersion: "; + std::cout << ((properties.apiVersion >> 22) & 0xfff) << '.'; // Major. + std::cout << ((properties.apiVersion >> 12) & 0x3ff) << '.'; // Minor. + std::cout << (properties.apiVersion & 0xfff); // Patch. + std::cout << '\n'; + + std::cout << "driverVersion: " << properties.driverVersion << '\n'; + + std::cout << std::showbase << std::internal << std::setfill('0') << std::hex; + std::cout << "vendorId: " << std::setw(6) << properties.vendorID << '\n'; + std::cout << "deviceId: " << std::setw(6) << properties.deviceID << '\n'; + std::cout << std::noshowbase << std::right << std::setfill(' ') << std::dec; + + std::cout << "deviceType: " << vk::to_string(properties.deviceType) << "\n"; + + std::cout << "deviceName: " << properties.deviceName << '\n'; + + std::cout << "pipelineCacheUUID: "; + std::cout << std::setfill('0') << std::hex; + print_UUID(properties.pipelineCacheUUID); + std::cout << std::setfill(' ') << std::dec; + std::cout << '\n'; + std::cout << '\n'; + } + + /* VULKAN_HPP_KEY_END */ + } + catch (vk::SystemError err) + { + std::cout << "vk::SystemError: " << err.what() << std::endl; + exit(-1); + } + catch (...) + { + std::cout << "unknown error\n"; + exit(-1); + } + return 0; +} diff --git a/samples/Events/CMakeLists.txt b/samples/Events/CMakeLists.txt new file mode 100644 index 0000000..3a184ea --- /dev/null +++ b/samples/Events/CMakeLists.txt @@ -0,0 +1,44 @@ +# Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.2) + +project(Events) + +set(HEADERS + ../utils/geometries.hpp + ../utils/math.hpp + ../utils/shaders.hpp + ../utils/utils.hpp +) + +set(SOURCES + Events.cpp + ../utils/math.cpp + ../utils/shaders.cpp + ../utils/utils.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(Events + ${HEADERS} + ${SOURCES} +) + +set_target_properties(Events PROPERTIES FOLDER "Samples") +target_include_directories(Events PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(Events PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/Events/Events.cpp b/samples/Events/Events.cpp new file mode 100644 index 0000000..074c19c --- /dev/null +++ b/samples/Events/Events.cpp @@ -0,0 +1,156 @@ +// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// VulkanHpp Samples : Events +// Use basic events + +#include "../utils/geometries.hpp" +#include "../utils/math.hpp" +#include "../utils/shaders.hpp" +#include "../utils/utils.hpp" +#include "vulkan/vulkan.hpp" +#include "SPIRV/GlslangToSpv.h" +#include + +static char const* AppName = "Events"; +static char const* EngineName = "Vulkan.hpp"; + +int main(int /*argc*/, char ** /*argv*/) +{ + try + { + vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions()); +#if !defined(NDEBUG) + vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance); +#endif + + std::vector physicalDevices = instance->enumeratePhysicalDevices(); + assert(!physicalDevices.empty()); + + uint32_t graphicsQueueFamilyIndex = vk::su::findGraphicsQueueFamilyIndex(physicalDevices[0].getQueueFamilyProperties()); + vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsQueueFamilyIndex); + + vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsQueueFamilyIndex); + std::vector commandBuffers = device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)); + + vk::Queue graphicsQueue = device->getQueue(graphicsQueueFamilyIndex, 0); + + /* VULKAN_KEY_START */ + + // Start with a trivial command buffer and make sure fence wait doesn't time out + commandBuffers[0]->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags())); + commandBuffers[0]->setViewport(0, vk::Viewport(0.0f, 0.0f, 10.0f, 10.0f, 0.0f, 1.0f)); + commandBuffers[0]->end(); + + vk::UniqueFence fence = device->createFenceUnique(vk::FenceCreateInfo()); + + vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); + vk::SubmitInfo submitInfo(0, nullptr, &waitDestinationStageMask, 1, &commandBuffers[0].get()); + graphicsQueue.submit(submitInfo, fence.get()); + + // Make sure timeout is long enough for a simple command buffer without waiting for an event + vk::Result result; + int timeouts = -1; + do + { + result = device->waitForFences(fence.get(), true, vk::su::FenceTimeout); + timeouts++; + } while (result == vk::Result::eTimeout); + assert(result == vk::Result::eSuccess); + if (timeouts != 0) + { + std::cout << "Unsuitable timeout value, exiting\n"; + exit(-1); + } + + // Now create an event and wait for it on the GPU + vk::UniqueEvent event = device->createEventUnique(vk::EventCreateInfo(vk::EventCreateFlags())); + + commandBuffers[0]->reset(vk::CommandBufferResetFlags()); + commandBuffers[0]->begin(vk::CommandBufferBeginInfo()); + commandBuffers[0]->waitEvents(event.get(), vk::PipelineStageFlagBits::eHost, vk::PipelineStageFlagBits::eBottomOfPipe, nullptr, nullptr, nullptr); + commandBuffers[0]->end(); + device->resetFences(fence.get()); + + // Note that stepping through this code in the debugger is a bad idea because the GPU can TDR waiting for the event. + // Execute the code from vkQueueSubmit through vkSetEvent without breakpoints + waitDestinationStageMask = vk::PipelineStageFlagBits::eBottomOfPipe; + graphicsQueue.submit(submitInfo, fence.get()); + + // We should timeout waiting for the fence because the GPU should be waiting on the event + result = device->waitForFences(fence.get(), true, vk::su::FenceTimeout); + if (result != vk::Result::eTimeout) + { + std::cout << "Didn't get expected timeout in vkWaitForFences, exiting\n"; + exit(-1); + } + + // Set the event from the CPU and wait for the fence. + // This should succeed since we set the event + device->setEvent(event.get()); + do + { + result = device->waitForFences(fence.get(), true, vk::su::FenceTimeout); + } while (result == vk::Result::eTimeout); + assert(result == vk::Result::eSuccess); + + commandBuffers[0]->reset({}); + device->resetFences(fence.get()); + device->resetEvent(event.get()); + + // Now set the event from the GPU and wait on the CPU + commandBuffers[0]->begin(vk::CommandBufferBeginInfo()); + commandBuffers[0]->setEvent(event.get(), vk::PipelineStageFlagBits::eBottomOfPipe); + commandBuffers[0]->end(); + + // Look for the event on the CPU. It should be RESET since we haven't sent the command buffer yet. + result = device->getEventStatus(event.get()); + assert(result == vk::Result::eEventReset); + + // Send the command buffer and loop waiting for the event + graphicsQueue.submit(submitInfo, fence.get()); + + int polls = 0; + do + { + result = device->getEventStatus(event.get()); + polls++; + } while (result != vk::Result::eEventSet); + printf("%d polls to find the event set\n", polls); + + do + { + result = device->waitForFences(fence.get(), true, vk::su::FenceTimeout); + } while (result == vk::Result::eTimeout); + assert(result == vk::Result::eSuccess); + + /* VULKAN_KEY_END */ + } + catch (vk::SystemError err) + { + std::cout << "vk::SystemError: " << err.what() << std::endl; + exit(-1); + } + catch (std::runtime_error err) + { + std::cout << "std::runtime_error: " << err.what() << std::endl; + exit(-1); + } + catch (...) + { + std::cout << "unknown error\n"; + exit(-1); + } + return 0; +} diff --git a/samples/utils/utils.cpp b/samples/utils/utils.cpp index a1b7de2..e7f9a5c 100644 --- a/samples/utils/utils.cpp +++ b/samples/utils/utils.cpp @@ -66,10 +66,10 @@ namespace vk return instance->createDebugReportCallbackEXTUnique(vk::DebugReportCallbackCreateInfoEXT(flags, &vk::su::debugReportCallback)); } - vk::UniqueDescriptorPool createDescriptorPool(vk::UniqueDevice &device, bool textured) + vk::UniqueDescriptorPool createDescriptorPool(vk::UniqueDevice &device, vk::DescriptorType descriptorType, bool textured) { std::vector poolSizes; - poolSizes.push_back(vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1)); + poolSizes.push_back(vk::DescriptorPoolSize(descriptorType, 1)); if (textured) { poolSizes.push_back(vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, 1)); @@ -78,10 +78,10 @@ namespace vk return device->createDescriptorPoolUnique(descriptorPoolCreateInfo); } - vk::UniqueDescriptorSetLayout createDescriptorSetLayout(vk::UniqueDevice &device, bool textured) + vk::UniqueDescriptorSetLayout createDescriptorSetLayout(vk::UniqueDevice &device, vk::DescriptorType descriptorType, bool textured) { std::vector bindings; - bindings.push_back(vk::DescriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex)); + bindings.push_back(vk::DescriptorSetLayoutBinding(0, descriptorType, 1, vk::ShaderStageFlagBits::eVertex)); if (textured) { bindings.push_back(vk::DescriptorSetLayoutBinding(1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment)); @@ -392,10 +392,10 @@ namespace vk ; } - void updateDescriptorSets(vk::UniqueDevice &device, vk::UniqueDescriptorSet &descriptorSet, vk::DescriptorBufferInfo const* descriptorBufferInfo, vk::DescriptorImageInfo const* descriptorImageInfo) + void updateDescriptorSets(vk::UniqueDevice &device, vk::UniqueDescriptorSet &descriptorSet, vk::DescriptorType descriptorType, vk::DescriptorBufferInfo const* descriptorBufferInfo, vk::DescriptorImageInfo const* descriptorImageInfo) { std::vector writeDescriptorSets; - writeDescriptorSets.push_back(vk::WriteDescriptorSet(descriptorSet.get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, descriptorBufferInfo, nullptr)); + writeDescriptorSets.push_back(vk::WriteDescriptorSet(descriptorSet.get(), 0, 0, 1, descriptorType, nullptr, descriptorBufferInfo, nullptr)); if (descriptorImageInfo) { writeDescriptorSets.push_back(vk::WriteDescriptorSet(descriptorSet.get(), 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, descriptorImageInfo, nullptr, nullptr)); diff --git a/samples/utils/utils.hpp b/samples/utils/utils.hpp index 27c95bd..82a0a11 100644 --- a/samples/utils/utils.hpp +++ b/samples/utils/utils.hpp @@ -91,10 +91,22 @@ namespace vk } template - void copyToDevice(vk::UniqueDevice &device, vk::UniqueDeviceMemory &memory, T const* pData, size_t count) + void copyToDevice(vk::UniqueDevice &device, vk::UniqueDeviceMemory &memory, T const* pData, size_t count, size_t stride = sizeof(T)) { - uint8_t* deviceData = static_cast(device->mapMemory(memory.get(), 0, count * sizeof(T))); - memcpy(deviceData, pData, count * sizeof(T)); + assert(sizeof(T) <= stride); + uint8_t* deviceData = static_cast(device->mapMemory(memory.get(), 0, count * stride)); + if (stride == sizeof(T)) + { + memcpy(deviceData, pData, count * sizeof(T)); + } + else + { + for (size_t i = 0; i < count; i++) + { + memcpy(deviceData, &pData[i], sizeof(T)); + deviceData += stride; + } + } device->unmapMemory(memory.get()); } @@ -113,8 +125,8 @@ namespace vk vk::UniqueDeviceMemory allocateMemory(vk::UniqueDevice &device, vk::PhysicalDeviceMemoryProperties const& memoryProperties, vk::MemoryRequirements const& memoryRequirements, vk::MemoryPropertyFlags memoryPropertyFlags); vk::UniqueCommandPool createCommandPool(vk::UniqueDevice &device, uint32_t queueFamilyIndex); vk::UniqueDebugReportCallbackEXT createDebugReportCallback(vk::UniqueInstance &instance); - vk::UniqueDescriptorPool createDescriptorPool(vk::UniqueDevice &device, bool textured = false); - vk::UniqueDescriptorSetLayout createDescriptorSetLayout(vk::UniqueDevice &device, bool textured = false); + vk::UniqueDescriptorPool createDescriptorPool(vk::UniqueDevice &device, vk::DescriptorType descriptorType = vk::DescriptorType::eUniformBuffer, bool textured = false); + vk::UniqueDescriptorSetLayout createDescriptorSetLayout(vk::UniqueDevice &device, vk::DescriptorType = vk::DescriptorType::eUniformBuffer, bool textured = false); vk::UniqueDevice createDevice(vk::PhysicalDevice physicalDevice, uint32_t queueFamilyIndex, std::vector const& extensions = {}); std::vector createFramebuffers(vk::UniqueDevice &device, vk::UniqueRenderPass &renderPass, std::vector const& imageViews, vk::UniqueImageView &depthImageView, vk::Extent2D const& extent); vk::UniquePipeline createGraphicsPipeline(vk::UniqueDevice &device, vk::UniquePipelineCache &pipelineCache, vk::UniqueShaderModule &vertexShaderModule, vk::UniqueShaderModule &fragmentShaderModule, uint32_t vertexStride, vk::UniquePipelineLayout &pipelineLayout, vk::UniqueRenderPass &renderPass); @@ -129,7 +141,7 @@ namespace vk vk::Format pickColorFormat(std::vector const& formats); void setImageLayout(vk::UniqueCommandBuffer &commandBuffer, vk::Image image, vk::ImageAspectFlags aspectFlags, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout, vk::PipelineStageFlags sourceStageMask, vk::PipelineStageFlags destinationStageMask); void submitAndWait(vk::UniqueDevice &device, vk::Queue queue, vk::UniqueCommandBuffer &commandBuffer); - void updateDescriptorSets(vk::UniqueDevice &device, vk::UniqueDescriptorSet &descriptorSet, vk::DescriptorBufferInfo const* descriptorBufferInfo, vk::DescriptorImageInfo const* descriptorImageInfo = nullptr); + void updateDescriptorSets(vk::UniqueDevice &device, vk::UniqueDescriptorSet &descriptorSet, vk::DescriptorType descriptorType, vk::DescriptorBufferInfo const* descriptorBufferInfo, vk::DescriptorImageInfo const* descriptorImageInfo = nullptr); #if defined(VK_USE_PLATFORM_WIN32_KHR) HWND initializeWindow(std::string const& className, std::string const& windowName, LONG width, LONG height);