Esempio n. 1
0
VkPresentModeKHR SwapChain::ChoosePresentMode()
{
	uint32_t presentModeCount;
	K3D_VK_VERIFY(fpGetPhysicalDeviceSurfacePresentModesKHR(GetPhysicalDevice(), m_Surface, &presentModeCount, NULL));
	std::vector<VkPresentModeKHR> presentModes(presentModeCount);
	K3D_VK_VERIFY(fpGetPhysicalDeviceSurfacePresentModesKHR(GetPhysicalDevice(), m_Surface, &presentModeCount, presentModes.data()));
	VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
	for (size_t i = 0; i < presentModeCount; i++)
	{
		if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
		{
			swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
			break;
		}
		if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR))
		{
			swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
		}
	}
	return swapchainPresentMode;
}
Esempio n. 2
0
static std::vector<VkPresentModeKHR> GetPresentModes(VkPhysicalDevice physDevice, VkSurfaceKHR surface)
{
	uint32_t presentModeCount;
	VkResult error;

	error = GetPhysicalDeviceSurfacePresentModesKHR(physDevice,
	                                                surface,
	                                                &presentModeCount,
	                                                nullptr);
	Assert(error, "could not get surface present modes");
	Assert(presentModeCount > 0, "present mode count is zero!!");

	std::vector<VkPresentModeKHR> presentModes(presentModeCount);


	error = GetPhysicalDeviceSurfacePresentModesKHR(physDevice,
	                                                surface,
	                                                &presentModeCount,
	                                                presentModes.data());
	Assert(error, "could not get the present Modes");
	return presentModes;
}
Esempio n. 3
0
	int XdevLSwapChainVulkan::create(VkCommandBuffer cmdBuffer, uint32_t *width, uint32_t *height) {

		VkResult result;

		VkSwapchainKHR oldSwapchain = m_swapChain;

		// Get physical device surface properties and formats.
		VkSurfaceCapabilitiesKHR surfCaps;
		result = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &surfCaps);
		if(VK_SUCCESS != result) {
			std::cerr << "vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed: " << vkVkResultToString(result) << std::endl;
			return 1;
		}

		// -------------------------------------------------------------------------
		// Get available present modes.
		//

		// Get the number of modes.
		uint32_t presentModeCount;
		result = fpGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, nullptr);
		if(VK_SUCCESS != result) {
			std::cerr << "vkGetPhysicalDeviceSurfacePresentModesKHR failed: " << vkVkResultToString(result) << std::endl;
			return 1;
		}

		// Use the number of modes and create an array of modes.
		std::vector<VkPresentModeKHR> presentModes(presentModeCount);
		result = fpGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, presentModes.data());
		if(VK_SUCCESS != result) {
			std::cerr << "vkGetPhysicalDeviceSurfacePresentModesKHR failed: " << vkVkResultToString(result) << std::endl;
			return 1;
		}
		// -------------------------------------------------------------------------

		VkExtent2D swapchainExtent = {};
		// width and height are either both -1, or both not -1.
		if(surfCaps.currentExtent.width == UINT32_MAX) {
			// 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;
		}

		VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
		for(size_t i = 0; i < presentModeCount; i++) {
			if(presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
				swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
				break;
			}
			if((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
				swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
			}
		}

		// Determine the number of images
		uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;
		if((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount)) {
			desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
		}

		VkSurfaceTransformFlagsKHR preTransform;
		if(surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
			preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
		} else {
			preTransform = surfCaps.currentTransform;
		}

		VkSwapchainCreateInfoKHR swapchainCI = {};
		swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
		swapchainCI.pNext = NULL;
		swapchainCI.surface = m_surface;
		swapchainCI.minImageCount = desiredNumberOfSwapchainImages;
		swapchainCI.imageFormat = m_colorFormat;
		swapchainCI.imageColorSpace = m_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.pQueueFamilyIndices = NULL;
		swapchainCI.presentMode = swapchainPresentMode;
		swapchainCI.oldSwapchain = oldSwapchain;
		swapchainCI.clipped = true;
		swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

		// If we recreate a SwapChain we have to destroy the previous one.
		// Note: destroying the swapchain also cleans up all its associated
    // presentable images once the platform is done with them.
		if(m_oldSwapChain != VK_NULL_HANDLE) {
			fpDestroySwapchainKHR(m_device, m_oldSwapChain, nullptr);
		}

		result = fpCreateSwapchainKHR(m_device, &swapchainCI, nullptr, &m_swapChain);
		if(VK_SUCCESS != result) {
			std::cerr << "vkCreateSwapchainKHR failed: " << vkVkResultToString(result) << std::endl;
			return 1;
		}

		result = fpGetSwapchainImagesKHR(m_device, m_swapChain, &m_imageCount, nullptr);
		if(VK_SUCCESS != result) {
			std::cerr << "vkGetSwapchainImagesKHR failed: " << vkVkResultToString(result) << std::endl;
			return 1;
		}

		m_images.reserve(m_imageCount);
		m_images.resize(m_imageCount);

		result = fpGetSwapchainImagesKHR(m_device, m_swapChain, &m_imageCount, m_images.data());
		if(VK_SUCCESS != result) {
			std::cerr << "vkGetSwapchainImagesKHR failed: " << vkVkResultToString(result) << std::endl;
			return 1;
		}

		m_buffers.reserve(m_imageCount);
		m_buffers.resize(m_imageCount);

		for(uint32_t i = 0; i < m_imageCount; i++) {
			VkImageViewCreateInfo colorAttachmentView = {};
			colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
			colorAttachmentView.pNext = NULL;
			colorAttachmentView.format = m_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;

			m_buffers[i].image = m_images[i];

			// Transform images from initial (undefined) to present layout
			setImageLayout(
			  cmdBuffer,
			  m_buffers[i].image,
			  VK_IMAGE_ASPECT_COLOR_BIT,
			  VK_IMAGE_LAYOUT_UNDEFINED,
			  VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);

			colorAttachmentView.image = m_buffers[i].image;

			result = vkCreateImageView(m_device, &colorAttachmentView, nullptr, &m_buffers[i].view);
			assert(!result);
		}
		return 0;
	}
  void create(VkCommandBuffer cmdBuffer) {
    VkSurfaceCapabilitiesKHR caps = {};
    VkResult result = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice,
                                                                surface, &caps);

    if (result != VK_SUCCESS)
      VulkanTools::exitOnError(
          "Failed to get physical device surface capabilities");

    VkExtent2D swapchainExtent = {};

    if (caps.currentExtent.width == -1 || caps.currentExtent.height == -1) {
      swapchainExtent.width = WINDOW_WIDTH;
      swapchainExtent.height = WINDOW_HEIGHT;
    } else {
      swapchainExtent = caps.currentExtent;
    }

    uint32_t presentModeCount = 0;
    result = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
                                                       &presentModeCount, NULL);

    assert(result == VK_SUCCESS);
    assert(presentModeCount >= 1);

    std::vector<VkPresentModeKHR> presentModes(presentModeCount);
    result = fpGetPhysicalDeviceSurfacePresentModesKHR(
        physicalDevice, surface, &presentModeCount, presentModes.data());

    assert(result == VK_SUCCESS);

    VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;

    for (uint32_t i = 0; i < presentModeCount; i++) {
      if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
        presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
        break;
      }

      if (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)
        presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
    }

    assert(caps.maxImageCount >= 1);

    imageCount = caps.minImageCount + 1;

    if (imageCount > caps.maxImageCount) imageCount = caps.maxImageCount;

    VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
    swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    swapchainCreateInfo.surface = surface;
    swapchainCreateInfo.minImageCount = imageCount;
    swapchainCreateInfo.imageFormat = colorFormat;
    swapchainCreateInfo.imageColorSpace = colorSpace;
    swapchainCreateInfo.imageExtent = {swapchainExtent.width,
                                       swapchainExtent.height};
    swapchainCreateInfo.imageArrayLayers = 1;
    swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
    swapchainCreateInfo.queueFamilyIndexCount = 1;
    swapchainCreateInfo.pQueueFamilyIndices = {0};
    swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
    swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
    swapchainCreateInfo.presentMode = presentMode;

    result =
        fpCreateSwapchainKHR(device, &swapchainCreateInfo, NULL, &swapchain);

    assert(result == VK_SUCCESS);

    result = fpGetSwapchainImagesKHR(device, swapchain, &imageCount, NULL);

    assert(result == VK_SUCCESS);

    images.resize(imageCount);
    buffers.resize(imageCount);

    result =
        fpGetSwapchainImagesKHR(device, swapchain, &imageCount, images.data());

    assert(result == VK_SUCCESS);
  }
Esempio n. 5
0
    // Create the swap chain and get images with given width and height
    void create(VkCommandBuffer cmdBuffer, uint32_t *width, uint32_t *height)
    {
        VkResult err;
        VkSwapchainKHR oldSwapchain = swapChain;

        // Get physical device surface properties and formats
        VkSurfaceCapabilitiesKHR surfCaps;
        err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfCaps);
        assert(!err);

        // Get available present modes
        uint32_t presentModeCount;
        err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, NULL);
        assert(!err);
        assert(presentModeCount > 0);

        std::vector<VkPresentModeKHR> presentModes(presentModeCount);

        err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes.data());
        assert(!err);

        VkExtent2D swapchainExtent = {};
        // width and height are either both -1, or both not -1.
        if (surfCaps.currentExtent.width == -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;
        }

        // Prefer mailbox mode if present, it's the lowest latency non-tearing present  mode
        VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
        for (size_t i = 0; i < presentModeCount; i++)
        {
            if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
            {
                swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
                break;
            }
            if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR))
            {
                swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
            }
        }

        // Determine the number of images
        uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;
        if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount))
        {
            desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
        }

        VkSurfaceTransformFlagsKHR preTransform;
        if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
        {
            preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
        }
        else
        {
            preTransform = surfCaps.currentTransform;
        }

        VkSwapchainCreateInfoKHR swapchainCI = {};
        swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
        swapchainCI.pNext = NULL;
        swapchainCI.surface = surface;
        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.pQueueFamilyIndices = NULL;
        swapchainCI.presentMode = swapchainPresentMode;
        swapchainCI.oldSwapchain = oldSwapchain;
        swapchainCI.clipped = true;
        swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

        err = fpCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapChain);
        assert(!err);

        // If an existing sawp chain is re-created, destroy the old swap chain
        // This also cleans up all the presentable images
        if (oldSwapchain != VK_NULL_HANDLE)
        {
            fpDestroySwapchainKHR(device, oldSwapchain, nullptr);
        }

        err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, NULL);
        assert(!err);

        // Get the swap chain images
        images.resize(imageCount);
        err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, images.data());
        assert(!err);

        // Get the swap chain buffers containing the image and imageview
        buffers.resize(imageCount);
        for (uint32_t i = 0; i < imageCount; 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;

            buffers[i].image = images[i];

            // Transform images from initial (undefined) to present layout
            feather::vulkan::tools::setImageLayout(
                cmdBuffer,
                buffers[i].image,
                VK_IMAGE_ASPECT_COLOR_BIT,
                VK_IMAGE_LAYOUT_UNDEFINED,
                VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);

            colorAttachmentView.image = buffers[i].image;

            err = vkCreateImageView(device, &colorAttachmentView, nullptr, &buffers[i].view);
            assert(!err);
        }
    }
Esempio n. 6
0
			bool VkContext::CreateSwapchain(int width, int height) {
				// Get surface capabilities
				VkSurfaceCapabilitiesKHR surfaceCapabilities;
				CheckVkResult(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDev, surf, &surfaceCapabilities));

				// Get surface formats
				u32 formatCount = 0;
				CheckVkResult(vkGetPhysicalDeviceSurfaceFormatsKHR(physDev, surf, &formatCount, nullptr));

				std::vector<VkSurfaceFormatKHR> formats(formatCount);
				CheckVkResult(vkGetPhysicalDeviceSurfaceFormatsKHR(physDev, surf, &formatCount, formats.data()));

				// Get present modes
				u32 presentModeCount;
				CheckVkResult(vkGetPhysicalDeviceSurfacePresentModesKHR(physDev, surf, &presentModeCount, nullptr));

				std::vector<VkPresentModeKHR> presentModes(presentModeCount);
				CheckVkResult(vkGetPhysicalDeviceSurfacePresentModesKHR(physDev, surf, &presentModeCount, presentModes.data()));

				// Select number of swapchain images
				u32 imageCount = surfaceCapabilities.minImageCount + 1;
				if (surfaceCapabilities.maxImageCount != 0 && imageCount > surfaceCapabilities.maxImageCount) {
					imageCount = surfaceCapabilities.maxImageCount;
				}

				// Select format
				VkSurfaceFormatKHR format;

				if (formats.size() == 1 && formats[0].format == VK_FORMAT_UNDEFINED) {
					format.format = VK_FORMAT_R8G8B8A8_UNORM;
					format.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
				}
				else {
					for (u32 i = 0; i < formats.size(); i++)
					{
						if (formats[i].format == VK_FORMAT_R8G8B8A8_UNORM) {
							format = formats[i];
						}
					}

					format = formats[0];
				}

				// Select extent
				VkExtent2D extent;

				if (surfaceCapabilities.currentExtent.width == -1) {
					extent.width = min(max((u32)width, surfaceCapabilities.minImageExtent.width), surfaceCapabilities.maxImageExtent.width);
					extent.height = min(max((u32)height, surfaceCapabilities.minImageExtent.height), surfaceCapabilities.maxImageExtent.height);
				}
				else {
					extent = surfaceCapabilities.currentExtent;
				}

				// Select present mode (FIFO by default)
				VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;

				// Choose mailbox if possible
				for (u32 i = 0; i < presentModes.size(); i++)
				{
					if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
						presentMode = presentModes[i];
					}
				}

				// Select transformation
				VkSurfaceTransformFlagBitsKHR transform;
				if (surfaceCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
					transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
				}
				else {
					transform = surfaceCapabilities.currentTransform;
				}

				// Check if image transfer destination is supported
				if (!(surfaceCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
					std::cout << "Image transfer destination not supported" << std::endl;
					return false;
				}

				// Create swapchian
				VkSwapchainCreateInfoKHR swapchainInfo = {};
				swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
				swapchainInfo.surface = surf;
				swapchainInfo.minImageCount = imageCount;
				swapchainInfo.imageFormat = format.format;
				swapchainInfo.imageColorSpace = format.colorSpace;
				swapchainInfo.imageExtent = extent;
				swapchainInfo.imageArrayLayers = 1;
				swapchainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
				swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
				swapchainInfo.queueFamilyIndexCount = 0;
				swapchainInfo.pQueueFamilyIndices = nullptr;
				swapchainInfo.preTransform = transform;
				swapchainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
				swapchainInfo.presentMode = presentMode;
				swapchainInfo.clipped = VK_TRUE;
				swapchainInfo.oldSwapchain = VK_NULL_HANDLE;

				CheckVkResult(vkCreateSwapchainKHR(dev, &swapchainInfo, nullptr, &swapchain));

				// Get swapchain images
				u32 swapchainImageCount = 0;
				CheckVkResult(vkGetSwapchainImagesKHR(dev, swapchain, &swapchainImageCount, nullptr));

				swapchainImages.resize(swapchainImageCount);
				CheckVkResult(vkGetSwapchainImagesKHR(dev, swapchain, &swapchainImageCount, swapchainImages.data()));

				// Create swapchain image views
				swapchainImageViews.resize(imageCount);
				for (u32 i = 0; i < imageCount; i++) {
					VkImageViewCreateInfo imageViewCreateInfo = {};
					imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
					imageViewCreateInfo.image = swapchainImages[i];
					imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
					imageViewCreateInfo.format = format.format;
					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.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
					imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
					imageViewCreateInfo.subresourceRange.levelCount = 1;
					imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
					imageViewCreateInfo.subresourceRange.layerCount = 1;

					CheckVkResult(vkCreateImageView(dev, &imageViewCreateInfo, nullptr, &swapchainImageViews[i]));
				}

				return true;
			}
  void create(VkCommandBuffer cmdBuffer) {
    VkSurfaceCapabilitiesKHR caps = {};
    VkResult result = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice,
                                                                surface, &caps);

    if (result != VK_SUCCESS)
      VulkanTools::exitOnError(
          "Failed to get physical device surface capabilities");

    VkExtent2D swapchainExtent = {};

    if (caps.currentExtent.width == -1 || caps.currentExtent.height == -1) {
      swapchainExtent.width = WINDOW_WIDTH;
      swapchainExtent.height = WINDOW_HEIGHT;
    } else {
      swapchainExtent = caps.currentExtent;
    }

    uint32_t presentModeCount = 0;
    result = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
                                                       &presentModeCount, NULL);

    assert(result == VK_SUCCESS);
    assert(presentModeCount >= 1);

    std::vector<VkPresentModeKHR> presentModes(presentModeCount);
    result = fpGetPhysicalDeviceSurfacePresentModesKHR(
        physicalDevice, surface, &presentModeCount, presentModes.data());

    assert(result == VK_SUCCESS);

    VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;

    for (uint32_t i = 0; i < presentModeCount; i++) {
      if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
        presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
        break;
      }

      if (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)
        presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
    }

    assert(caps.maxImageCount >= 1);

    imageCount = caps.minImageCount + 1;

    if (imageCount > caps.maxImageCount) imageCount = caps.maxImageCount;

    VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
    swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    swapchainCreateInfo.surface = surface;
    swapchainCreateInfo.minImageCount = imageCount;
    swapchainCreateInfo.imageFormat = colorFormat;
    swapchainCreateInfo.imageColorSpace = colorSpace;
    swapchainCreateInfo.imageExtent = {swapchainExtent.width,
                                       swapchainExtent.height};
    swapchainCreateInfo.imageArrayLayers = 1;
    swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
    swapchainCreateInfo.queueFamilyIndexCount = 1;
    swapchainCreateInfo.pQueueFamilyIndices = {0};
    swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
    swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
    swapchainCreateInfo.presentMode = presentMode;

    result =
        fpCreateSwapchainKHR(device, &swapchainCreateInfo, NULL, &swapchain);

    assert(result == VK_SUCCESS);

    result = fpGetSwapchainImagesKHR(device, swapchain, &imageCount, NULL);

    assert(result == VK_SUCCESS);

    images.resize(imageCount);
    buffers.resize(imageCount);

    result =
        fpGetSwapchainImagesKHR(device, swapchain, &imageCount, images.data());

    assert(result == VK_SUCCESS);

    for (uint32_t i = 0; i < imageCount; i++) {
      VkImageViewCreateInfo imageCreateInfo = {};
      imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
      imageCreateInfo.pNext = NULL;
      imageCreateInfo.format = colorFormat;
      imageCreateInfo.components = {
          VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
          VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
      imageCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
      imageCreateInfo.subresourceRange.baseMipLevel = 0;
      imageCreateInfo.subresourceRange.levelCount = 1;
      imageCreateInfo.subresourceRange.baseArrayLayer = 0;
      imageCreateInfo.subresourceRange.layerCount = 1;
      imageCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
      imageCreateInfo.flags = 0;

      buffers[i].image = images[i];
      VulkanTools::setImageLayout(
          cmdBuffer, buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
          VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
      imageCreateInfo.image = buffers[i].image;
      result =
          vkCreateImageView(device, &imageCreateInfo, NULL, &buffers[i].view);

      assert(result == VK_SUCCESS);

      VkFramebufferCreateInfo fbCreateInfo = {};
      fbCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
      fbCreateInfo.attachmentCount = 1;
      fbCreateInfo.pAttachments = &buffers[i].view;
      fbCreateInfo.width = swapchainExtent.width;
      fbCreateInfo.height = swapchainExtent.height;
      fbCreateInfo.layers = 1;

      result = vkCreateFramebuffer(device, &fbCreateInfo, NULL,
                                   &buffers[i].frameBuffer);

      assert(result == VK_SUCCESS);
    }
  }
Esempio n. 8
0
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;
}