123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758 |
- // The MIT License(MIT)
- //
- // Copyright(c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy of
- // this software and associated documentation files(the "Software"), to deal in
- // the Software without restriction, including without limitation the rights to
- // use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
- // the Software, and to permit persons to whom the Software is furnished to do so,
- // subject to the following conditions :
- //
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR
- // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- #include "DeviceResources.h"
- #include <algorithm>
- #include <array>
- #include <vector>
- #include <imgui_impl_vulkan.h>
- static void glfw_window_size_callback(GLFWwindow* window, int width, int height)
- {
- auto devRes = reinterpret_cast<DeviceResources*>(glfwGetWindowUserPointer(window));
- devRes->resizeRenderTarget(width, height);
- }
- const VkFormat DeviceResources::SwapchainFormat = VK_FORMAT_R8G8B8A8_UNORM;
- void DeviceResources::create(GLFWwindow* hWnd)
- {
- m_window = hWnd;
- assert(glfwGetWindowUserPointer(hWnd) == nullptr);
- uint32_t extensionCount;
- auto extensions = glfwGetRequiredInstanceExtensions(&extensionCount);
- if (extensions == nullptr)
- {
- VK_DIE("glfwGetRequiredInstanceExtensions");
- }
- VkInstanceCreateInfo createInfo{};
- createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
- createInfo.enabledExtensionCount = extensionCount;
- createInfo.ppEnabledExtensionNames = extensions;
- VK_OK(vkCreateInstance(&createInfo, nullptr, &m_instance));
- selectPhysicalDeviceAndQueueFamily();
- VkDeviceQueueCreateInfo qCreateInfo{};
- qCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- qCreateInfo.queueFamilyIndex = m_queueFamilyIndex;
- qCreateInfo.queueCount = 1;
- const float qPriority = 1.f;
- qCreateInfo.pQueuePriorities = &qPriority;
- VkPhysicalDeviceFeatures physDevFeatures;
- vkGetPhysicalDeviceFeatures(m_physicalDevice, &physDevFeatures);
- const char* logicalDevExt[] = {
- VK_KHR_SWAPCHAIN_EXTENSION_NAME,
- VK_KHR_MAINTENANCE2_EXTENSION_NAME, // For VkImageViewUsageCreateInfo
- };
- VkDeviceCreateInfo devCreateInfo{};
- devCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
- devCreateInfo.pQueueCreateInfos = &qCreateInfo;
- devCreateInfo.queueCreateInfoCount = 1;
- devCreateInfo.pEnabledFeatures = &physDevFeatures;
- devCreateInfo.enabledExtensionCount = static_cast<uint32_t>(std::size(logicalDevExt));
- devCreateInfo.ppEnabledExtensionNames = logicalDevExt;
- VK_OK(vkCreateDevice(m_physicalDevice, &devCreateInfo, nullptr, &m_device));
- vkGetPhysicalDeviceProperties(m_physicalDevice, &m_physicalDeviceProperties);
- vkGetDeviceQueue(m_device, m_queueFamilyIndex, 0, &m_queue);
- //See: vkCreateWin32SurfaceKHR
- VK_OK(glfwCreateWindowSurface(m_instance, m_window, nullptr, &m_surface));
- VkBool32 isSurfaceSupported;
- VK_OK(vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, m_queueFamilyIndex, m_surface, &isSurfaceSupported));
- if (isSurfaceSupported != VK_TRUE)
- {
- VK_DIE("vkGetPhysicalDeviceSurfaceSupportKHR");
- }
- m_surfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(m_physicalDevice, m_surface, &SwapchainFormat, 1, SwapchainColorSpace);
- // Imgui needs a descriptor pool.
- // This is probably excessive, but it's what's in the sample and should cover all our other needs.
- // https://github.com/ocornut/imgui/wiki/Integrating-with-Vulkan
- // https://github.com/ocornut/imgui/blob/master/examples/example_glfw_vulkan/main.cpp
- {
- const uint32_t POOL_COUNT = 1000;
- VkDescriptorPoolSize pool_sizes[] =
- {
- { VK_DESCRIPTOR_TYPE_SAMPLER, POOL_COUNT },
- { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, POOL_COUNT },
- { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, POOL_COUNT },
- { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, POOL_COUNT },
- { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, POOL_COUNT },
- { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, POOL_COUNT },
- { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, POOL_COUNT },
- { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, POOL_COUNT },
- { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, POOL_COUNT },
- { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, POOL_COUNT },
- { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, POOL_COUNT }
- };
- constexpr uint32_t NUM_POOLS = static_cast<uint32_t>(std::size(pool_sizes));
- VkDescriptorPoolCreateInfo pool_info{};
- pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
- pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
- pool_info.maxSets = POOL_COUNT * NUM_POOLS;
- pool_info.poolSizeCount = NUM_POOLS;
- pool_info.pPoolSizes = pool_sizes;
- VK_OK(vkCreateDescriptorPool(m_device, &pool_info, nullptr, &m_descriptorPool));
- }
- // Texture sampler
- {
- VkSamplerCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
- info.magFilter = VK_FILTER_LINEAR;
- info.minFilter = VK_FILTER_LINEAR;
- info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
- info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
- info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
- info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
- info.minLod = -1000;
- info.maxLod = 1000;
- info.maxAnisotropy = 1.0f;
- VK_OK(vkCreateSampler(m_device, &info, nullptr, &m_sampler));
- }
- if (m_physicalDeviceProperties.limits.timestampComputeAndGraphics)
- {
- VkQueryPoolCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
- info.queryType = VK_QUERY_TYPE_TIMESTAMP;
- info.queryCount = DeviceResources::NumQueryValues;
- VK_OK(vkCreateQueryPool(m_device, &info, m_allocator, &m_queryPool));
- }
- int width, height;
- glfwGetFramebufferSize(m_window, &width, &height);
- resizeRenderTarget(width, height);
- m_initialized = true;
- glfwSetWindowUserPointer(m_window, this);
- glfwSetWindowSizeCallback(m_window, glfw_window_size_callback);
- }
- void DeviceResources::createSurfaceResources()
- {
- destroySurfaceResources();
- // Swapchain
- {
- const auto oldSwapchain = m_swapchain;
- VkSurfaceCapabilitiesKHR surfCaps{};
- VK_OK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &surfCaps));
- VkSwapchainCreateInfoKHR swapCreateInfo{};
- swapCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
- swapCreateInfo.surface = m_surface;
- swapCreateInfo.minImageCount = surfCaps.minImageCount;
- swapCreateInfo.imageFormat = m_surfaceFormat.format;
- swapCreateInfo.imageColorSpace = m_surfaceFormat.colorSpace;
- swapCreateInfo.imageArrayLayers = 1;
- // `TRANSFER_DST` allows us to blit into the swapchain images
- // `STORAGE` allows us to bind to compute shader output
- swapCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
- swapCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- swapCreateInfo.preTransform = surfCaps.currentTransform;
- swapCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- swapCreateInfo.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
- swapCreateInfo.clipped = VK_TRUE;
- swapCreateInfo.oldSwapchain = oldSwapchain;
- if (surfCaps.currentExtent.width != UINT32_MAX)
- {
- swapCreateInfo.imageExtent = surfCaps.currentExtent;
- }
- else
- {
- int width, height;
- glfwGetFramebufferSize(m_window, &width, &height);
- swapCreateInfo.imageExtent = {
- std::clamp<uint32_t>(width, surfCaps.minImageExtent.width, surfCaps.maxImageExtent.width),
- std::clamp<uint32_t>(height, surfCaps.minImageExtent.height, surfCaps.maxImageExtent.height)
- };
- }
- m_width = swapCreateInfo.imageExtent.width;
- m_height = swapCreateInfo.imageExtent.height;
- VK_OK(vkCreateSwapchainKHR(m_device, &swapCreateInfo, m_allocator, &m_swapchain));
- if (oldSwapchain != VK_NULL_HANDLE)
- {
- vkDestroySwapchainKHR(m_device, oldSwapchain, m_allocator);
- }
- }
- // Render pass
- {
- VkAttachmentDescription colorAttachDesc {};
- colorAttachDesc.format = m_surfaceFormat.format;
- colorAttachDesc.samples = VK_SAMPLE_COUNT_1_BIT;
- // Don't VK_ATTACHMENT_LOAD_OP_CLEAR because this pass is only used for imgui
- // and compute shader has already populated buffer
- colorAttachDesc.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
- colorAttachDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
- colorAttachDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- colorAttachDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- colorAttachDesc.initialLayout = VK_IMAGE_LAYOUT_GENERAL;
- colorAttachDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- VkAttachmentReference colorRef{};
- colorRef.attachment = 0;
- colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- VkSubpassDescription subpassDesc{};
- subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpassDesc.colorAttachmentCount = 1;
- subpassDesc.pColorAttachments = &colorRef;
- VkSubpassDependency subpassDep{};
- subpassDep.srcSubpass = VK_SUBPASS_EXTERNAL;
- subpassDep.dstSubpass = 0;
- subpassDep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- subpassDep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- subpassDep.srcAccessMask = 0;
- subpassDep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- VkRenderPassCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- info.attachmentCount = 1;
- info.pAttachments = &colorAttachDesc;
- info.subpassCount = 1;
- info.pSubpasses = &subpassDesc;
- info.dependencyCount = 1;
- info.pDependencies = &subpassDep;
- VK_OK(vkCreateRenderPass(m_device, &info, m_allocator, &m_renderPass));
- }
- // Swapchain entourage
- {
- uint32_t imageCount;
- VK_OK(vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, nullptr));
- std::vector<VkImage> swapchainImages(imageCount);
- VK_OK(vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, swapchainImages.data()));
- m_frames.resize(imageCount);
- m_semaphores.resize(imageCount);
- for (uint32_t i = 0; i < imageCount; ++i)
- {
- m_frames[i].backbuffer = swapchainImages[i];
- // Image views
- {
- const VkImageViewUsageCreateInfo usageInfo{
- VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
- nullptr,
- VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT
- };
- VkImageViewCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- info.pNext = &usageInfo;
- info.image = m_frames[i].backbuffer;
- info.viewType = VK_IMAGE_VIEW_TYPE_2D;
- info.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
- info.format = m_surfaceFormat.format;
- info.subresourceRange.layerCount = 1;
- info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- info.subresourceRange.levelCount = 1;
- VK_OK(vkCreateImageView(m_device, &info, m_allocator, &m_frames[i].backbufferView));
- }
- // Framebuffers
- {
- VkFramebufferCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
- info.renderPass = m_renderPass;
- info.attachmentCount = 1;
- info.pAttachments = &m_frames[i].backbufferView;
- info.width = m_width;
- info.height = m_height;
- info.layers = 1;
- VK_OK(vkCreateFramebuffer(m_device, &info, m_allocator, &m_frames[i].framebuffer));
- }
- // Command pool
- {
- VkCommandPoolCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- info.queueFamilyIndex = m_queueFamilyIndex;
- VK_OK(vkCreateCommandPool(m_device, &info, m_allocator, &m_frames[i].commandPool));
- }
- {
- VkCommandBufferAllocateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- info.commandPool = m_frames[i].commandPool;
- info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- info.commandBufferCount = 1;
- VK_OK(vkAllocateCommandBuffers(m_device, &info, &m_frames[i].commandBuffer));
- }
- {
- VkFenceCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
- VK_OK(vkCreateFence(m_device, &info, m_allocator, &m_frames[i].fence));
- }
- // Per-frame semaphores
- {
- VkSemaphoreCreateInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- VK_OK(vkCreateSemaphore(m_device, &info, m_allocator, &m_semaphores[i].imageAcquired));
- VK_OK(vkCreateSemaphore(m_device, &info, m_allocator, &m_semaphores[i].renderComplete));
- }
- }
- }
- }
- void DeviceResources::destroySurfaceResources()
- {
- VK_OK(vkDeviceWaitIdle(m_device));
- for (auto& frame : m_frames)
- {
- vkDestroyFence(m_device, frame.fence, m_allocator);
- vkFreeCommandBuffers(m_device, frame.commandPool, 1, &frame.commandBuffer);
- vkDestroyCommandPool(m_device, frame.commandPool, m_allocator);
- vkDestroyFramebuffer(m_device, frame.framebuffer, m_allocator);
- vkDestroyImageView(m_device, frame.backbufferView, m_allocator);
- }
- m_frames.clear();
- for (auto& frame : m_semaphores)
- {
- vkDestroySemaphore(m_device, frame.imageAcquired, m_allocator);
- vkDestroySemaphore(m_device, frame.renderComplete, m_allocator);
- }
- m_semaphores.clear();
- if (m_renderPass != VK_NULL_HANDLE)
- {
- vkDestroyRenderPass(m_device, m_renderPass, m_allocator);
- m_renderPass = VK_NULL_HANDLE;
- }
- // NB: swapchain isn't destroyed because this is called from
- // createSurfaceResources() where we need old swapchain when recreating it
- }
- void DeviceResources::cleanUp()
- {
- m_initialized = false;
- glfwSetWindowUserPointer(m_window, nullptr);
- destroySurfaceResources();
- vkDestroyQueryPool(m_device, m_queryPool, m_allocator);
- vkDestroySampler(m_device, m_sampler, m_allocator);
- vkDestroyDescriptorPool(m_device, m_descriptorPool, m_allocator);
- vkDestroySwapchainKHR(m_device, m_swapchain, m_allocator);
- vkDestroySurfaceKHR(m_instance, m_surface, m_allocator);
- vkDestroyDevice(m_device, m_allocator);
- vkDestroyInstance(m_instance, m_allocator);
- }
- void DeviceResources::selectPhysicalDeviceAndQueueFamily()
- {
- uint32_t deviceCount = 0;
- VK_OK(vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr));
- if (deviceCount == 0) {
- VK_DIE("vkEnumeratePhysicalDevices");
- }
- std::vector<VkPhysicalDevice> physicalDevices(deviceCount);
- VK_OK(vkEnumeratePhysicalDevices(m_instance, &deviceCount, physicalDevices.data()));
- for (const auto& physDev : physicalDevices)
- {
- uint32_t queueFamilyCount = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueFamilyCount, nullptr);
- std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
- vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueFamilyCount, queueFamilies.data());
- for (auto i = 0; i < queueFamilies.size(); ++i)
- {
- const auto& qFamily = queueFamilies[i];
- // To make things a bit simpler, we want a single queue that does everything we need
- if ((qFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) && (qFamily.queueFlags & VK_QUEUE_COMPUTE_BIT)
- && (qFamily.queueFlags & VK_QUEUE_TRANSFER_BIT)
- && glfwGetPhysicalDevicePresentationSupport(m_instance, physDev, i))
- {
- // Additionally can:
- // - vkGetPhysicalDeviceSurfaceFormatsKHR
- // - vkGetPhysicalDeviceSurfacePresentModesKHR
- m_physicalDevice = physDev;
- m_queueFamilyIndex = i;
- return;
- }
- }
- }
- VK_DIE("selectPhysicalDeviceAndQueueFamily");
- }
- uint32_t DeviceResources::findMemoryTypeIndex(uint32_t memoryTypeBits, VkMemoryPropertyFlags memPropFlags)
- {
- VkPhysicalDeviceMemoryProperties physDevMemProps;
- vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &physDevMemProps);
- for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i)
- {
- if ((memoryTypeBits & (1 << i))
- && (physDevMemProps.memoryTypes[i].propertyFlags & memPropFlags) == memPropFlags)
- {
- return i;
- }
- }
- VK_DIE("findMemoryTypeIndex");
- return -1;
- }
- void DeviceResources::createConstBuffer(void* initialData, uint32_t size, VkBuffer* outBuffer, VkDeviceMemory* outBuffMem, VkDeviceSize* outOffset)
- {
- const auto align = m_physicalDeviceProperties.limits.minUniformBufferOffsetAlignment;
- *outOffset = ((size + align - 1) / align) * align;
- createBuffer(*outOffset * numSwapchainImages(),
- VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
- outBuffer, outBuffMem);
- }
- void DeviceResources::createBuffer(VkDeviceSize size, VkBufferUsageFlags buffUsage, VkMemoryPropertyFlags memProps, VkBuffer* outBuffer, VkDeviceMemory* outBuffMem)
- {
- {
- VkBufferCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- info.size = size;
- info.usage = buffUsage;
- info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- VK_OK(vkCreateBuffer(m_device, &info, nullptr, outBuffer));
- }
- {
- VkMemoryRequirements memReqs;
- vkGetBufferMemoryRequirements(m_device, *outBuffer, &memReqs);
- VkMemoryAllocateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- info.allocationSize = memReqs.size;
- info.memoryTypeIndex = findMemoryTypeIndex(memReqs.memoryTypeBits, memProps);
- VK_OK(vkAllocateMemory(m_device, &info, nullptr, outBuffMem));
- }
- VK_OK(vkBindBufferMemory(m_device, *outBuffer, *outBuffMem, 0));
- }
- void DeviceResources::resizeRenderTarget(uint32_t Width, uint32_t Height)
- {
- createSurfaceResources();
- }
- void DeviceResources::update()
- {
- if (m_swapChainRebuild)
- {
- int width, height;
- glfwGetFramebufferSize(m_window, &width, &height);
- if (width > 0 && height > 0)
- {
- ImGui_ImplVulkan_SetMinImageCount(m_minImageCount);
- resizeRenderTarget(width, height);
- m_frameIndex = 0;
- m_swapChainRebuild = false;
- }
- }
- }
- void DeviceResources::beginRender()
- {
- auto image_acquired_semaphore = imageAcquired();
- auto render_complete_semaphore = renderComplete();
- VkResult err = vkAcquireNextImageKHR(m_device, swapchain(), UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &m_frameIndex);
- if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
- {
- requestSwapChainRebuild();
- return;
- }
- auto frame = currentFrame();
- auto cmdBuff = commandBuffer();
- {
- VK_OK(vkWaitForFences(m_device, 1, &frame->fence, VK_TRUE, UINT64_MAX)); // wait indefinitely
- VK_OK(vkResetFences(m_device, 1, &frame->fence));
- }
- {
- VK_OK(vkResetCommandPool(m_device, frame->commandPool, 0));
- VkCommandBufferBeginInfo info{};
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
- VK_OK(vkBeginCommandBuffer(cmdBuff, &info));
- }
- // Layout transition backbuffer
- {
- VkImageMemoryBarrier barrier{};
- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
- barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
- barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- barrier.subresourceRange.levelCount = 1;
- barrier.subresourceRange.layerCount = 1;
- barrier.image = backBuffer();
- vkCmdPipelineBarrier(cmdBuff, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
- }
- }
- void DeviceResources::present(uint32_t SyncInterval, uint32_t Flags)
- {
- if (m_swapChainRebuild)
- return;
- auto cmdBuff = commandBuffer();
- // Layout transition backbuffer for present
- {
- VkImageMemoryBarrier barrier{};
- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
- barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
- barrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- barrier.subresourceRange.levelCount = 1;
- barrier.subresourceRange.layerCount = 1;
- barrier.image = backBuffer();
- vkCmdPipelineBarrier(cmdBuff, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
- }
- auto image_acquired_semaphore = imageAcquired();
- auto render_complete_semaphore = renderComplete();
- auto frame = currentFrame();
- // Submit command buffer
- {
- VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkSubmitInfo info = {};
- info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- info.waitSemaphoreCount = 1;
- info.pWaitSemaphores = &image_acquired_semaphore;
- info.pWaitDstStageMask = &wait_stage;
- info.commandBufferCount = 1;
- info.pCommandBuffers = &cmdBuff;
- info.signalSemaphoreCount = 1;
- info.pSignalSemaphores = &render_complete_semaphore;
- VK_OK(vkEndCommandBuffer(cmdBuff));
- VK_OK(vkQueueSubmit(m_queue, 1, &info, frame->fence));
- }
- // Frame present
- VkPresentInfoKHR info{};
- info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
- info.waitSemaphoreCount = 1;
- info.pWaitSemaphores = &render_complete_semaphore;
- info.swapchainCount = 1;
- info.pSwapchains = &m_swapchain;
- info.pImageIndices = &m_frameIndex;
- VkResult err = vkQueuePresentKHR(m_queue, &info);
- if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
- {
- requestSwapChainRebuild();
- return;
- }
- assert(err == VK_SUCCESS);
- m_semaphoreIndex = (m_semaphoreIndex + 1) % numSwapchainImages(); // Now we can use the next set of semaphores
- // SwapBuffers not needed with Vulkan
- //glfwSwapBuffers(hwnd);
- }
- VkCommandBuffer DeviceResources::beginOneTimeSubmitCmd()
- {
- VkCommandBuffer cmdBuff = commandBuffer();
- VK_OK(vkResetCommandPool(m_device, commandPool(), 0));
- VkCommandBufferBeginInfo info{};
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
- VK_OK(vkBeginCommandBuffer(cmdBuff, &info));
- return cmdBuff;
- }
- void DeviceResources::endOneTimeSubmitCmd()
- {
- VkCommandBuffer cmdBuff = commandBuffer();
- VkSubmitInfo info{};
- info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- info.commandBufferCount = 1;
- info.pCommandBuffers = &cmdBuff;
- VK_OK(vkEndCommandBuffer(cmdBuff));
- VK_OK(vkQueueSubmit(m_queue, 1, &info, VK_NULL_HANDLE));
- VK_OK(vkDeviceWaitIdle(m_device));
- }
- void DeviceResources::createTexture2D(int w, int h, VkFormat format, const void* data, uint32_t rowPitch, uint32_t imageSize, VkImage* outImage, VkDeviceMemory* outDeviceMemory)
- {
- auto width = static_cast<uint32_t>(w);
- auto height = static_cast<uint32_t>(h);
- VkBuffer stagingBuff;
- VkDeviceMemory stagingBuffMem;
- createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
- &stagingBuff, &stagingBuffMem);
- void* mappedMem;
- VK_OK(vkMapMemory(m_device, stagingBuffMem, 0, imageSize, 0, &mappedMem));
- memcpy(mappedMem, data, imageSize);
- vkUnmapMemory(m_device, stagingBuffMem);
- // Create texture image object and backing memory
- {
- VkImageCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- info.imageType = VK_IMAGE_TYPE_2D;
- info.extent.width = width;
- info.extent.height = height;
- info.extent.depth = 1;
- info.mipLevels = 1;
- info.arrayLayers = 1;
- info.format = format;
- info.tiling = VK_IMAGE_TILING_OPTIMAL;
- info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
- info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- info.samples = VK_SAMPLE_COUNT_1_BIT;
- VK_OK(vkCreateImage(m_device, &info, nullptr, outImage));
- }
- {
- VkMemoryRequirements memReq{};
- vkGetImageMemoryRequirements(m_device, *outImage, &memReq);
- VkMemoryAllocateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- info.allocationSize = memReq.size;
- info.memoryTypeIndex = findMemoryTypeIndex(memReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- VK_OK(vkAllocateMemory(m_device, &info, nullptr, outDeviceMemory));
- VK_OK(vkBindImageMemory(m_device, *outImage, *outDeviceMemory, 0));
- }
- VkCommandBuffer cmdBuff = beginOneTimeSubmitCmd();
- {
- VkImageMemoryBarrier transferBarrier{};
- transferBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- transferBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- transferBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- transferBarrier.srcAccessMask = 0;
- transferBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- transferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- transferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- transferBarrier.image = *outImage;
- transferBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- transferBarrier.subresourceRange.levelCount = 1;
- transferBarrier.subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(cmdBuff, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &transferBarrier);
- VkBufferImageCopy buffImageCopyRegion{};
- buffImageCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- buffImageCopyRegion.imageSubresource.layerCount = 1;
- buffImageCopyRegion.imageExtent = { width, height, 1 };
- vkCmdCopyBufferToImage(cmdBuff, stagingBuff, *outImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffImageCopyRegion);
- VkImageMemoryBarrier useBarrier{};
- useBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- useBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- useBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- useBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- useBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
- useBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- useBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- useBarrier.image = *outImage;
- useBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- useBarrier.subresourceRange.levelCount = 1;
- useBarrier.subresourceRange.layerCount = 1;
- vkCmdPipelineBarrier(cmdBuff, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &useBarrier);
- }
- endOneTimeSubmitCmd();
- vkFreeMemory(m_device, stagingBuffMem, nullptr);
- vkDestroyBuffer(m_device, stagingBuff, nullptr);
- }
- void DeviceResources::createTexture2D(int w, int h, VkFormat format, VkImage* outImage, VkDeviceMemory* outDeviceMemory)
- {
- auto width = static_cast<uint32_t>(w);
- auto height = static_cast<uint32_t>(h);
- // Create texture image object and backing memory
- {
- VkImageCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- info.imageType = VK_IMAGE_TYPE_2D;
- info.extent.width = width;
- info.extent.height = height;
- info.extent.depth = 1;
- info.mipLevels = 1;
- info.arrayLayers = 1;
- info.format = format;
- info.tiling = VK_IMAGE_TILING_OPTIMAL;
- info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
- info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- info.samples = VK_SAMPLE_COUNT_1_BIT;
- VK_OK(vkCreateImage(m_device, &info, nullptr, outImage));
- }
- {
- VkMemoryRequirements memReq{};
- vkGetImageMemoryRequirements(m_device, *outImage, &memReq);
- VkMemoryAllocateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- info.allocationSize = memReq.size;
- info.memoryTypeIndex = findMemoryTypeIndex(memReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
- VK_OK(vkAllocateMemory(m_device, &info, nullptr, outDeviceMemory));
- VK_OK(vkBindImageMemory(m_device, *outImage, *outDeviceMemory, 0));
- }
- }
- void DeviceResources::createSRV(VkImage inputImage, VkFormat format, VkImageView* outSrv)
- {
- VkImageViewCreateInfo info{};
- info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- info.image = inputImage;
- info.viewType = VK_IMAGE_VIEW_TYPE_2D;
- info.format = format;
- info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- info.subresourceRange.layerCount = 1;
- info.subresourceRange.levelCount = 1;
- VK_OK(vkCreateImageView(m_device, &info, nullptr, outSrv));
- }
|