module; #include #include #include #include #include #include #include #include module Crafter.Graphics; import Crafter.Event; using namespace Crafter; void WindowWaylandVulkan::CreateSwapchain() { VkResult result; VkSurfaceCapabilitiesKHR capabilities; VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VulkanDevice::physDevice, vulkanSurface, &capabilities)); uint32_t formatCount; VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(VulkanDevice::physDevice, vulkanSurface, &formatCount, NULL)); std::vector formats(formatCount); VulkanDevice::CHECK_VK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(VulkanDevice::physDevice, vulkanSurface, &formatCount, formats.data())); VkSurfaceFormatKHR chosenFormat = formats[0]; for (uint32_t i = 0; i < formatCount; i++) { if (formats[i].format == VK_FORMAT_B8G8R8A8_UNORM) { chosenFormat = formats[i]; break; } } format = chosenFormat.format; imageCount = capabilities.minImageCount + 1 < capabilities.maxImageCount ? capabilities.minImageCount + 1 : capabilities.minImageCount; 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; VkAttachmentReference attachmentRef = {}; attachmentRef.attachment = 0; attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkSubpassDescription subpass = {}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &attachmentRef; 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)); std::vector images(imageCount); VulkanDevice::CHECK_VK_RESULT(vkGetSwapchainImagesKHR(VulkanDevice::device, swapchain, &imageCount, images.data())); swapchainElements.resize(imageCount); 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]; 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)); swapchainElements[i].lastFence = VK_NULL_HANDLE; } } 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)); CreateSwapchain(); command = reinterpret_cast(vkGetDeviceProcAddr(VulkanDevice::device, "vkCmdDrawMeshTasksEXT")); } void WindowWaylandVulkan::Start() { thread = std::thread([this](){ while (open && wl_display_dispatch(display) != -1) { } }); while(true) { SwapchainElement* currentElement = &swapchainElements[currentFrame]; 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)); SwapchainElement* element = &swapchainElements[imageIndex]; if (element->lastFence) { VulkanDevice::CHECK_VK_RESULT(vkWaitForFences(VulkanDevice::device, 1, &element->lastFence, 1, UINT64_MAX)); } element->lastFence = currentElement->fence; VulkanDevice::CHECK_VK_RESULT(vkResetFences(VulkanDevice::device, 1, ¤tElement->fence)); VkCommandBufferBeginInfo commandBeginInfo = {}; commandBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; commandBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; VulkanDevice::CHECK_VK_RESULT(vkBeginCommandBuffer(element->commandBuffer, &commandBeginInfo)); VkClearValue clearValue = {{ 1.0f, 0.0f, 1.0f, 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; vkCmdBeginRenderPass(element->commandBuffer, &renderBeginInfo, VK_SUBPASS_CONTENTS_INLINE); VkViewport viewport = {0, 0, static_cast(width), static_cast(height), 0, 1}; vkCmdSetViewport(element->commandBuffer, 0, 1, &viewport); VkRect2D scissor = {{static_cast(width), static_cast(height)},{0,0}}; vkCmdSetScissor(element->commandBuffer, 0, 1, &scissor); vkCmdBindDescriptorSets(element->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, VulkanPipeline, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::layout, 0, 1, &VulkanPipeline, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::descriptor_set, 0, nullptr); vkCmdBindPipeline(element->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, VulkanPipeline, VulkanShader<"test2.spirv", "main", VK_SHADER_STAGE_FRAGMENT_BIT>>::pipeline); command(element->commandBuffer, 1, 1, 1); vkCmdEndRenderPass(element->commandBuffer); VulkanDevice::CHECK_VK_RESULT(vkEndCommandBuffer(element->commandBuffer)); const VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 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::CHECK_VK_RESULT(vkQueueSubmit(VulkanDevice::queue, 1, &submitInfo, currentElement->fence)); 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); } }