From 2d8483e06f4ed17833fbae2f43cbc439c17ebcd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20S=C3=BC=C3=9Fenbach?= Date: Tue, 26 Mar 2019 12:24:36 +0100 Subject: [PATCH] Add samples 16_Vulkan_1_1, CopyBlitImage, CreateDebugReportCallback, DrawTexturedCube (#304) + slightly adjust some other samples. --- .../06_InitDepthBuffer/06_InitDepthBuffer.cpp | 15 +- .../09_InitDescriptorSet.cpp | 9 +- samples/09_InitDescriptorSet/CMakeLists.txt | 2 + .../10_InitRenderPass/10_InitRenderPass.cpp | 15 +- samples/11_InitShaders/11_InitShaders.cpp | 4 +- .../12_InitFrameBuffers.cpp | 34 +- .../13_InitVertexBuffer.cpp | 32 +- samples/14_InitPipeline/14_InitPipeline.cpp | 19 +- samples/15_DrawCube/15_DrawCube.cpp | 66 ++-- samples/16_Vulkan_1_1/16_Vulkan_1_1.cpp | 108 ++++++ samples/16_Vulkan_1_1/CMakeLists.txt | 39 +++ samples/CopyBlitImage/CMakeLists.txt | 39 +++ samples/CopyBlitImage/CopyBlitImage.cpp | 183 ++++++++++ .../CreateDebugReportCallback/CMakeLists.txt | 37 ++ .../CreateDebugReportCallback.cpp | 129 +++++++ samples/DrawTexturedCube/CMakeLists.txt | 44 +++ samples/DrawTexturedCube/DrawTexturedCube.cpp | 256 ++++++++++++++ samples/utils/geometries.hpp | 4 +- samples/utils/shaders.cpp | 2 +- samples/utils/shaders.hpp | 12 +- samples/utils/utils.cpp | 325 +++++++++++++----- samples/utils/utils.hpp | 72 +++- 22 files changed, 1209 insertions(+), 237 deletions(-) create mode 100644 samples/16_Vulkan_1_1/16_Vulkan_1_1.cpp create mode 100644 samples/16_Vulkan_1_1/CMakeLists.txt create mode 100644 samples/CopyBlitImage/CMakeLists.txt create mode 100644 samples/CopyBlitImage/CopyBlitImage.cpp create mode 100644 samples/CreateDebugReportCallback/CMakeLists.txt create mode 100644 samples/CreateDebugReportCallback/CreateDebugReportCallback.cpp create mode 100644 samples/DrawTexturedCube/CMakeLists.txt create mode 100644 samples/DrawTexturedCube/DrawTexturedCube.cpp diff --git a/samples/06_InitDepthBuffer/06_InitDepthBuffer.cpp b/samples/06_InitDepthBuffer/06_InitDepthBuffer.cpp index 3178ff9..2c35198 100644 --- a/samples/06_InitDepthBuffer/06_InitDepthBuffer.cpp +++ b/samples/06_InitDepthBuffer/06_InitDepthBuffer.cpp @@ -34,16 +34,9 @@ int main(int /*argc*/, char ** /*argv*/) std::vector physicalDevices = instance->enumeratePhysicalDevices(); assert(!physicalDevices.empty()); - uint32_t width = 500; - uint32_t height = 500; -#if defined(VK_USE_PLATFORM_WIN32_KHR) - HWND window = vk::su::initializeWindow(AppName, AppName, width, height); - vk::UniqueSurfaceKHR surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR({}, GetModuleHandle(nullptr), window)); -#else -#pragma error "unhandled platform" -#endif + vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500)); - std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surface); + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.surface); vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); /* VULKAN_HPP_KEY_START */ @@ -64,7 +57,7 @@ int main(int /*argc*/, char ** /*argv*/) { throw std::runtime_error("DepthStencilAttachment is not supported for D16Unorm depth format."); } - vk::ImageCreateInfo imageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, depthFormat, vk::Extent3D(width, height, 1), 1, 1, vk::SampleCountFlagBits::e1, tiling, vk::ImageUsageFlagBits::eDepthStencilAttachment); + vk::ImageCreateInfo imageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, depthFormat, vk::Extent3D(surfaceData.extent, 1), 1, 1, vk::SampleCountFlagBits::e1, tiling, vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::UniqueImage depthImage = device->createImageUnique(imageCreateInfo); vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); @@ -92,7 +85,7 @@ int main(int /*argc*/, char ** /*argv*/) /* VULKAN_HPP_KEY_END */ #if defined(VK_USE_PLATFORM_WIN32_KHR) - DestroyWindow(window); + DestroyWindow(surfaceData.window); #else #pragma error "unhandled platform" #endif diff --git a/samples/09_InitDescriptorSet/09_InitDescriptorSet.cpp b/samples/09_InitDescriptorSet/09_InitDescriptorSet.cpp index 08e1116..1df411b 100644 --- a/samples/09_InitDescriptorSet/09_InitDescriptorSet.cpp +++ b/samples/09_InitDescriptorSet/09_InitDescriptorSet.cpp @@ -15,6 +15,7 @@ // VulkanHpp Samples : 09_InitDescriptorSet // Initialize a descriptor set +#include "../utils/math.hpp" #include "../utils/utils.hpp" #include "vulkan/vulkan.hpp" #include @@ -40,10 +41,8 @@ int main(int /*argc*/, char ** /*argv*/) vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], vk::su::findGraphicsQueueFamilyIndex(physicalDevices[0].getQueueFamilyProperties())); - vk::UniqueBuffer buffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer)); - vk::UniqueDeviceMemory deviceMemory = vk::su::allocateMemory(device, physicalDevices[0].getMemoryProperties(), device->getBufferMemoryRequirements(buffer.get()), vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); - - device->bindBufferMemory(buffer.get(), deviceMemory.get(), 0); + 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); @@ -56,7 +55,7 @@ int main(int /*argc*/, char ** /*argv*/) // allocate a descriptor set std::vector descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 1, &descriptorSetLayout.get())); - vk::DescriptorBufferInfo descriptorBufferInfo(buffer.get(), 0, sizeof(glm::mat4x4)); + vk::DescriptorBufferInfo descriptorBufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); device->updateDescriptorSets(vk::WriteDescriptorSet(descriptorSets[0].get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &descriptorBufferInfo), {}); /* VULKAN_HPP_KEY_END */ diff --git a/samples/09_InitDescriptorSet/CMakeLists.txt b/samples/09_InitDescriptorSet/CMakeLists.txt index 5988249..b73ff37 100644 --- a/samples/09_InitDescriptorSet/CMakeLists.txt +++ b/samples/09_InitDescriptorSet/CMakeLists.txt @@ -17,11 +17,13 @@ cmake_minimum_required(VERSION 3.2) project(09_InitDescriptorSet) set(HEADERS + ../utils/math.hpp ../utils/utils.hpp ) set(SOURCES 09_InitDescriptorSet.cpp + ../utils/math.cpp ../utils/utils.cpp ) diff --git a/samples/10_InitRenderPass/10_InitRenderPass.cpp b/samples/10_InitRenderPass/10_InitRenderPass.cpp index a2bc07f..ff07bee 100644 --- a/samples/10_InitRenderPass/10_InitRenderPass.cpp +++ b/samples/10_InitRenderPass/10_InitRenderPass.cpp @@ -38,19 +38,12 @@ int main(int /*argc*/, char ** /*argv*/) std::vector physicalDevices = instance->enumeratePhysicalDevices(); assert(!physicalDevices.empty()); - uint32_t width = 64; - uint32_t height = 64; -#if defined(VK_USE_PLATFORM_WIN32_KHR) - HWND window = vk::su::initializeWindow(AppName, AppName, width, height); - vk::UniqueSurfaceKHR surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR({}, GetModuleHandle(nullptr), window)); -#else -#pragma error "unhandled platform" -#endif + vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(64, 64)); - std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surface); + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.surface); vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); - vk::Format colorFormat = vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())); + vk::Format colorFormat = vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surfaceData.surface.get())); vk::Format depthFormat = vk::Format::eD16Unorm; /* VULKAN_HPP_KEY_START */ @@ -73,7 +66,7 @@ int main(int /*argc*/, char ** /*argv*/) /* VULKAN_HPP_KEY_END */ #if defined(VK_USE_PLATFORM_WIN32_KHR) - DestroyWindow(window); + DestroyWindow(surfaceData.window); #else #pragma error "unhandled platform" #endif diff --git a/samples/11_InitShaders/11_InitShaders.cpp b/samples/11_InitShaders/11_InitShaders.cpp index 09f1464..3ef52d4 100644 --- a/samples/11_InitShaders/11_InitShaders.cpp +++ b/samples/11_InitShaders/11_InitShaders.cpp @@ -43,14 +43,14 @@ int main(int /*argc*/, char ** /*argv*/) glslang::InitializeProcess(); std::vector vertexShaderSPV; - bool ok = vk::su::GLSLtoSPV(vk::ShaderStageFlagBits::eVertex, vertexShaderText, vertexShaderSPV); + bool ok = vk::su::GLSLtoSPV(vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C, vertexShaderSPV); assert(ok); vk::ShaderModuleCreateInfo vertexShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), vertexShaderSPV.size() * sizeof(unsigned int), vertexShaderSPV.data()); vk::UniqueShaderModule vertexShaderModule = device->createShaderModuleUnique(vertexShaderModuleCreateInfo); std::vector fragmentShaderSPV; - ok = vk::su::GLSLtoSPV(vk::ShaderStageFlagBits::eFragment, fragmentShaderText, fragmentShaderSPV); + ok = vk::su::GLSLtoSPV(vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C, fragmentShaderSPV); assert(ok); vk::ShaderModuleCreateInfo fragmentShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), fragmentShaderSPV.size() * sizeof(unsigned int), fragmentShaderSPV.data()); diff --git a/samples/12_InitFrameBuffers/12_InitFrameBuffers.cpp b/samples/12_InitFrameBuffers/12_InitFrameBuffers.cpp index 9510ed1..35e2e47 100644 --- a/samples/12_InitFrameBuffers/12_InitFrameBuffers.cpp +++ b/samples/12_InitFrameBuffers/12_InitFrameBuffers.cpp @@ -34,41 +34,29 @@ int main(int /*argc*/, char ** /*argv*/) std::vector physicalDevices = instance->enumeratePhysicalDevices(); assert(!physicalDevices.empty()); - uint32_t width = 64; - uint32_t height = 64; -#if defined(VK_USE_PLATFORM_WIN32_KHR) - HWND window = vk::su::initializeWindow(AppName, AppName, width, height); - vk::UniqueSurfaceKHR surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR({}, GetModuleHandle(nullptr), window)); -#else -#pragma error "unhandled platform" -#endif + vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(64, 64)); - std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surface); + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.surface); vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); - vk::Format colorFormat = vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())); - vk::UniqueSwapchainKHR swapChain = vk::su::createSwapChain(physicalDevices[0], surface, device, width, height, colorFormat, graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); - std::vector swapChainImageViews = vk::su::createSwapChainImageViews(device, swapChain, colorFormat); + vk::su::SwapChainData swapChainData(physicalDevices[0], device, surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc + , graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); - vk::Format depthFormat = vk::Format::eD16Unorm; - vk::UniqueImage depthImage = vk::su::createImage(device, depthFormat, width, height); - vk::UniqueDeviceMemory depthMemory = vk::su::allocateMemory(device, physicalDevices[0].getMemoryProperties(), device->getImageMemoryRequirements(depthImage.get()), vk::MemoryPropertyFlagBits::eDeviceLocal); - device->bindImageMemory(depthImage.get(), depthMemory.get(), 0); - vk::UniqueImageView depthViewImage = vk::su::createImageView(device, depthImage, depthFormat); + vk::su::DepthBufferData depthBufferData(physicalDevices[0], device, vk::Format::eD16Unorm, surfaceData.extent); - vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, colorFormat, depthFormat); + vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, swapChainData.colorFormat, depthBufferData.format); /* VULKAN_KEY_START */ vk::ImageView attachments[2]; - attachments[1] = depthViewImage.get(); + attachments[1] = depthBufferData.imageView.get(); std::vector framebuffers; - framebuffers.reserve(swapChainImageViews.size()); - for (auto const& view : swapChainImageViews) + framebuffers.reserve(swapChainData.imageViews.size()); + for (auto const& view : swapChainData.imageViews) { attachments[0] = view.get(); - framebuffers.push_back(device->createFramebufferUnique(vk::FramebufferCreateInfo(vk::FramebufferCreateFlags(), renderPass.get(), 2, attachments, width, height, 1))); + framebuffers.push_back(device->createFramebufferUnique(vk::FramebufferCreateInfo(vk::FramebufferCreateFlags(), renderPass.get(), 2, attachments, surfaceData.extent.width, surfaceData.extent.height, 1))); } // Note: No need to explicitly destroy the Framebuffers, as the destroy functions are called by the destructor of the UniqueFramebuffer on leaving this scope. @@ -76,7 +64,7 @@ int main(int /*argc*/, char ** /*argv*/) /* VULKAN_KEY_END */ #if defined(VK_USE_PLATFORM_WIN32_KHR) - DestroyWindow(window); + DestroyWindow(surfaceData.window); #else #pragma error "unhandled platform" #endif diff --git a/samples/13_InitVertexBuffer/13_InitVertexBuffer.cpp b/samples/13_InitVertexBuffer/13_InitVertexBuffer.cpp index 85c5858..7e1976c 100644 --- a/samples/13_InitVertexBuffer/13_InitVertexBuffer.cpp +++ b/samples/13_InitVertexBuffer/13_InitVertexBuffer.cpp @@ -35,16 +35,9 @@ int main(int /*argc*/, char ** /*argv*/) std::vector physicalDevices = instance->enumeratePhysicalDevices(); assert(!physicalDevices.empty()); - uint32_t width = 64; - uint32_t height = 64; -#if defined(VK_USE_PLATFORM_WIN32_KHR) - HWND window = vk::su::initializeWindow(AppName, AppName, width, height); - vk::UniqueSurfaceKHR surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR({}, GetModuleHandle(nullptr), window)); -#else -#pragma error "unhandled platform" -#endif + vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(64, 64)); - std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surface); + 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); @@ -52,19 +45,14 @@ int main(int /*argc*/, char ** /*argv*/) vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); - vk::Format colorFormat = vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())); - vk::UniqueSwapchainKHR swapChain = vk::su::createSwapChain(physicalDevices[0], surface, device, width, height, colorFormat, graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); - std::vector swapChainImageViews = vk::su::createSwapChainImageViews(device, swapChain, colorFormat); + vk::su::SwapChainData swapChainData(physicalDevices[0], device, surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc + , graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); - vk::Format depthFormat = vk::Format::eD16Unorm; - vk::UniqueImage depthImage = vk::su::createImage(device, depthFormat, width, height); - vk::UniqueDeviceMemory depthMemory = vk::su::allocateMemory(device, physicalDevices[0].getMemoryProperties(), device->getImageMemoryRequirements(depthImage.get()), vk::MemoryPropertyFlagBits::eDeviceLocal); - device->bindImageMemory(depthImage.get(), depthMemory.get(), 0); - vk::UniqueImageView depthViewImage = vk::su::createImageView(device, depthImage, depthFormat); + vk::su::DepthBufferData depthBufferData(physicalDevices[0], device, vk::Format::eD16Unorm, surfaceData.extent); - vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, colorFormat, depthFormat); + vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, swapChainData.colorFormat, depthBufferData.format); - std::vector framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainImageViews, depthViewImage, width, height); + std::vector framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); /* VULKAN_KEY_START */ @@ -85,7 +73,7 @@ int main(int /*argc*/, char ** /*argv*/) device->bindBufferMemory(vertexBuffer.get(), deviceMemory.get(), 0); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo(vk::SemaphoreCreateFlags())); - vk::ResultValue currentBuffer = device->acquireNextImageKHR(swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); + 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()); @@ -95,7 +83,7 @@ int main(int /*argc*/, char ** /*argv*/) commandBuffers[0]->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags())); - vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), vk::Extent2D(width, height)), 2, clearValues); + 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); VkDeviceSize offset = 0; @@ -111,7 +99,7 @@ int main(int /*argc*/, char ** /*argv*/) /* VULKAN_KEY_END */ #if defined(VK_USE_PLATFORM_WIN32_KHR) - DestroyWindow(window); + DestroyWindow(surfaceData.window); #else #pragma error "unhandled platform" #endif diff --git a/samples/14_InitPipeline/14_InitPipeline.cpp b/samples/14_InitPipeline/14_InitPipeline.cpp index 37bdb80..74f5d35 100644 --- a/samples/14_InitPipeline/14_InitPipeline.cpp +++ b/samples/14_InitPipeline/14_InitPipeline.cpp @@ -39,26 +39,19 @@ int main(int /*argc*/, char ** /*argv*/) assert(!physicalDevices.empty()); vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); - uint32_t width = 500; - uint32_t height = 500; -#if defined(VK_USE_PLATFORM_WIN32_KHR) - HWND window = vk::su::initializeWindow(AppName, AppName, width, height); - vk::UniqueSurfaceKHR surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR({}, GetModuleHandle(nullptr), window)); -#else -#pragma error "unhandled platform" -#endif + vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500)); - std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surface); + std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.surface); vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); - vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())), vk::Format::eD16Unorm); + vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surfaceData.surface.get())), vk::Format::eD16Unorm); vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device); vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); glslang::InitializeProcess(); - vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText); - vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText); + 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(); /* VULKAN_KEY_START */ @@ -166,7 +159,7 @@ int main(int /*argc*/, char ** /*argv*/) /* VULKAN_KEY_END */ #if defined(VK_USE_PLATFORM_WIN32_KHR) - DestroyWindow(window); + DestroyWindow(surfaceData.window); #else #pragma error "unhandled platform" #endif diff --git a/samples/15_DrawCube/15_DrawCube.cpp b/samples/15_DrawCube/15_DrawCube.cpp index 9ad1bd7..167dab8 100644 --- a/samples/15_DrawCube/15_DrawCube.cpp +++ b/samples/15_DrawCube/15_DrawCube.cpp @@ -39,16 +39,9 @@ int main(int /*argc*/, char ** /*argv*/) assert(!physicalDevices.empty()); vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); - uint32_t width = 500; - uint32_t height = 500; -#if defined(VK_USE_PLATFORM_WIN32_KHR) - HWND window = vk::su::initializeWindow(AppName, AppName, width, height); - vk::UniqueSurfaceKHR surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR({}, GetModuleHandle(nullptr), window)); -#else -#pragma error "unhandled platform" -#endif + vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500)); - std::pair graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surface); + 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); @@ -57,45 +50,34 @@ int main(int /*argc*/, char ** /*argv*/) vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); - vk::Format colorFormat = vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surface.get())); - vk::UniqueSwapchainKHR swapChain = vk::su::createSwapChain(physicalDevices[0], surface, device, width, height, colorFormat, graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); - std::vector swapChainImageViews = vk::su::createSwapChainImageViews(device, swapChain, colorFormat); + vk::su::SwapChainData swapChainData(physicalDevices[0], device, surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc + , graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); - vk::Format depthFormat = vk::Format::eD16Unorm; - vk::UniqueImage depthImage = vk::su::createImage(device, depthFormat, width, height); - vk::UniqueDeviceMemory depthMemory = vk::su::allocateMemory(device, memoryProperties, device->getImageMemoryRequirements(depthImage.get()), vk::MemoryPropertyFlagBits::eDeviceLocal); - device->bindImageMemory(depthImage.get(), depthMemory.get(), 0); - vk::UniqueImageView depthViewImage = vk::su::createImageView(device, depthImage, depthFormat); + vk::su::DepthBufferData depthBufferData(physicalDevices[0], device, vk::Format::eD16Unorm, surfaceData.extent); - glm::mat4x4 mvpc = vk::su::createModelViewProjectionClipMatrix(); - vk::UniqueBuffer uniformBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(mvpc), vk::BufferUsageFlagBits::eUniformBuffer)); - vk::UniqueDeviceMemory uniformMemory = vk::su::allocateMemory(device, physicalDevices[0].getMemoryProperties(), device->getBufferMemoryRequirements(uniformBuffer.get()), vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); - vk::su::copyToDevice(device, uniformMemory, mvpc); - device->bindBufferMemory(uniformBuffer.get(), uniformMemory.get(), 0); + 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); 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(surface.get())), vk::Format::eD16Unorm); + 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); - vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText); + 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, swapChainImageViews, depthViewImage, width, height); + std::vector framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); - vk::UniqueBuffer vertexBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(coloredCubeData), vk::BufferUsageFlagBits::eVertexBuffer)); - vk::MemoryRequirements memoryRequirements = device->getBufferMemoryRequirements(vertexBuffer.get()); - vk::UniqueDeviceMemory vertexDeviceMemory = vk::su::allocateMemory(device, memoryProperties, memoryRequirements, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); - vk::su::copyToDevice(device, vertexDeviceMemory, coloredCubeData, sizeof(coloredCubeData) / sizeof(coloredCubeData[0])); - device->bindBufferMemory(vertexBuffer.get(), vertexDeviceMemory.get(), 0); + vk::su::BufferData vertexBufferData(physicalDevices[0], device, sizeof(coloredCubeData), vk::BufferUsageFlagBits::eVertexBuffer); + vk::su::copyToDevice(device, vertexBufferData.deviceMemory, coloredCubeData, sizeof(coloredCubeData) / sizeof(coloredCubeData[0])); - vk::DescriptorPoolSize poolSize(vk::DescriptorType::eUniformBuffer, 1); - vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 1, &poolSize)); + vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device); std::vector descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 1, &descriptorSetLayout.get())); - vk::DescriptorBufferInfo descriptorBufferInfo(uniformBuffer.get(), 0, sizeof(mvpc)); - device->updateDescriptorSets(vk::WriteDescriptorSet(descriptorSets[0].get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &descriptorBufferInfo), nullptr); + + vk::DescriptorBufferInfo descriptorBufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); + vk::su::updateDescriptorSets(device, descriptorSets[0], &descriptorBufferInfo); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, vertexShaderModule, fragmentShaderModule, sizeof(coloredCubeData[0]), pipelineLayout, renderPass); @@ -104,7 +86,7 @@ int main(int /*argc*/, char ** /*argv*/) // Get the index of the next available swapchain image: vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); - vk::ResultValue currentBuffer = device->acquireNextImageKHR(swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); + 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()); @@ -113,19 +95,19 @@ int main(int /*argc*/, char ** /*argv*/) 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), vk::Extent2D(width, height)), 2, clearValues); + 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()); commandBuffers[0]->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSets[0].get(), nullptr); - vk::Viewport viewport(0.0f, 0.0f, static_cast(width), static_cast(height), 0.0f, 1.0f); + 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), vk::Extent2D(width, height)); + vk::Rect2D scissor(vk::Offset2D(0, 0), surfaceData.extent); commandBuffers[0]->setScissor(0, scissor); vk::DeviceSize offset = 0; - commandBuffers[0]->bindVertexBuffers(0, vertexBuffer.get(), offset); + commandBuffers[0]->bindVertexBuffers(0, vertexBufferData.buffer.get(), offset); commandBuffers[0]->draw(12 * 3, 1, 0, 0); commandBuffers[0]->endRenderPass(); @@ -140,14 +122,14 @@ int main(int /*argc*/, char ** /*argv*/) while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) ; - presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChain.get(), ¤tBuffer.value)); + 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(window); + DestroyWindow(surfaceData.window); #else #pragma error "unhandled platform" #endif diff --git a/samples/16_Vulkan_1_1/16_Vulkan_1_1.cpp b/samples/16_Vulkan_1_1/16_Vulkan_1_1.cpp new file mode 100644 index 0000000..2c7b456 --- /dev/null +++ b/samples/16_Vulkan_1_1/16_Vulkan_1_1.cpp @@ -0,0 +1,108 @@ +// 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 : 16_Vulkan_1_1 +// Determine if the current system can use Vulkan 1.1 API features + +#include "../utils/utils.hpp" +#include "vulkan/vulkan.hpp" + +static char const* AppName = "16_Vulkan_1_1"; +static char const* EngineName = "Vulkan.hpp"; + +int main(int /*argc*/, char ** /*argv*/) +{ + try + { + /* VULKAN_KEY_START */ + + // Keep track of the major/minor version we can actually use + uint16_t usingMajorVersion = 1; + uint16_t usingMinorVersion = 0; + std::string usingVersionString = ""; + + // Set the desired version we want + uint16_t desiredMajorVersion = 1; + uint16_t desiredMinorVersion = 1; + uint32_t desiredVersion = VK_MAKE_VERSION(desiredMajorVersion, desiredMinorVersion, 0); + std::string desiredVersionString = ""; + desiredVersionString += std::to_string(desiredMajorVersion); + desiredVersionString += "."; + desiredVersionString += std::to_string(desiredMinorVersion); + + // Determine what API version is available + uint32_t apiVersion = vk::enumerateInstanceVersion(); + + // Translate the version into major/minor for easier comparison + uint32_t loader_major_version = VK_VERSION_MAJOR(apiVersion); + uint32_t loader_minor_version = VK_VERSION_MINOR(apiVersion); + std::cout << "Loader/Runtime support detected for Vulkan " << loader_major_version << "." << loader_minor_version << "\n"; + + // Check current version against what we want to run + if (loader_major_version > desiredMajorVersion || + (loader_major_version == desiredMajorVersion && loader_minor_version >= desiredMinorVersion)) + { + // Create the instance + vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions(), desiredVersion); +#if !defined(NDEBUG) + vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance); +#endif + + // Get the list of physical devices + std::vector physicalDevices = instance->enumeratePhysicalDevices(); + + // Go through the list of physical devices and select only those that are capable of running the API version we want. + std::vector desiredPhysicalDevices; + std::copy_if(physicalDevices.begin(), physicalDevices.end(), std::back_inserter(desiredPhysicalDevices), [desiredVersion](vk::PhysicalDevice const& pd) { return pd.getProperties().apiVersion >= desiredVersion; }); + + // If we have something in the desired version physical device list, we're good + if (desiredPhysicalDevices.size() > 0) + { + usingMajorVersion = desiredMajorVersion; + usingMinorVersion = desiredMinorVersion; + } + } + + usingVersionString += std::to_string(usingMajorVersion); + usingVersionString += "."; + usingVersionString += std::to_string(usingMinorVersion); + + if (usingMinorVersion < desiredMinorVersion) + { + std::cout << "Determined that this system can only use Vulkan API version " << usingVersionString << " instead of desired version " << desiredVersionString << std::endl; + } + else + { + std::cout << "Determined that this system can run desired Vulkan API version " << desiredVersionString << std::endl; + } + + /* 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/16_Vulkan_1_1/CMakeLists.txt b/samples/16_Vulkan_1_1/CMakeLists.txt new file mode 100644 index 0000000..924707c --- /dev/null +++ b/samples/16_Vulkan_1_1/CMakeLists.txt @@ -0,0 +1,39 @@ +# 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(16_Vulkan_1_1) + +set(HEADERS + ../utils/utils.hpp +) + +set(SOURCES + 16_Vulkan_1_1.cpp + ../utils/utils.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(16_Vulkan_1_1 + ${HEADERS} + ${SOURCES} +) + +set_target_properties(16_Vulkan_1_1 PROPERTIES FOLDER "Samples") +target_include_directories(16_Vulkan_1_1 PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(16_Vulkan_1_1 PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/CopyBlitImage/CMakeLists.txt b/samples/CopyBlitImage/CMakeLists.txt new file mode 100644 index 0000000..5bc473c --- /dev/null +++ b/samples/CopyBlitImage/CMakeLists.txt @@ -0,0 +1,39 @@ +# 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(CopyBlitImage) + +set(HEADERS + ../utils/utils.hpp +) + +set(SOURCES + CopyBlitImage.cpp + ../utils/utils.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(CopyBlitImage + ${HEADERS} + ${SOURCES} +) + +set_target_properties(CopyBlitImage PROPERTIES FOLDER "Samples") +target_include_directories(CopyBlitImage PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(CopyBlitImage PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/CopyBlitImage/CopyBlitImage.cpp b/samples/CopyBlitImage/CopyBlitImage.cpp new file mode 100644 index 0000000..920ab16 --- /dev/null +++ b/samples/CopyBlitImage/CopyBlitImage.cpp @@ -0,0 +1,183 @@ +// 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 : CopyBlitImage +// Draw a cube + +#include "../utils/utils.hpp" +#include "vulkan/vulkan.hpp" + +static char const* AppName = "CopyBlitImage"; +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(640, 640)); + + vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevices[0].getSurfaceCapabilitiesKHR(surfaceData.surface.get()); + if (!(surfaceCapabilities.supportedUsageFlags & vk::ImageUsageFlagBits::eTransferDst)) + { + std::cout << "Surface cannot be destination of blit - abort \n"; + exit(-1); + } + + 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::eTransferDst + , graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); + + /* VULKAN_KEY_START */ + + vk::FormatProperties formatProperties = physicalDevices[0].getFormatProperties(swapChainData.colorFormat); + assert((formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eBlitSrc) && "Format cannot be used as transfer source"); + + vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); + + // Get the index of the next available swapchain image: + vk::ResultValue nextImage = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); + assert(nextImage.result == vk::Result::eSuccess); + assert(nextImage.value < swapChainData.images.size()); + uint32_t currentBuffer = nextImage.value; + + commandBuffers[0]->begin(vk::CommandBufferBeginInfo()); + vk::su::setImageLayout(commandBuffers[0], swapChainData.images[currentBuffer], vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, + vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer); + + // Create an image, map it, and write some values to the image + vk::ImageCreateInfo imageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, swapChainData.colorFormat, vk::Extent3D(surfaceData.extent, 1), 1, 1, vk::SampleCountFlagBits::e1, vk::ImageTiling::eLinear, vk::ImageUsageFlagBits::eTransferSrc); + vk::UniqueImage blitSourceImage = device->createImageUnique(imageCreateInfo); + + vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); + vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements(blitSourceImage.get()); + uint32_t memoryTypeIndex = vk::su::findMemoryType(memoryProperties, memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible); + + vk::UniqueDeviceMemory deviceMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); + device->bindImageMemory(blitSourceImage.get(), deviceMemory.get(), 0); + + vk::su::setImageLayout(commandBuffers[0], blitSourceImage.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral, + vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eHost); + + commandBuffers[0]->end(); + + /* Queue the command buffer for execution */ + vk::UniqueFence commandFence = device->createFenceUnique({}); + vk::PipelineStageFlags pipeStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput); + graphicsQueue.submit(vk::SubmitInfo(1, &imageAcquiredSemaphore.get(), &pipeStageFlags, 1, &commandBuffers[0].get()), commandFence.get()); + + /* Make sure command buffer is finished before mapping */ + while (device->waitForFences(commandFence.get(), true, vk::su::FenceTimeout) == vk::Result::eTimeout) + ; + + unsigned char* pImageMemory = static_cast(device->mapMemory(deviceMemory.get(), 0, memoryRequirements.size)); + + // Checkerboard of 8x8 pixel squares + for (uint32_t row = 0; row < surfaceData.extent.height; row++) + { + for (uint32_t col = 0; col < surfaceData.extent.width; col++) + { + unsigned char rgb = (((row & 0x8) == 0) ^ ((col & 0x8) == 0)) * 255; + pImageMemory[0] = rgb; + pImageMemory[1] = rgb; + pImageMemory[2] = rgb; + pImageMemory[3] = 255; + pImageMemory += 4; + } + } + + // Flush the mapped memory and then unmap it. Assume it isn't coherent since we didn't really confirm + device->flushMappedMemoryRanges(vk::MappedMemoryRange(deviceMemory.get(), 0, memoryRequirements.size)); + device->unmapMemory(deviceMemory.get()); + + commandBuffers[0]->reset({}); + commandBuffers[0]->begin(vk::CommandBufferBeginInfo()); + + // Intend to blit from this image, set the layout accordingly + vk::su::setImageLayout(commandBuffers[0], blitSourceImage.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eGeneral, vk::ImageLayout::eTransferSrcOptimal, + vk::PipelineStageFlagBits::eHost, vk::PipelineStageFlagBits::eTransfer); + + vk::Image blitDestinationImage = swapChainData.images[currentBuffer]; + + // Do a 32x32 blit to all of the dst image - should get big squares + vk::ImageSubresourceLayers imageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1); + vk::ImageBlit imageBlit(imageSubresourceLayers, { { vk::Offset3D(0, 0, 0), vk::Offset3D(32, 32, 1) } }, imageSubresourceLayers, { { vk::Offset3D(0, 0, 0), vk::Offset3D(surfaceData.extent.width, surfaceData.extent.height, 1) } }); + commandBuffers[0]->blitImage(blitSourceImage.get(), vk::ImageLayout::eTransferSrcOptimal, blitDestinationImage, vk::ImageLayout::eTransferDstOptimal, imageBlit, vk::Filter::eLinear); + + // Use a barrier to make sure the blit is finished before the copy starts + vk::ImageMemoryBarrier memoryBarrier(vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eMemoryRead, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eTransferDstOptimal, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, blitDestinationImage, vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); + commandBuffers[0]->pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlags(), nullptr, nullptr, memoryBarrier); + + // Do a image copy to part of the dst image - checks should stay small + vk::ImageCopy imageCopy(imageSubresourceLayers, vk::Offset3D(), imageSubresourceLayers, vk::Offset3D(256, 256, 0), vk::Extent3D(128, 128, 1)); + commandBuffers[0]->copyImage(blitSourceImage.get(), vk::ImageLayout::eTransferSrcOptimal, blitDestinationImage, vk::ImageLayout::eTransferDstOptimal, imageCopy); + + vk::ImageMemoryBarrier prePresentBarrier(vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eMemoryRead, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::ePresentSrcKHR, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, swapChainData.images[currentBuffer], vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); + commandBuffers[0]->pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTopOfPipe, vk::DependencyFlags(), nullptr, nullptr, prePresentBarrier); + commandBuffers[0]->end(); + + vk::UniqueFence drawFence = device->createFenceUnique({}); + graphicsQueue.submit(vk::SubmitInfo(0, nullptr, nullptr, 1, &commandBuffers[0].get()), drawFence.get()); + graphicsQueue.waitIdle(); + + /* Make sure command buffer is finished before presenting */ + while (device->waitForFences(drawFence.get(), true, vk::su::FenceTimeout) == vk::Result::eTimeout) + ; + + /* Now present the image in the window */ + presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), ¤tBuffer, nullptr)); + Sleep(1000); + + /* VULKAN_KEY_END */ + +#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/CreateDebugReportCallback/CMakeLists.txt b/samples/CreateDebugReportCallback/CMakeLists.txt new file mode 100644 index 0000000..0fb2b23 --- /dev/null +++ b/samples/CreateDebugReportCallback/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(CreateDebugReportCallback) + +set(HEADERS +) + +set(SOURCES + CreateDebugReportCallback.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(CreateDebugReportCallback + ${HEADERS} + ${SOURCES} +) + +set_target_properties(CreateDebugReportCallback PROPERTIES FOLDER "Samples") +target_include_directories(CreateDebugReportCallback PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(CreateDebugReportCallback PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/CreateDebugReportCallback/CreateDebugReportCallback.cpp b/samples/CreateDebugReportCallback/CreateDebugReportCallback.cpp new file mode 100644 index 0000000..3f0bb39 --- /dev/null +++ b/samples/CreateDebugReportCallback/CreateDebugReportCallback.cpp @@ -0,0 +1,129 @@ +// 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 : CreateDebugReportCallback +// Draw a cube + +#include "vulkan/vulkan.hpp" +#include +#include + +static char const* AppName = "CreateDebugReportCallback"; +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; +} + + +int main(int /*argc*/, char ** /*argv*/) +{ + try + { + /* VULKAN_KEY_START */ + + std::vector props = vk::enumerateInstanceExtensionProperties(); + + auto propsIterator = std::find_if(props.begin(), props.end(), [](vk::ExtensionProperties const& ep) { return strcmp(ep.extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0; }); + if (propsIterator == props.end()) + { + std::cout << "Something went very wrong, cannot find " << VK_EXT_DEBUG_REPORT_EXTENSION_NAME << " extension" << std::endl; + exit(1); + } + + vk::ApplicationInfo applicationInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_0); + const char *extensionName = VK_EXT_DEBUG_REPORT_EXTENSION_NAME; + vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo(vk::InstanceCreateFlags(), &applicationInfo, 0, nullptr, 1, &extensionName)); + + 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)); + + /* 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/DrawTexturedCube/CMakeLists.txt b/samples/DrawTexturedCube/CMakeLists.txt new file mode 100644 index 0000000..5204116 --- /dev/null +++ b/samples/DrawTexturedCube/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(DrawTexturedCube) + +set(HEADERS + ../utils/geometries.hpp + ../utils/math.hpp + ../utils/shaders.hpp + ../utils/utils.hpp +) + +set(SOURCES + DrawTexturedCube.cpp + ../utils/math.cpp + ../utils/shaders.cpp + ../utils/utils.cpp +) + +source_group(headers FILES ${HEADERS}) +source_group(sources FILES ${SOURCES}) + +add_executable(DrawTexturedCube + ${HEADERS} + ${SOURCES} +) + +set_target_properties(DrawTexturedCube PROPERTIES FOLDER "Samples") +target_include_directories(DrawTexturedCube PUBLIC ${CMAKE_SOURCE_DIR}/glslang) +target_link_libraries(DrawTexturedCube PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib" +) diff --git a/samples/DrawTexturedCube/DrawTexturedCube.cpp b/samples/DrawTexturedCube/DrawTexturedCube.cpp new file mode 100644 index 0000000..59737b5 --- /dev/null +++ b/samples/DrawTexturedCube/DrawTexturedCube.cpp @@ -0,0 +1,256 @@ +// 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 : DrawTexturedCube +// Draw a textured cube + +#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 = "DrawTexturedCube"; +static char const* EngineName = "Vulkan.hpp"; + +// vertex shader with (P)osition and (T)exCoord in and (T)exCoord out +const std::string vertexShaderText_PT_T = R"( +#version 400 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (std140, binding = 0) uniform buffer +{ + mat4 mvp; +} uniformBuffer; + +layout (location = 0) in vec4 pos; +layout (location = 1) in vec2 inTexCoord; + +layout (location = 0) out vec2 outTexCoord; + +void main() +{ + outTexCoord = inTexCoord; + gl_Position = uniformBuffer.mvp * pos; +} +)"; + +// fragment shader with (T)exCoord in and (C)olor out +const std::string fragmentShaderText_T_C = R"( +#version 400 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (binding = 1) uniform sampler2D tex; + +layout (location = 0) in vec2 inTexCoord; + +layout (location = 0) out vec4 outColor; + +void main() +{ + outColor = textureLod(tex, inTexCoord, 0.0f); +} +)"; + +struct VertexPT +{ + float x, y, z, w; // Position data + float u, v; // texture u,v +}; + +static const VertexPT texturedCubeData[] = +{ + // left face + { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f }, + { -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, + { -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, + { -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, + { -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f }, + { -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, + // front face + { -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, + { 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f }, + { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, + { -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, + { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, + { -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, + // top face + { -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, + { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, + { 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f }, + { -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, + { -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, + { 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f }, + // bottom face + { -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, + { -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, + { -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, + { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, + // right face + { 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, + { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, + { 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f }, + { 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, + // back face + { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, + { -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, + { -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, + { 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f }, +}; + +int main(int /*argc*/, char ** /*argv*/) +{ + try + { + bool textured = true; // this is a textured sample ! + + 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::PhysicalDeviceMemoryProperties memoryProperties = physicalDevices[0].getMemoryProperties(); + + 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::su::TextureData textureData(physicalDevices[0], device); + + commandBuffers[0]->begin(vk::CommandBufferBeginInfo()); + textureData.setCheckerboardTexture(device, commandBuffers[0]); + + 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::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); + + glslang::InitializeProcess(); + vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); + vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_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(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); + vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); + + vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, 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::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); + vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, vertexShaderModule, fragmentShaderModule, sizeof(texturedCubeData[0]), pipelineLayout, renderPass); + + /* VULKAN_KEY_START */ + + // 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() has already been called above! + + 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()); + commandBuffers[0]->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSets[0].get(), nullptr); + + 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); + + vk::DeviceSize offset = 0; + commandBuffers[0]->bindVertexBuffers(0, vertexBufferData.buffer.get(), offset); + + 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/utils/geometries.hpp b/samples/utils/geometries.hpp index bfa9d93..3efa0b7 100644 --- a/samples/utils/geometries.hpp +++ b/samples/utils/geometries.hpp @@ -13,13 +13,13 @@ // limitations under the License. // -struct Vertex +struct VertexPC { float x, y, z, w; // Position float r, g, b, a; // Color }; -static const Vertex coloredCubeData[] = +static const VertexPC coloredCubeData[] = { // red face { -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f }, diff --git a/samples/utils/shaders.cpp b/samples/utils/shaders.cpp index 554ca12..26dea06 100644 --- a/samples/utils/shaders.cpp +++ b/samples/utils/shaders.cpp @@ -13,6 +13,7 @@ // limitations under the License. // +#include "shaders.hpp" #include "vulkan/vulkan.hpp" #include "SPIRV/GlslangToSpv.h" @@ -183,6 +184,5 @@ namespace vk return device->createShaderModuleUnique(vk::ShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), shaderSPV.size() * sizeof(unsigned int), shaderSPV.data())); } - } } diff --git a/samples/utils/shaders.hpp b/samples/utils/shaders.hpp index c6e1724..c37d81d 100644 --- a/samples/utils/shaders.hpp +++ b/samples/utils/shaders.hpp @@ -28,16 +28,17 @@ namespace vk } -const std::string vertexShaderText = R"( +// vertex shader with (P)osition and (C)olor in and (C)olor out +const std::string vertexShaderText_PC_C = R"( #version 400 #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_shading_language_420pack : enable -layout (std140, binding = 0) uniform bufferVals +layout (std140, binding = 0) uniform buffer { mat4 mvp; -} myBufferVals; +} uniformBuffer; layout (location = 0) in vec4 pos; layout (location = 1) in vec4 inColor; @@ -47,11 +48,12 @@ layout (location = 0) out vec4 outColor; void main() { outColor = inColor; - gl_Position = myBufferVals.mvp * pos; + gl_Position = uniformBuffer.mvp * pos; } )"; -const std::string fragmentShaderText = R"( +// fragment shader with (C)olor in and (C)olor out +const std::string fragmentShaderText_C_C = R"( #version 400 #extension GL_ARB_separate_shader_objects : enable diff --git a/samples/utils/utils.cpp b/samples/utils/utils.cpp index 14cfbf7..a1b7de2 100644 --- a/samples/utils/utils.cpp +++ b/samples/utils/utils.cpp @@ -66,10 +66,28 @@ namespace vk return instance->createDebugReportCallbackEXTUnique(vk::DebugReportCallbackCreateInfoEXT(flags, &vk::su::debugReportCallback)); } - vk::UniqueDescriptorSetLayout createDescriptorSetLayout(vk::UniqueDevice &device) + vk::UniqueDescriptorPool createDescriptorPool(vk::UniqueDevice &device, bool textured) { + std::vector poolSizes; + poolSizes.push_back(vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1)); + if (textured) + { + poolSizes.push_back(vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, 1)); + } + vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, checked_cast(poolSizes.size()), poolSizes.data()); + return device->createDescriptorPoolUnique(descriptorPoolCreateInfo); + } + + vk::UniqueDescriptorSetLayout createDescriptorSetLayout(vk::UniqueDevice &device, bool textured) + { + std::vector bindings; + bindings.push_back(vk::DescriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex)); + if (textured) + { + bindings.push_back(vk::DescriptorSetLayoutBinding(1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment)); + } vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex); - return device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo({}, 1, &descriptorSetLayoutBinding)); + return device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo({}, checked_cast(bindings.size()), bindings.data())); } vk::UniqueDevice createDevice(vk::PhysicalDevice physicalDevice, uint32_t queueFamilyIndex, std::vector const& extensions) @@ -88,7 +106,7 @@ namespace vk return physicalDevice.createDeviceUnique(deviceCreateInfo); } - std::vector createFramebuffers(vk::UniqueDevice &device, vk::UniqueRenderPass &renderPass, std::vector const& imageViews, vk::UniqueImageView &depthImageView, int width, int height) + std::vector createFramebuffers(vk::UniqueDevice &device, vk::UniqueRenderPass &renderPass, std::vector const& imageViews, vk::UniqueImageView &depthImageView, vk::Extent2D const& extent) { vk::ImageView attachments[2]; attachments[1] = depthImageView.get(); @@ -98,7 +116,7 @@ namespace vk for (auto const& view : imageViews) { attachments[0] = view.get(); - framebuffers.push_back(device->createFramebufferUnique(vk::FramebufferCreateInfo(vk::FramebufferCreateFlags(), renderPass.get(), 2, attachments, width, height, 1))); + framebuffers.push_back(device->createFramebufferUnique(vk::FramebufferCreateInfo(vk::FramebufferCreateFlags(), renderPass.get(), 2, attachments, extent.width, extent.height, 1))); } return framebuffers; @@ -143,22 +161,7 @@ namespace vk return device->createGraphicsPipelineUnique(pipelineCache.get(), graphicsPipelineCreateInfo); } - vk::UniqueImage createImage(vk::UniqueDevice &device, vk::Format format, uint32_t width, uint32_t height, vk::ImageTiling tiling) - { - vk::Extent3D extend3D(width, height, 1); - vk::ImageCreateInfo imageCreateInfo({}, vk::ImageType::e2D, format, extend3D, 1, 1, vk::SampleCountFlagBits::e1, tiling, vk::ImageUsageFlagBits::eDepthStencilAttachment); - return device->createImageUnique(imageCreateInfo); - } - - vk::UniqueImageView createImageView(vk::UniqueDevice &device, vk::UniqueImage &image, vk::Format format) - { - vk::ComponentMapping componentMapping(ComponentSwizzle::eR, ComponentSwizzle::eG, ComponentSwizzle::eB, ComponentSwizzle::eA); - vk::ImageSubresourceRange imageSubresourceRange(vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1); - vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), image.get(), vk::ImageViewType::e2D, format, componentMapping, imageSubresourceRange); - return device->createImageViewUnique(imageViewCreateInfo); - } - - vk::UniqueInstance createInstance(std::string const& appName, std::string const& engineName, std::vector const& extensions) + vk::UniqueInstance createInstance(std::string const& appName, std::string const& engineName, std::vector const& extensions, uint32_t apiVersion) { std::vector enabledLayers; #if !defined(NDEBUG) @@ -180,7 +183,7 @@ namespace vk #endif // create a UniqueInstance - vk::ApplicationInfo applicationInfo(appName.c_str(), 1, engineName.c_str(), 1, VK_API_VERSION_1_1); + vk::ApplicationInfo applicationInfo(appName.c_str(), 1, engineName.c_str(), 1, apiVersion); vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo({}, &applicationInfo, checked_cast(enabledLayers.size()), enabledLayers.data(), checked_cast(enabledExtensions.size()), enabledExtensions.data())); @@ -211,61 +214,6 @@ namespace vk return device->createRenderPassUnique(vk::RenderPassCreateInfo(vk::RenderPassCreateFlags(), 2, attachmentDescriptions, 1, &subpassDescription)); } - vk::UniqueSwapchainKHR createSwapChain(vk::PhysicalDevice physicalDevice, vk::UniqueSurfaceKHR &surface, vk::UniqueDevice &device, uint32_t width, uint32_t height, vk::Format format, uint32_t graphicsQueueFamilyIndex, uint32_t presentQueueFamilyIndex) - { - vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.get()); - VkExtent2D swapchainExtent; - if (surfaceCapabilities.currentExtent.width == std::numeric_limits::max()) - { - // If the surface size is undefined, the size is set to the size of the images requested. - swapchainExtent.width = clamp(width, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width); - swapchainExtent.height = clamp(height, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height); - } - else - { - // If the surface size is defined, the swap chain size must match - swapchainExtent = surfaceCapabilities.currentExtent; - } - - vk::SurfaceTransformFlagBitsKHR preTransform = (surfaceCapabilities.supportedTransforms & vk::SurfaceTransformFlagBitsKHR::eIdentity) ? vk::SurfaceTransformFlagBitsKHR::eIdentity : surfaceCapabilities.currentTransform; - - vk::CompositeAlphaFlagBitsKHR compositeAlpha = - (surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::ePreMultiplied) ? vk::CompositeAlphaFlagBitsKHR::ePreMultiplied : - (surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::ePostMultiplied) ? vk::CompositeAlphaFlagBitsKHR::ePostMultiplied : - (surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::eInherit) ? vk::CompositeAlphaFlagBitsKHR::eInherit : vk::CompositeAlphaFlagBitsKHR::eOpaque; - - vk::SwapchainCreateInfoKHR swapChainCreateInfo({}, surface.get(), surfaceCapabilities.minImageCount, format, vk::ColorSpaceKHR::eSrgbNonlinear, swapchainExtent, 1, - vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::SharingMode::eExclusive, 0, nullptr, preTransform, compositeAlpha, vk::PresentModeKHR::eFifo, true, - nullptr); - - uint32_t queueFamilyIndices[2] = { graphicsQueueFamilyIndex, presentQueueFamilyIndex }; - if (graphicsQueueFamilyIndex != presentQueueFamilyIndex) - { - // If the graphics and present queues are from different queue families, we either have to explicitly transfer ownership of images between - // the queues, or we have to create the swapchain with imageSharingMode as vk::SharingMode::eConcurrent - swapChainCreateInfo.imageSharingMode = vk::SharingMode::eConcurrent; - swapChainCreateInfo.queueFamilyIndexCount = 2; - swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices; - } - return device->createSwapchainKHRUnique(swapChainCreateInfo); - } - - std::vector createSwapChainImageViews(vk::UniqueDevice &device, vk::UniqueSwapchainKHR &swapChain, vk::Format format) - { - std::vector images = device->getSwapchainImagesKHR(swapChain.get()); - std::vector imageViews; - imageViews.reserve(images.size()); - - vk::ComponentMapping componentMapping(ComponentSwizzle::eR, ComponentSwizzle::eG, ComponentSwizzle::eB, ComponentSwizzle::eA); - vk::ImageSubresourceRange imageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1); - - for (auto const& image : images) - { - imageViews.push_back(device->createImageViewUnique(vk::ImageViewCreateInfo(vk::ImageViewCreateFlags(), image, vk::ImageViewType::e2D, format, componentMapping, imageSubresourceRange))); - } - return imageViews; - } - VkBool32 debugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT /*objectType*/, uint64_t /*object*/, size_t /*location*/, int32_t /*messageCode*/, const char* /*pLayerPrefix*/, const char* pMessage, void* /*pUserData*/) { switch (flags) @@ -356,22 +304,6 @@ namespace vk return{ VK_KHR_SWAPCHAIN_EXTENSION_NAME }; } - vk::ImageTiling getImageTiling(vk::FormatProperties const& formatProperties) - { - if (formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment) - { - return vk::ImageTiling::eLinear; - } - else if (formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment) - { - return vk::ImageTiling::eOptimal; - } - else - { - throw std::runtime_error("DepthStencilAttachment is not supported for D16Unorm depth format."); - } - } - std::vector getInstanceExtensions() { std::vector extensions; @@ -406,6 +338,51 @@ namespace vk return (formats[0].format == vk::Format::eUndefined) ? vk::Format::eB8G8R8A8Unorm : formats[0].format; } + void setImageLayout(vk::UniqueCommandBuffer &commandBuffer, vk::Image image, vk::ImageAspectFlags aspectFlags, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout, vk::PipelineStageFlags sourceStageMask, vk::PipelineStageFlags destinationStageMask) + { + vk::AccessFlags sourceAccessMask; + switch (oldImageLayout) + { + case vk::ImageLayout::eColorAttachmentOptimal: + sourceAccessMask = vk::AccessFlagBits::eColorAttachmentWrite; + break; + case vk::ImageLayout::eTransferDstOptimal: + sourceAccessMask = vk::AccessFlagBits::eTransferWrite; + break; + case vk::ImageLayout::ePreinitialized: + sourceAccessMask = vk::AccessFlagBits::eHostWrite; + break; + default: + break; + } + + vk::AccessFlags destinationAccessMask; + switch (newImageLayout) + { + case vk::ImageLayout::eTransferDstOptimal: + destinationAccessMask = vk::AccessFlagBits::eTransferWrite; + break; + case vk::ImageLayout::eTransferSrcOptimal: + destinationAccessMask = vk::AccessFlagBits::eTransferRead; + break; + case vk::ImageLayout::eShaderReadOnlyOptimal: + destinationAccessMask = vk::AccessFlagBits::eShaderRead; + break; + case vk::ImageLayout::eColorAttachmentOptimal: + destinationAccessMask = vk::AccessFlagBits::eColorAttachmentWrite; + break; + case vk::ImageLayout::eDepthStencilAttachmentOptimal: + destinationAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite; + break; + default: + break; + } + + vk::ImageSubresourceRange imageSubresourceRange(aspectFlags, 0, 1, 0, 1); + vk::ImageMemoryBarrier imageMemoryBarrier(sourceAccessMask, destinationAccessMask, oldImageLayout, newImageLayout, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, image, imageSubresourceRange); + return commandBuffer->pipelineBarrier(sourceStageMask, destinationStageMask, {}, nullptr, nullptr, imageMemoryBarrier); + } + void submitAndWait(vk::UniqueDevice &device, vk::Queue queue, vk::UniqueCommandBuffer &commandBuffer) { vk::UniqueFence fence = device->createFenceUnique(vk::FenceCreateInfo()); @@ -415,6 +392,170 @@ namespace vk ; } + void updateDescriptorSets(vk::UniqueDevice &device, vk::UniqueDescriptorSet &descriptorSet, 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)); + if (descriptorImageInfo) + { + writeDescriptorSets.push_back(vk::WriteDescriptorSet(descriptorSet.get(), 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, descriptorImageInfo, nullptr, nullptr)); + } + device->updateDescriptorSets(writeDescriptorSets, nullptr); + } + + BufferData::BufferData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice &device, vk::DeviceSize size, vk::BufferUsageFlags usage) + { + buffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), size, usage)); + deviceMemory = vk::su::allocateMemory(device, physicalDevice.getMemoryProperties(), device->getBufferMemoryRequirements(buffer.get()) + , vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); + device->bindBufferMemory(buffer.get(), deviceMemory.get(), 0); + } + + DepthBufferData::DepthBufferData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice & device, vk::Format format, vk::Extent2D const& extent) + : ImageData(physicalDevice, device, format, extent, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eDepthStencilAttachment, vk::ImageLayout::eUndefined, vk::MemoryPropertyFlagBits::eDeviceLocal, vk::ImageAspectFlagBits::eDepth) + {} + + ImageData::ImageData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice & device, vk::Format format_, vk::Extent2D const& extent, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::ImageLayout initialLayout, vk::MemoryPropertyFlags memoryProperties, vk::ImageAspectFlags aspectMask) + : format(format_) + { + vk::ImageCreateInfo imageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, format, vk::Extent3D(extent, 1), 1, 1, vk::SampleCountFlagBits::e1, tiling, usage, vk::SharingMode::eExclusive, 0, nullptr, initialLayout); + image = device->createImageUnique(imageCreateInfo); + + deviceMemory = vk::su::allocateMemory(device, physicalDevice.getMemoryProperties(), device->getImageMemoryRequirements(image.get()), memoryProperties); + + device->bindImageMemory(image.get(), deviceMemory.get(), 0); + + vk::ComponentMapping componentMapping(ComponentSwizzle::eR, ComponentSwizzle::eG, ComponentSwizzle::eB, ComponentSwizzle::eA); + vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), image.get(), vk::ImageViewType::e2D, format, componentMapping, vk::ImageSubresourceRange(aspectMask, 0, 1, 0, 1)); + imageView = device->createImageViewUnique(imageViewCreateInfo); + } + + SurfaceData::SurfaceData(vk::UniqueInstance &instance, std::string const& className, std::string const& windowName, vk::Extent2D const& extent_) + : extent(extent_) + { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + window = vk::su::initializeWindow(className.c_str(), windowName.c_str(), extent.width, extent.height); + surface = instance->createWin32SurfaceKHRUnique(vk::Win32SurfaceCreateInfoKHR(vk::Win32SurfaceCreateFlagsKHR(), GetModuleHandle(nullptr), window)); +#else +#pragma error "unhandled platform" +#endif + } + + SwapChainData::SwapChainData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice &device, vk::UniqueSurfaceKHR &surface, vk::Extent2D const& extent, vk::ImageUsageFlags usage, uint32_t graphicsQueueFamilyIndex, uint32_t presentQueueFamilyIndex) + { + colorFormat = vk::su::pickColorFormat(physicalDevice.getSurfaceFormatsKHR(surface.get())); + + vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.get()); + VkExtent2D swapchainExtent; + if (surfaceCapabilities.currentExtent.width == std::numeric_limits::max()) + { + // If the surface size is undefined, the size is set to the size of the images requested. + swapchainExtent.width = clamp(extent.width, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width); + swapchainExtent.height = clamp(extent.height, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height); + } + else + { + // If the surface size is defined, the swap chain size must match + swapchainExtent = surfaceCapabilities.currentExtent; + } + vk::SurfaceTransformFlagBitsKHR preTransform = (surfaceCapabilities.supportedTransforms & vk::SurfaceTransformFlagBitsKHR::eIdentity) ? vk::SurfaceTransformFlagBitsKHR::eIdentity : surfaceCapabilities.currentTransform; + vk::CompositeAlphaFlagBitsKHR compositeAlpha = + (surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::ePreMultiplied) ? vk::CompositeAlphaFlagBitsKHR::ePreMultiplied : + (surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::ePostMultiplied) ? vk::CompositeAlphaFlagBitsKHR::ePostMultiplied : + (surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::eInherit) ? vk::CompositeAlphaFlagBitsKHR::eInherit : vk::CompositeAlphaFlagBitsKHR::eOpaque; + vk::SwapchainCreateInfoKHR swapChainCreateInfo({}, surface.get(), surfaceCapabilities.minImageCount, colorFormat, vk::ColorSpaceKHR::eSrgbNonlinear, swapchainExtent, 1, usage, + vk::SharingMode::eExclusive, 0, nullptr, preTransform, compositeAlpha, vk::PresentModeKHR::eFifo, true, nullptr); + uint32_t queueFamilyIndices[2] = { graphicsQueueFamilyIndex, presentQueueFamilyIndex }; + if (graphicsQueueFamilyIndex != presentQueueFamilyIndex) + { + // If the graphics and present queues are from different queue families, we either have to explicitly transfer ownership of images between + // the queues, or we have to create the swapchain with imageSharingMode as vk::SharingMode::eConcurrent + swapChainCreateInfo.imageSharingMode = vk::SharingMode::eConcurrent; + swapChainCreateInfo.queueFamilyIndexCount = 2; + swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices; + } + swapChain = device->createSwapchainKHRUnique(swapChainCreateInfo); + + images = device->getSwapchainImagesKHR(swapChain.get()); + + imageViews.reserve(images.size()); + vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA); + vk::ImageSubresourceRange subResourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1); + for (auto image : images) + { + vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), image, vk::ImageViewType::e2D, colorFormat, componentMapping, subResourceRange); + imageViews.push_back(device->createImageViewUnique(imageViewCreateInfo)); + } + } + + TextureData::TextureData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice &device) + : format(vk::Format::eR8G8B8A8Unorm) + , extent(256, 256) + { + vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties(); + vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(format); + + needsStaging = (formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eSampledImage) != vk::FormatFeatureFlagBits::eSampledImage; + vk::ImageTiling imageTiling; + vk::ImageUsageFlags usageFlags(vk::ImageUsageFlagBits::eSampled); + vk::ImageLayout initialLayout; + if (needsStaging) + { + bufferData = std::make_unique(physicalDevice, device, extent.width * extent.height * 4, vk::BufferUsageFlagBits::eTransferSrc); + imageTiling = vk::ImageTiling::eOptimal; + usageFlags |= vk::ImageUsageFlagBits::eTransferDst; + initialLayout = vk::ImageLayout::eUndefined; + } + else + { + imageTiling = vk::ImageTiling::eLinear; + initialLayout = vk::ImageLayout::ePreinitialized; + } + imageData = std::make_unique(physicalDevice, device, format, extent, imageTiling, usageFlags, initialLayout + , vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible, vk::ImageAspectFlagBits::eColor); + + textureSampler = device->createSamplerUnique(vk::SamplerCreateInfo(vk::SamplerCreateFlags(), vk::Filter::eNearest, vk::Filter::eNearest, vk::SamplerMipmapMode::eNearest, + vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, 0.0f, false, 1.0f, false, vk::CompareOp::eNever, 0.0f, 0.0f + , vk::BorderColor::eFloatOpaqueWhite)); + } + + void TextureData::setCheckerboardTexture(vk::UniqueDevice &device, vk::UniqueCommandBuffer &commandBuffer) + { + void* data = needsStaging + ? device->mapMemory(bufferData->deviceMemory.get(), 0, device->getBufferMemoryRequirements(bufferData->buffer.get()).size) + : device->mapMemory(imageData->deviceMemory.get(), 0, device->getImageMemoryRequirements(imageData->image.get()).size); + // Checkerboard of 16x16 pixel squares + unsigned char *pImageMemory = static_cast(data); + for (uint32_t row = 0; row < extent.height; row++) + { + for (uint32_t col = 0; col < extent.width; col++) + { + unsigned char rgb = (((row & 0x10) == 0) ^ ((col & 0x10) == 0)) * 255; + pImageMemory[0] = rgb; + pImageMemory[1] = rgb; + pImageMemory[2] = rgb; + pImageMemory[3] = 255; + pImageMemory += 4; + } + } + device->unmapMemory(needsStaging ? bufferData->deviceMemory.get() : imageData->deviceMemory.get()); + + if (needsStaging) + { + // Since we're going to blit to the texture image, set its layout to eTransferDstOptimal + vk::su::setImageLayout(commandBuffer, imageData->image.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer); + vk::BufferImageCopy copyRegion(0, extent.width, extent.height, vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), vk::Offset3D(0, 0, 0), vk::Extent3D(extent, 1)); + commandBuffer->copyBufferToImage(bufferData->buffer.get(), imageData->image.get(), vk::ImageLayout::eTransferDstOptimal, copyRegion); + // Set the layout for the texture image from eTransferDstOptimal to SHADER_READ_ONLY + vk::su::setImageLayout(commandBuffer, imageData->image.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader); + } + else + { + // If we can use the linear tiled image as a texture, just do it + vk::su::setImageLayout(commandBuffer, imageData->image.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::ePreinitialized, vk::ImageLayout::eShaderReadOnlyOptimal, vk::PipelineStageFlagBits::eHost, vk::PipelineStageFlagBits::eFragmentShader); + } + } + #if defined(VK_USE_PLATFORM_WIN32_KHR) LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { diff --git a/samples/utils/utils.hpp b/samples/utils/utils.hpp index 423e833..27c95bd 100644 --- a/samples/utils/utils.hpp +++ b/samples/utils/utils.hpp @@ -22,6 +22,64 @@ namespace vk { const uint64_t FenceTimeout = 100000000; + struct BufferData + { + BufferData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice &device, vk::DeviceSize size, vk::BufferUsageFlags usage); + + vk::UniqueBuffer buffer; + vk::UniqueDeviceMemory deviceMemory; + }; + + struct ImageData + { + ImageData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice & device, vk::Format format, vk::Extent2D const& extent, vk::ImageTiling tiling, vk::ImageUsageFlags usage + , vk::ImageLayout initialLayout, vk::MemoryPropertyFlags memoryProperties, vk::ImageAspectFlags aspectMask); + + vk::Format format; + vk::UniqueImage image; + vk::UniqueDeviceMemory deviceMemory; + vk::UniqueImageView imageView; + }; + + struct DepthBufferData : public ImageData + { + DepthBufferData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice & device, vk::Format format, vk::Extent2D const& extent); + }; + + struct SurfaceData + { + SurfaceData(vk::UniqueInstance &instance, std::string const& className, std::string const& windowName, vk::Extent2D const& extent); + + vk::Extent2D extent; + HWND window; + vk::UniqueSurfaceKHR surface; + }; + + struct SwapChainData + { + SwapChainData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice &device, vk::UniqueSurfaceKHR &surface, vk::Extent2D const& extent, vk::ImageUsageFlags usage, uint32_t graphicsFamilyIndex, uint32_t presentFamilyIndex); + + vk::Format colorFormat; + vk::UniqueSwapchainKHR swapChain; + std::vector images; + std::vector imageViews; + }; + + struct TextureData + { + TextureData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice &device); + + void setCheckerboardTexture(vk::UniqueDevice &device, vk::UniqueCommandBuffer &commandBuffer); + + vk::Format format; + vk::Extent2D extent; + bool needsStaging; + std::unique_ptr bufferData; + std::unique_ptr imageData; + vk::UniqueSampler textureSampler; + }; + + template VULKAN_HPP_INLINE TargetType checked_cast(SourceType value) { @@ -55,25 +113,23 @@ 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::UniqueDescriptorSetLayout createDescriptorSetLayout(vk::UniqueDevice &device); + vk::UniqueDescriptorPool createDescriptorPool(vk::UniqueDevice &device, bool textured = false); + vk::UniqueDescriptorSetLayout createDescriptorSetLayout(vk::UniqueDevice &device, 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, int width, int height); + 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); - vk::UniqueInstance createInstance(std::string const& appName, std::string const& engineName, std::vector const& extensions = {}); - vk::UniqueImage createImage(vk::UniqueDevice &device, vk::Format format, uint32_t width, uint32_t height, vk::ImageTiling tiling = vk::ImageTiling::eOptimal); - vk::UniqueImageView createImageView(vk::UniqueDevice &device, vk::UniqueImage &image, vk::Format format); + vk::UniqueInstance createInstance(std::string const& appName, std::string const& engineName, std::vector const& extensions = {}, uint32_t apiVersion = VK_API_VERSION_1_0); vk::UniqueRenderPass createRenderPass(vk::UniqueDevice &device, vk::Format colorFormat, vk::Format depthFormat); - vk::UniqueSwapchainKHR createSwapChain(vk::PhysicalDevice physicalDevice, vk::UniqueSurfaceKHR &surface, vk::UniqueDevice &device, uint32_t width, uint32_t height, vk::Format format, uint32_t graphicsQueueFamilyIndex, uint32_t presentQueueFamilyIndex); - std::vector createSwapChainImageViews(vk::UniqueDevice &device, vk::UniqueSwapchainKHR &swapChain, vk::Format format); VkBool32 debugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData); uint32_t findGraphicsQueueFamilyIndex(std::vector const& queueFamilyProperties); std::pair findGraphicsAndPresentQueueFamilyIndex(vk::PhysicalDevice physicalDevice, vk::UniqueSurfaceKHR & surface); uint32_t findMemoryType(vk::PhysicalDeviceMemoryProperties const& memoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirementsMask); std::vector getDeviceExtensions(); - vk::ImageTiling getImageTiling(vk::FormatProperties const& formatProperties); std::vector getInstanceExtensions(); 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); #if defined(VK_USE_PLATFORM_WIN32_KHR) HWND initializeWindow(std::string const& className, std::string const& windowName, LONG width, LONG height);