working mesh shader
This commit is contained in:
parent
c45afab0dd
commit
97ca634108
18 changed files with 2591 additions and 340 deletions
|
|
@ -8,6 +8,10 @@ module;
|
|||
#include <wayland-client.h>
|
||||
#include <thread>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <exception>
|
||||
#include "VulkanInitializers.hpp"
|
||||
#include "VulkanTransition.hpp"
|
||||
|
||||
module Crafter.Graphics;
|
||||
import Crafter.Event;
|
||||
|
|
@ -15,254 +19,443 @@ using namespace Crafter;
|
|||
|
||||
void WindowWaylandVulkan::CreateSwapchain()
|
||||
{
|
||||
VkResult result;
|
||||
|
||||
VkSurfaceCapabilitiesKHR capabilities;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VulkanDevice::physDevice, vulkanSurface, &capabilities));
|
||||
// Store the current swap chain handle so we can use it later on to ease up recreation
|
||||
VkSwapchainKHR oldSwapchain = swapChain;
|
||||
|
||||
uint32_t formatCount;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(VulkanDevice::physDevice, vulkanSurface, &formatCount, NULL));
|
||||
// Get physical device surface properties and formats
|
||||
VkSurfaceCapabilitiesKHR surfCaps;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VulkanDevice::physDevice, vulkanSurface, &surfCaps));
|
||||
|
||||
std::vector<VkSurfaceFormatKHR> formats(formatCount);
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(VulkanDevice::physDevice, vulkanSurface, &formatCount, formats.data()));
|
||||
VkExtent2D swapchainExtent = {};
|
||||
// If width (and height) equals the special value 0xFFFFFFFF, the size of the surface will be set by the swapchain
|
||||
if (surfCaps.currentExtent.width == (uint32_t)-1)
|
||||
{
|
||||
// If the surface size is undefined, the size is set to the size of the images requested
|
||||
swapchainExtent.width = width;
|
||||
swapchainExtent.height = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the surface size is defined, the swap chain size must match
|
||||
swapchainExtent = surfCaps.currentExtent;
|
||||
width = surfCaps.currentExtent.width;
|
||||
height = surfCaps.currentExtent.height;
|
||||
}
|
||||
|
||||
VkSurfaceFormatKHR chosenFormat = formats[0];
|
||||
|
||||
for (uint32_t i = 0; i < formatCount; i++)
|
||||
{
|
||||
if (formats[i].format == VK_FORMAT_B8G8R8A8_UNORM)
|
||||
{
|
||||
chosenFormat = formats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Select a present mode for the swapchain
|
||||
uint32_t presentModeCount;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(VulkanDevice::physDevice, vulkanSurface, &presentModeCount, NULL));
|
||||
assert(presentModeCount > 0);
|
||||
|
||||
format = chosenFormat.format;
|
||||
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfacePresentModesKHR(VulkanDevice::physDevice, vulkanSurface, &presentModeCount, presentModes.data()));
|
||||
|
||||
imageCount = capabilities.minImageCount + 1 < capabilities.maxImageCount ? capabilities.minImageCount + 1 : capabilities.minImageCount;
|
||||
// The VK_PRESENT_MODE_FIFO_KHR mode must always be present as per spec
|
||||
// This mode waits for the vertical blank ("v-sync")
|
||||
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
|
||||
VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
|
||||
swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
swapchainCreateInfo.surface = vulkanSurface;
|
||||
swapchainCreateInfo.minImageCount = imageCount;
|
||||
swapchainCreateInfo.imageFormat = chosenFormat.format;
|
||||
swapchainCreateInfo.imageColorSpace = chosenFormat.colorSpace;
|
||||
swapchainCreateInfo.imageExtent.width = width;
|
||||
swapchainCreateInfo.imageExtent.height = height;
|
||||
swapchainCreateInfo.imageArrayLayers = 1;
|
||||
swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
swapchainCreateInfo.preTransform = capabilities.currentTransform;
|
||||
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
swapchainCreateInfo.presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
swapchainCreateInfo.clipped = 1;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateSwapchainKHR(VulkanDevice::device, &swapchainCreateInfo, NULL, &swapchain));
|
||||
|
||||
VkAttachmentDescription attachment = {};
|
||||
attachment.format = format;
|
||||
attachment.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
// Determine the number of images
|
||||
uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;
|
||||
if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount))
|
||||
{
|
||||
desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
|
||||
}
|
||||
|
||||
VkAttachmentReference attachmentRef = {};
|
||||
attachmentRef.attachment = 0;
|
||||
attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
// Find the transformation of the surface
|
||||
VkSurfaceTransformFlagsKHR preTransform;
|
||||
if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
|
||||
{
|
||||
// We prefer a non-rotated transform
|
||||
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||
}
|
||||
else
|
||||
{
|
||||
preTransform = surfCaps.currentTransform;
|
||||
}
|
||||
|
||||
VkSubpassDescription subpass = {};
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpass.colorAttachmentCount = 1;
|
||||
subpass.pColorAttachments = &attachmentRef;
|
||||
// Find a supported composite alpha format (not all devices support alpha opaque)
|
||||
VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
// Simply select the first composite alpha format available
|
||||
std::vector<VkCompositeAlphaFlagBitsKHR> compositeAlphaFlags = {
|
||||
VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
||||
VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
|
||||
VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
|
||||
VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
|
||||
};
|
||||
for (auto& compositeAlphaFlag : compositeAlphaFlags) {
|
||||
if (surfCaps.supportedCompositeAlpha & compositeAlphaFlag) {
|
||||
compositeAlpha = compositeAlphaFlag;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
VkRenderPassCreateInfo renderPasscreateInfo = {};
|
||||
renderPasscreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
renderPasscreateInfo.flags = 0;
|
||||
renderPasscreateInfo.attachmentCount = 1;
|
||||
renderPasscreateInfo.pAttachments = &attachment;
|
||||
renderPasscreateInfo.subpassCount = 1;
|
||||
renderPasscreateInfo.pSubpasses = &subpass;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateRenderPass(VulkanDevice::device, &renderPasscreateInfo, NULL, &renderPass));
|
||||
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetSwapchainImagesKHR(VulkanDevice::device, swapchain, &imageCount, NULL));
|
||||
VkSwapchainCreateInfoKHR swapchainCI = {};
|
||||
swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
swapchainCI.surface = vulkanSurface;
|
||||
swapchainCI.minImageCount = desiredNumberOfSwapchainImages;
|
||||
swapchainCI.imageFormat = colorFormat;
|
||||
swapchainCI.imageColorSpace = colorSpace;
|
||||
swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height };
|
||||
swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
swapchainCI.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform;
|
||||
swapchainCI.imageArrayLayers = 1;
|
||||
swapchainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
swapchainCI.queueFamilyIndexCount = 0;
|
||||
swapchainCI.presentMode = swapchainPresentMode;
|
||||
// Setting oldSwapChain to the saved handle of the previous swapchain aids in resource reuse and makes sure that we can still present already acquired images
|
||||
swapchainCI.oldSwapchain = oldSwapchain;
|
||||
// Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the surface area
|
||||
swapchainCI.clipped = VK_TRUE;
|
||||
swapchainCI.compositeAlpha = compositeAlpha;
|
||||
|
||||
std::vector<VkImage> images(imageCount);
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetSwapchainImagesKHR(VulkanDevice::device, swapchain, &imageCount, images.data()));
|
||||
// Enable transfer source on swap chain images if supported
|
||||
if (surfCaps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
|
||||
swapchainCI.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
}
|
||||
|
||||
swapchainElements.resize(imageCount);
|
||||
// Enable transfer destination on swap chain images if supported
|
||||
if (surfCaps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
|
||||
swapchainCI.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < imageCount; i++)
|
||||
{
|
||||
VkCommandBufferAllocateInfo commandBufferAllocInfo = {};
|
||||
commandBufferAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
commandBufferAllocInfo.commandPool = VulkanDevice::commandPool;
|
||||
commandBufferAllocInfo.commandBufferCount = 1;
|
||||
commandBufferAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||
vkAllocateCommandBuffers(VulkanDevice::device, &commandBufferAllocInfo, &swapchainElements[i].commandBuffer);
|
||||
|
||||
swapchainElements[i].image = images[i];
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateSwapchainKHR(VulkanDevice::device, &swapchainCI, nullptr, &swapChain));
|
||||
|
||||
VkImageViewCreateInfo imageViewcreateInfo = {};
|
||||
imageViewcreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
imageViewcreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
imageViewcreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
imageViewcreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
imageViewcreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
imageViewcreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||
imageViewcreateInfo.subresourceRange.baseMipLevel = 0;
|
||||
imageViewcreateInfo.subresourceRange.levelCount = 1;
|
||||
imageViewcreateInfo.subresourceRange.baseArrayLayer = 0;
|
||||
imageViewcreateInfo.subresourceRange.layerCount = 1;
|
||||
imageViewcreateInfo.image = swapchainElements[i].image;
|
||||
imageViewcreateInfo.format = format;
|
||||
imageViewcreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateImageView(VulkanDevice::device, &imageViewcreateInfo, NULL, &swapchainElements[i].imageView));
|
||||
|
||||
VkFramebufferCreateInfo framebufferCreateInfo = {};
|
||||
framebufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
framebufferCreateInfo.renderPass = renderPass;
|
||||
framebufferCreateInfo.attachmentCount = 1;
|
||||
framebufferCreateInfo.pAttachments = &swapchainElements[i].imageView;
|
||||
framebufferCreateInfo.width = width;
|
||||
framebufferCreateInfo.height = height;
|
||||
framebufferCreateInfo.layers = 1;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateFramebuffer(VulkanDevice::device, &framebufferCreateInfo, NULL, &swapchainElements[i].framebuffer));
|
||||
|
||||
VkSemaphoreCreateInfo startSemaphoreCreateInfo = {};
|
||||
startSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateSemaphore(VulkanDevice::device, &startSemaphoreCreateInfo, NULL, &swapchainElements[i].startSemaphore));
|
||||
|
||||
VkSemaphoreCreateInfo endSemaphoreCreateInfo = {};
|
||||
endSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateSemaphore(VulkanDevice::device, &endSemaphoreCreateInfo, NULL, &swapchainElements[i].endSemaphore));
|
||||
|
||||
VkFenceCreateInfo fenceCreateInfo = {};
|
||||
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateFence(VulkanDevice::device, &fenceCreateInfo, NULL, &swapchainElements[i].fence));
|
||||
// If an existing swap chain is re-created, destroy the old swap chain and the ressources owned by the application (image views, images are owned by the swap chain)
|
||||
if (oldSwapchain != VK_NULL_HANDLE) {
|
||||
for (auto i = 0; i < images.size(); i++) {
|
||||
vkDestroyImageView(VulkanDevice::device, imageViews[i], nullptr);
|
||||
}
|
||||
vkDestroySwapchainKHR(VulkanDevice::device, oldSwapchain, nullptr);
|
||||
}
|
||||
uint32_t imageCount{ 0 };
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetSwapchainImagesKHR(VulkanDevice::device, swapChain, &imageCount, nullptr));
|
||||
|
||||
swapchainElements[i].lastFence = VK_NULL_HANDLE;
|
||||
}
|
||||
// Get the swap chain images
|
||||
images.resize(imageCount);
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetSwapchainImagesKHR(VulkanDevice::device, swapChain, &imageCount, images.data()));
|
||||
|
||||
// Get the swap chain buffers containing the image and imageview
|
||||
imageViews.resize(imageCount);
|
||||
for (auto i = 0; i < images.size(); i++)
|
||||
{
|
||||
VkImageViewCreateInfo colorAttachmentView = {};
|
||||
colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
colorAttachmentView.pNext = NULL;
|
||||
colorAttachmentView.format = colorFormat;
|
||||
colorAttachmentView.components = {
|
||||
VK_COMPONENT_SWIZZLE_R,
|
||||
VK_COMPONENT_SWIZZLE_G,
|
||||
VK_COMPONENT_SWIZZLE_B,
|
||||
VK_COMPONENT_SWIZZLE_A
|
||||
};
|
||||
colorAttachmentView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
colorAttachmentView.subresourceRange.baseMipLevel = 0;
|
||||
colorAttachmentView.subresourceRange.levelCount = 1;
|
||||
colorAttachmentView.subresourceRange.baseArrayLayer = 0;
|
||||
colorAttachmentView.subresourceRange.layerCount = 1;
|
||||
colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
colorAttachmentView.flags = 0;
|
||||
colorAttachmentView.image = images[i];
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateImageView(VulkanDevice::device, &colorAttachmentView, nullptr, &imageViews[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void WindowWaylandVulkan::DestroySwapchain()
|
||||
{
|
||||
for (uint32_t i = 0; i < imageCount; i++)
|
||||
{
|
||||
vkDestroyFence(VulkanDevice::device, swapchainElements[i].fence, NULL);
|
||||
vkDestroySemaphore(VulkanDevice::device, swapchainElements[i].endSemaphore, NULL);
|
||||
vkDestroySemaphore(VulkanDevice::device, swapchainElements[i].startSemaphore, NULL);
|
||||
vkDestroyFramebuffer(VulkanDevice::device, swapchainElements[i].framebuffer, NULL);
|
||||
vkDestroyImageView(VulkanDevice::device, swapchainElements[i].imageView, NULL);
|
||||
vkFreeCommandBuffers(VulkanDevice::device, VulkanDevice::commandPool, 1, &swapchainElements[i].commandBuffer);
|
||||
}
|
||||
|
||||
vkDestroyRenderPass(VulkanDevice::device, renderPass, NULL);
|
||||
vkDestroySwapchainKHR(VulkanDevice::device, swapchain, NULL);
|
||||
}
|
||||
|
||||
PFN_vkCmdDrawMeshTasksEXT command;
|
||||
|
||||
WindowWaylandVulkan::WindowWaylandVulkan(std::string name, std::uint32_t width, std::uint32_t height) : WindowWayland(name, width, height) {
|
||||
VkWaylandSurfaceCreateInfoKHR createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
|
||||
createInfo.display = display;
|
||||
createInfo.surface = surface;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateWaylandSurfaceKHR(VulkanDevice::instance, &createInfo, NULL, &vulkanSurface));
|
||||
|
||||
// Get list of supported surface formats
|
||||
std::uint32_t formatCount;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(VulkanDevice::physDevice, vulkanSurface, &formatCount, NULL));
|
||||
assert(formatCount > 0);
|
||||
|
||||
std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
|
||||
VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(VulkanDevice::physDevice, vulkanSurface, &formatCount, surfaceFormats.data()));
|
||||
|
||||
// We want to get a format that best suits our needs, so we try to get one from a set of preferred formats
|
||||
// Initialize the format to the first one returned by the implementation in case we can't find one of the preffered formats
|
||||
VkSurfaceFormatKHR selectedFormat = surfaceFormats[0];
|
||||
std::vector<VkFormat> preferredImageFormats = {
|
||||
VK_FORMAT_R8G8B8A8_UNORM,
|
||||
};
|
||||
|
||||
for (auto& availableFormat : surfaceFormats) {
|
||||
if (std::find(preferredImageFormats.begin(), preferredImageFormats.end(), availableFormat.format) != preferredImageFormats.end()) {
|
||||
selectedFormat = availableFormat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
colorFormat = selectedFormat.format;
|
||||
colorSpace = selectedFormat.colorSpace;
|
||||
|
||||
CreateSwapchain();
|
||||
command = reinterpret_cast<PFN_vkCmdDrawMeshTasksEXT>(vkGetDeviceProcAddr(VulkanDevice::device, "vkCmdDrawMeshTasksEXT"));
|
||||
|
||||
std::array<VkAttachmentDescription, 2> attachments = {};
|
||||
// Color attachment
|
||||
attachments[0].format = colorFormat;
|
||||
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
// Depth attachment
|
||||
attachments[1].format = VulkanDevice::depthFormat;
|
||||
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkAttachmentReference colorReference = {};
|
||||
colorReference.attachment = 0;
|
||||
colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkAttachmentReference depthReference = {};
|
||||
depthReference.attachment = 1;
|
||||
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
VkSubpassDescription subpassDescription = {};
|
||||
subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpassDescription.colorAttachmentCount = 1;
|
||||
subpassDescription.pColorAttachments = &colorReference;
|
||||
subpassDescription.pDepthStencilAttachment = &depthReference;
|
||||
subpassDescription.inputAttachmentCount = 0;
|
||||
subpassDescription.pInputAttachments = nullptr;
|
||||
subpassDescription.preserveAttachmentCount = 0;
|
||||
subpassDescription.pPreserveAttachments = nullptr;
|
||||
subpassDescription.pResolveAttachments = nullptr;
|
||||
|
||||
// Subpass dependencies for layout transitions
|
||||
std::array<VkSubpassDependency, 2> dependencies{};
|
||||
|
||||
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||
dependencies[0].dstSubpass = 0;
|
||||
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
dependencies[0].srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
dependencies[0].dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
|
||||
dependencies[0].dependencyFlags = 0;
|
||||
|
||||
dependencies[1].srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||
dependencies[1].dstSubpass = 0;
|
||||
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
dependencies[1].srcAccessMask = 0;
|
||||
dependencies[1].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
|
||||
dependencies[1].dependencyFlags = 0;
|
||||
|
||||
VkRenderPassCreateInfo renderPassInfo = {};
|
||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
|
||||
renderPassInfo.pAttachments = attachments.data();
|
||||
renderPassInfo.subpassCount = 1;
|
||||
renderPassInfo.pSubpasses = &subpassDescription;
|
||||
renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
|
||||
renderPassInfo.pDependencies = dependencies.data();
|
||||
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateRenderPass(VulkanDevice::device, &renderPassInfo, nullptr, &renderPass));
|
||||
|
||||
VkImageCreateInfo imageCI{};
|
||||
imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
imageCI.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageCI.format = VulkanDevice::depthFormat;
|
||||
imageCI.extent = { width, height, 1 };
|
||||
imageCI.mipLevels = 1;
|
||||
imageCI.arrayLayers = 1;
|
||||
imageCI.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageCI.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageCI.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateImage(VulkanDevice::device, &imageCI, nullptr, &depthStencil.image));
|
||||
VkMemoryRequirements memReqs{};
|
||||
vkGetImageMemoryRequirements(VulkanDevice::device, depthStencil.image, &memReqs);
|
||||
|
||||
VkMemoryAllocateInfo memAllloc{};
|
||||
memAllloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
memAllloc.allocationSize = memReqs.size;
|
||||
memAllloc.memoryTypeIndex = VulkanDevice::GetMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VulkanDevice::CHECK_VK_RESULT(vkAllocateMemory(VulkanDevice::device, &memAllloc, nullptr, &depthStencil.memory));
|
||||
VulkanDevice::CHECK_VK_RESULT(vkBindImageMemory(VulkanDevice::device, depthStencil.image, depthStencil.memory, 0));
|
||||
|
||||
VkImageViewCreateInfo imageViewCI{};
|
||||
imageViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
imageViewCI.image = depthStencil.image;
|
||||
imageViewCI.format = VulkanDevice::depthFormat;
|
||||
imageViewCI.subresourceRange.baseMipLevel = 0;
|
||||
imageViewCI.subresourceRange.levelCount = 1;
|
||||
imageViewCI.subresourceRange.baseArrayLayer = 0;
|
||||
imageViewCI.subresourceRange.layerCount = 1;
|
||||
imageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateImageView(VulkanDevice::device, &imageViewCI, nullptr, &depthStencil.view));
|
||||
|
||||
// Create frame buffers for every swap chain image
|
||||
frameBuffers.resize(images.size());
|
||||
for (uint32_t i = 0; i < frameBuffers.size(); i++)
|
||||
{
|
||||
const VkImageView attachments[2] = {
|
||||
imageViews[i],
|
||||
depthStencil.view
|
||||
};
|
||||
VkFramebufferCreateInfo frameBufferCreateInfo{};
|
||||
frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||
frameBufferCreateInfo.renderPass = renderPass;
|
||||
frameBufferCreateInfo.attachmentCount = 2;
|
||||
frameBufferCreateInfo.pAttachments = attachments;
|
||||
frameBufferCreateInfo.width = width;
|
||||
frameBufferCreateInfo.height = height;
|
||||
frameBufferCreateInfo.layers = 1;
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateFramebuffer(VulkanDevice::device, &frameBufferCreateInfo, nullptr, &frameBuffers[i]));
|
||||
}
|
||||
|
||||
drawCmdBuffers.resize(images.size());
|
||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(VulkanDevice::commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, static_cast<uint32_t>(drawCmdBuffers.size()));
|
||||
VulkanDevice::CHECK_VK_RESULT(vkAllocateCommandBuffers(VulkanDevice::device, &cmdBufAllocateInfo, drawCmdBuffers.data()));
|
||||
|
||||
VkSemaphoreCreateInfo semaphoreCreateInfo = vks::initializers::semaphoreCreateInfo();
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateSemaphore(VulkanDevice::device, &semaphoreCreateInfo, nullptr, &semaphores.presentComplete));
|
||||
VulkanDevice::CHECK_VK_RESULT(vkCreateSemaphore(VulkanDevice::device, &semaphoreCreateInfo, nullptr, &semaphores.renderComplete));
|
||||
|
||||
// Set up submit info structure
|
||||
// Semaphores will stay the same during application lifetime
|
||||
// Command buffer submission info is set by each example
|
||||
submitInfo = vks::initializers::submitInfo();
|
||||
submitInfo.pWaitDstStageMask = &submitPipelineStages;
|
||||
submitInfo.waitSemaphoreCount = 1;
|
||||
submitInfo.pWaitSemaphores = &semaphores.presentComplete;
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
submitInfo.pSignalSemaphores = &semaphores.renderComplete;
|
||||
}
|
||||
|
||||
WindowWaylandVulkan::~WindowWaylandVulkan() {
|
||||
if (swapChain != VK_NULL_HANDLE) {
|
||||
for (auto i = 0; i < images.size(); i++) {
|
||||
vkDestroyImageView(VulkanDevice::device, imageViews[i], nullptr);
|
||||
}
|
||||
vkDestroySwapchainKHR(VulkanDevice::device, swapChain, nullptr);
|
||||
}
|
||||
if (vulkanSurface != VK_NULL_HANDLE) {
|
||||
vkDestroySurfaceKHR(VulkanDevice::instance, vulkanSurface, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowWaylandVulkan::Start() {
|
||||
thread = std::thread([this](){
|
||||
while (open && wl_display_dispatch(display) != -1) {
|
||||
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
|
||||
|
||||
}
|
||||
});
|
||||
while(true) {
|
||||
SwapchainElement* currentElement = &swapchainElements[currentFrame];
|
||||
VkClearValue clearValues[2];
|
||||
clearValues[0].color = { };;
|
||||
clearValues[1].depthStencil = { 1.0f, 0 };
|
||||
|
||||
VulkanDevice::CHECK_VK_RESULT(vkWaitForFences(VulkanDevice::device, 1, ¤tElement->fence, 1, UINT64_MAX));
|
||||
VulkanDevice::CHECK_VK_RESULT(vkAcquireNextImageKHR(VulkanDevice::device, swapchain, UINT64_MAX, currentElement->startSemaphore, NULL, &imageIndex));
|
||||
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
|
||||
{
|
||||
VulkanDevice::CHECK_VK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
|
||||
|
||||
SwapchainElement* element = &swapchainElements[imageIndex];
|
||||
if (element->lastFence) {
|
||||
VulkanDevice::CHECK_VK_RESULT(vkWaitForFences(VulkanDevice::device, 1, &element->lastFence, 1, UINT64_MAX));
|
||||
}
|
||||
VkImageSubresourceRange range{};
|
||||
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
range.baseMipLevel = 0;
|
||||
range.levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
range.baseArrayLayer = 0;
|
||||
range.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
||||
|
||||
element->lastFence = currentElement->fence;
|
||||
VkImageSubresourceRange depth_range{range};
|
||||
depth_range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
|
||||
VulkanDevice::CHECK_VK_RESULT(vkResetFences(VulkanDevice::device, 1, ¤tElement->fence));
|
||||
image_layout_transition(drawCmdBuffers[i],
|
||||
images[i],
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
0,
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
range);
|
||||
|
||||
VkCommandBufferBeginInfo commandBeginInfo = {};
|
||||
commandBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
commandBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
image_layout_transition(drawCmdBuffers[i],
|
||||
depthStencil.image,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
|
||||
depth_range);
|
||||
|
||||
VulkanDevice::CHECK_VK_RESULT(vkBeginCommandBuffer(element->commandBuffer, &commandBeginInfo));
|
||||
|
||||
VkClearValue clearValue = {{
|
||||
1.0f,
|
||||
0.0f,
|
||||
1.0f,
|
||||
1.0f
|
||||
}};
|
||||
VkRenderingAttachmentInfoKHR color_attachment_info = {VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, VK_NULL_HANDLE};
|
||||
color_attachment_info.imageView = imageViews[i];
|
||||
color_attachment_info.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
color_attachment_info.resolveMode = VK_RESOLVE_MODE_NONE;
|
||||
color_attachment_info.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
color_attachment_info.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
color_attachment_info.clearValue = { 0.0f, 0.0f, 0.2f, 1.0f };
|
||||
|
||||
VkRenderPassBeginInfo renderBeginInfo = {};
|
||||
renderBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
renderBeginInfo.renderPass = renderPass;
|
||||
renderBeginInfo.framebuffer = element->framebuffer;
|
||||
renderBeginInfo.renderArea.offset.x = 0;
|
||||
renderBeginInfo.renderArea.offset.y = 0;
|
||||
renderBeginInfo.renderArea.extent.width = width;
|
||||
renderBeginInfo.renderArea.extent.height = height;
|
||||
renderBeginInfo.clearValueCount = 1;
|
||||
renderBeginInfo.pClearValues = &clearValue;
|
||||
VkRenderingAttachmentInfoKHR depth_attachment_info = {VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, VK_NULL_HANDLE};
|
||||
depth_attachment_info.imageView = depthStencil.view;
|
||||
depth_attachment_info.imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
|
||||
depth_attachment_info.resolveMode = VK_RESOLVE_MODE_NONE;
|
||||
depth_attachment_info.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
depth_attachment_info.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
depth_attachment_info.clearValue = { 1.0f, 0 };
|
||||
|
||||
vkCmdBeginRenderPass(element->commandBuffer, &renderBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||
VkRenderingInfo render_info = {VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,VK_NULL_HANDLE,0};
|
||||
render_info.renderArea = VkRect2D{VkOffset2D{}, VkExtent2D{width, height}};
|
||||
render_info.viewMask = 0;
|
||||
render_info.layerCount = 1;
|
||||
render_info.colorAttachmentCount = 1;
|
||||
render_info.pColorAttachments = &color_attachment_info;
|
||||
render_info.pDepthAttachment = &depth_attachment_info;
|
||||
render_info.pStencilAttachment = VK_NULL_HANDLE;
|
||||
|
||||
VkViewport viewport = {0, 0, static_cast<float>(width), static_cast<float>(height), 0, 1};
|
||||
vkCmdSetViewport(element->commandBuffer, 0, 1, &viewport);
|
||||
VulkanDevice::vkCmdBeginRenderingKHRProc(drawCmdBuffers[i], &render_info);
|
||||
|
||||
VkRect2D scissor = {{static_cast<std::int32_t>(width), static_cast<std::int32_t>(height)},{0,0}};
|
||||
vkCmdSetScissor(element->commandBuffer, 0, 1, &scissor);
|
||||
VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
|
||||
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
|
||||
|
||||
vkCmdBindDescriptorSets(element->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, VulkanPipeline<VulkanShader<"test.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT>, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::layout, 0, 1, &VulkanPipeline<VulkanShader<"test.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT>, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::descriptor_set, 0, nullptr);
|
||||
vkCmdBindPipeline(element->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, VulkanPipeline<VulkanShader<"test.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT>, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::pipeline);
|
||||
|
||||
command(element->commandBuffer, 1, 1, 1);
|
||||
VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
|
||||
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
|
||||
|
||||
vkCmdEndRenderPass(element->commandBuffer);
|
||||
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, VulkanPipeline<VulkanShader<"test.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT>, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::pipelineLayout, 0, 1, &VulkanPipeline<VulkanShader<"test.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT>, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::descriptorSet, 0, NULL);
|
||||
|
||||
VulkanDevice::CHECK_VK_RESULT(vkEndCommandBuffer(element->commandBuffer));
|
||||
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, VulkanPipeline<VulkanShader<"test.spirv", "main", VK_SHADER_STAGE_MESH_BIT_EXT>, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::pipeline);
|
||||
|
||||
const VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
// Use mesh and task shader to draw the scene
|
||||
VulkanDevice::vkCmdDrawMeshTasksEXTProc(drawCmdBuffers[i], 3, 1, 1);
|
||||
|
||||
VkSubmitInfo submitInfo = {};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
submitInfo.waitSemaphoreCount = 1;
|
||||
submitInfo.pWaitSemaphores = ¤tElement->startSemaphore;
|
||||
submitInfo.pWaitDstStageMask = &waitStage;
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &element->commandBuffer;
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
submitInfo.pSignalSemaphores = ¤tElement->endSemaphore;
|
||||
VulkanDevice::vkCmdEndRenderingKHRProc(drawCmdBuffers[i]);
|
||||
|
||||
VulkanDevice::CHECK_VK_RESULT(vkQueueSubmit(VulkanDevice::queue, 1, &submitInfo, currentElement->fence));
|
||||
image_layout_transition(drawCmdBuffers[i],
|
||||
images[i],
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
range
|
||||
);
|
||||
|
||||
VkPresentInfoKHR presentInfo = {};
|
||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
presentInfo.waitSemaphoreCount = 1;
|
||||
presentInfo.pWaitSemaphores = ¤tElement->endSemaphore;
|
||||
presentInfo.swapchainCount = 1;
|
||||
presentInfo.pSwapchains = &swapchain;
|
||||
presentInfo.pImageIndices = &imageIndex;
|
||||
|
||||
VulkanDevice::CHECK_VK_RESULT(vkQueuePresentKHR(VulkanDevice::queue, &presentInfo));
|
||||
|
||||
currentFrame = (currentFrame + 1) % imageCount;
|
||||
|
||||
wl_display_roundtrip(display);
|
||||
VulkanDevice::CHECK_VK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));
|
||||
}
|
||||
}
|
||||
while (open && wl_display_dispatch(display) != -1) {
|
||||
// Acquire the next image from the swap chain
|
||||
VulkanDevice::CHECK_VK_RESULT(vkAcquireNextImageKHR(VulkanDevice::device, swapChain, UINT64_MAX, semaphores.presentComplete, (VkFence)nullptr, ¤tBuffer));
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
|
||||
VulkanDevice::CHECK_VK_RESULT(vkQueueSubmit(VulkanDevice::queue, 1, &submitInfo, VK_NULL_HANDLE));
|
||||
VkPresentInfoKHR presentInfo = {};
|
||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
presentInfo.pNext = NULL;
|
||||
presentInfo.swapchainCount = 1;
|
||||
presentInfo.pSwapchains = &swapChain;
|
||||
presentInfo.pImageIndices = ¤tBuffer;
|
||||
// Check if a wait semaphore has been specified to wait for before presenting the image
|
||||
if (semaphores.renderComplete != VK_NULL_HANDLE)
|
||||
{
|
||||
presentInfo.pWaitSemaphores = &semaphores.renderComplete;
|
||||
presentInfo.waitSemaphoreCount = 1;
|
||||
}
|
||||
VulkanDevice::CHECK_VK_RESULT(vkQueuePresentKHR(VulkanDevice::queue, &presentInfo));
|
||||
VulkanDevice::CHECK_VK_RESULT(vkQueueWaitIdle(VulkanDevice::queue));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue