void op3d::Engine::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) { VkCommandBuffer commandBuffer = commandBufferManager.beginSingleTimeCommands(); VkImageMemoryBarrier barrier = {}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.oldLayout = oldLayout; barrier.newLayout = newLayout; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.image = image; barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; barrier.subresourceRange.baseMipLevel = 0; barrier.subresourceRange.levelCount = 1; barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.layerCount = 1; if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; if (hasStencilComponent(format)) { barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; } } else { barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; } if (oldLayout == VK_IMAGE_LAYOUT_PREINITIALIZED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) { barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; } else if (oldLayout == VK_IMAGE_LAYOUT_PREINITIALIZED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; } else if(oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { barrier.srcAccessMask = 0; barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; } else { throw std::invalid_argument("unsupported layout transition!"); } vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier ); commandBufferManager.endSingleTimeCommands(commandBuffer, graphicsQueue); }
void VkHelper::transitImageLayout(VkDevice device, VkCommandPool cmdPool, VkQueue queue, VkImage img, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) { VkCommandBuffer cmdBuffer = beginSingleTimeCommandBufffer(device, cmdPool); VkImageMemoryBarrier barrier{}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.pNext = VK_NULL_HANDLE; barrier.oldLayout = oldLayout; barrier.newLayout = newLayout; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.image = img; barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.layerCount = 1; barrier.subresourceRange.baseMipLevel = 0; barrier.subresourceRange.levelCount = 1; if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; if (hasStencilComponent(format)) { barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; } } else { barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; } auto isInInitialState = [oldLayout]() -> bool { return oldLayout == VK_IMAGE_LAYOUT_PREINITIALIZED || oldLayout == VK_IMAGE_LAYOUT_UNDEFINED; }; VkPipelineStageFlags srcStageFlag, dstStageFlag; if (isInInitialState() && newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) { barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; srcStageFlag = VK_PIPELINE_STAGE_HOST_BIT; dstStageFlag = VK_PIPELINE_STAGE_TRANSFER_BIT; } else if (isInInitialState() && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; srcStageFlag = VK_PIPELINE_STAGE_HOST_BIT; dstStageFlag = VK_PIPELINE_STAGE_TRANSFER_BIT; } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; srcStageFlag = VK_PIPELINE_STAGE_TRANSFER_BIT; dstStageFlag = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; } else if (isInInitialState() && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { barrier.srcAccessMask = 0; barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; srcStageFlag = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dstStageFlag = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; } else { throw std::runtime_error("ERROR: Not supported layouts."); } vkCmdPipelineBarrier( cmdBuffer, srcStageFlag, dstStageFlag, 0, 0, nullptr, 0, nullptr, 1, &barrier); endSingleTimeCommandBuffer(device, cmdPool, queue, cmdBuffer); }
bool _agpu_swap_chain::initialize(agpu_swap_chain_create_info *createInfo) { swapChainWidth = createInfo->width; swapChainHeight = createInfo->height; VkSurfaceCapabilitiesKHR surfaceCapabilities; auto error = device->fpGetPhysicalDeviceSurfaceCapabilitiesKHR(device->physicalDevice, surface, &surfaceCapabilities); if (error) return false; uint32_t presentModeCount; error = device->fpGetPhysicalDeviceSurfacePresentModesKHR(device->physicalDevice, surface, &presentModeCount, nullptr); if (error) return false; std::vector<VkPresentModeKHR> presentModes(presentModeCount); error = device->fpGetPhysicalDeviceSurfacePresentModesKHR(device->physicalDevice, surface, &presentModeCount, &presentModes[0]); if (error) return false; VkExtent2D swapchainExtent; if (surfaceCapabilities.currentExtent.width == (uint32_t)-1) { swapchainExtent.width = swapChainWidth; swapchainExtent.height = swapChainHeight; } else { swapchainExtent = surfaceCapabilities.currentExtent; swapChainWidth = swapchainExtent.width; swapChainHeight = swapchainExtent.height; } VkPresentModeKHR swapchainPresentMode = presentModes[0]; for (size_t i = 0; i < presentModeCount; i++) { if (presentModes[i] == VK_PRESENT_MODE_FIFO_KHR) { swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; } if (presentModes[i] == VK_PRESENT_MODE_FIFO_RELAXED_KHR) { swapchainPresentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR; break; } } uint32_t desiredNumberOfSwapchainImages = std::max(surfaceCapabilities.minImageCount, createInfo->buffer_count); if ((surfaceCapabilities.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfaceCapabilities.maxImageCount)) desiredNumberOfSwapchainImages = surfaceCapabilities.maxImageCount; VkSurfaceTransformFlagsKHR preTransform; if (surfaceCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; } else { preTransform = surfaceCapabilities.currentTransform; } VkSwapchainCreateInfoKHR swapchainInfo; memset(&swapchainInfo, 0, sizeof(swapchainInfo)); swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainInfo.surface = surface; swapchainInfo.minImageCount = desiredNumberOfSwapchainImages; swapchainInfo.imageFormat = format; swapchainInfo.imageColorSpace = colorSpace; swapchainInfo.imageExtent = swapchainExtent; swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; swapchainInfo.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform; swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapchainInfo.imageArrayLayers = 1; swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainInfo.presentMode = swapchainPresentMode; swapchainInfo.oldSwapchain = handle; error = device->fpCreateSwapchainKHR(device->device, &swapchainInfo, nullptr, &handle); if (error) return false; error = device->fpGetSwapchainImagesKHR(device->device, handle, &imageCount, nullptr); if (error) return false; std::vector<VkImage> swapChainImages(imageCount); error = device->fpGetSwapchainImagesKHR(device->device, handle, &imageCount, &swapChainImages[0]); if (error) return false; // Color buffers descriptions agpu_texture_description colorDesc; memset(&colorDesc, 0, sizeof(colorDesc)); colorDesc.type = AGPU_TEXTURE_2D; colorDesc.width = createInfo->width; colorDesc.height = createInfo->height; colorDesc.depthOrArraySize = 1; colorDesc.format = agpuFormat; colorDesc.flags = agpu_texture_flags(AGPU_TEXTURE_FLAG_RENDER_TARGET | AGPU_TEXTURE_FLAG_RENDERBUFFER_ONLY); colorDesc.miplevels = 1; colorDesc.sample_count = 1; // Depth stencil buffer descriptions. agpu_texture_description depthStencilDesc; memset(&depthStencilDesc, 0, sizeof(depthStencilDesc)); depthStencilDesc.type = AGPU_TEXTURE_2D; depthStencilDesc.width = createInfo->width; depthStencilDesc.height = createInfo->height; depthStencilDesc.depthOrArraySize = 1; depthStencilDesc.format = createInfo->depth_stencil_format; depthStencilDesc.flags = agpu_texture_flags(AGPU_TEXTURE_FLAG_RENDERBUFFER_ONLY); depthStencilDesc.miplevels = 1; bool hasDepth = hasDepthComponent(createInfo->depth_stencil_format); bool hasStencil = hasStencilComponent(createInfo->depth_stencil_format); if (hasDepth) depthStencilDesc.flags = agpu_texture_flags(depthStencilDesc.flags | AGPU_TEXTURE_FLAG_DEPTH); if (hasStencil) depthStencilDesc.flags = agpu_texture_flags(depthStencilDesc.flags | AGPU_TEXTURE_FLAG_STENCIL); agpu_texture_view_description colorViewDesc; agpu_texture_view_description depthStencilViewDesc; auto depthStencilViewPointer = &depthStencilViewDesc; if (!hasDepth && !hasStencil) depthStencilViewPointer = nullptr; // Create the semaphores VkSemaphoreCreateInfo semaphoreInfo; memset(&semaphoreInfo, 0, sizeof(semaphoreInfo)); semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphores.resize(imageCount, VK_NULL_HANDLE); currentSemaphoreIndex = 0; for (size_t i = 0; i < imageCount; ++i) { error = vkCreateSemaphore(device->device, &semaphoreInfo, nullptr, &semaphores[i]); if(error) return false; } VkClearColorValue clearColor; memset(&clearColor, 0, sizeof(clearColor)); framebuffers.resize(imageCount); for (size_t i = 0; i < imageCount; ++i) { auto colorImage = swapChainImages[i]; VkImageSubresourceRange range; memset(&range, 0, sizeof(range)); range.layerCount = 1; range.levelCount = 1; if (!device->clearImageWithColor(colorImage, range, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VkAccessFlagBits(0), &clearColor)) return false; agpu_texture *colorBuffer = nullptr; agpu_texture *depthStencilBuffer = nullptr; { colorBuffer = agpu_texture::createFromImage(device, &colorDesc, colorImage); if (!colorBuffer) return false; // Get the color buffer view description. colorBuffer->getFullViewDescription(&colorViewDesc); } { depthStencilBuffer = agpu_texture::create(device, &depthStencilDesc); if (!depthStencilBuffer) { colorBuffer->release(); return false; } // Get the depth stencil buffer view description. depthStencilBuffer->getFullViewDescription(&depthStencilViewDesc); } auto framebuffer = agpu_framebuffer::create(device, swapChainWidth, swapChainHeight, 1, &colorViewDesc, depthStencilViewPointer); framebuffer->swapChainFramebuffer = true; framebuffers[i] = framebuffer; // Release the references to the buffers. colorBuffer->release(); depthStencilBuffer->release(); if (!framebuffer) return false; } if (!getNextBackBufferIndex()) return false; return true; }