Exemple #1
0
void GetSurfaceColorSpaceAndFormat(VkPhysicalDevice physicalDevice,
                                   SurfaceInfo* surfaceInfo)
{
	uint32_t surfaceFormatCount;
	VkResult error;
	error = GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surfaceInfo->surface, &surfaceFormatCount, nullptr);
	Assert(error, "could not get surface format counts, GetphysicalDeviceSurfaceFormatsKHR is probably null");
	Assert(surfaceFormatCount > 0, "surfaceformatcount is less than 1");

	std::vector<VkSurfaceFormatKHR> surfaceFormats(surfaceFormatCount);
	error = GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice,
	                                           surfaceInfo->surface,
	                                           &surfaceFormatCount,
	                                           surfaceFormats.data());
	Assert(error, "could not get surface format counts, GetphysicalDeviceSurfaceFormatsKHR is probably null");

	if (surfaceFormatCount == 1 && surfaceFormats[0].format == VK_FORMAT_UNDEFINED)
	{
		surfaceInfo->colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
	} else
	{
		surfaceInfo->colorFormat = surfaceFormats[0].format;
	}
	surfaceInfo->colorSpace = surfaceFormats[0].colorSpace;
}
	int XdevLSwapChainVulkan::createSurface(IPXdevLWindow window) {
		Display* display = static_cast<Display*>(window->getInternal(XdevLInternalName("X11_DISPLAY")));
		if(nullptr == display) {
			XDEVL_MODULEX_ERROR(XdevLSwapChainVulkan, "Could not get native X11 display information.\n");
			return RET_FAILED;
		}

		Window x11window = (Window)(window->getInternal(XdevLInternalName("X11_WINDOW")));
		if(None == x11window) {
			XDEVL_MODULEX_ERROR(XdevLSwapChainVulkan, "Could not get native X11 window information.\n");
			return RET_FAILED;
		}

		//
		// Get the Surface extensions.
		//
		VkResult result;

#if defined(_WIN32)
		VkWin32SurfaceCreateInfoKHR surfaceCreateInfo;
		surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
		surfaceCreateInfo.hinstance = (HINSTANCE)platformHandle; // provided by the platform code
		surfaceCreateInfo.hwnd = (HWND)platformWindow;           // provided by the platform code
		result = vkCreateWin32SurfaceKHR(instance, &surfaceCreateInfo, nullptr, &m_surface);
#elif defined(__ANDROID__)
		VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
		surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
		surfaceCreateInfo.window = window;                       // provided by the platform code
		result = vkCreateAndroidSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &m_surface);
#else
		VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = {
			VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
			nullptr,
			0,
			XGetXCBConnection(display),
			(xcb_window_t)x11window
		};
		result = vkCreateXcbSurfaceKHR(m_instance, &surfaceCreateInfo, nullptr, &m_surface);
#endif
		if(result != VK_SUCCESS) {
			std::cerr << "Failed to create Vulkan surface: " << vkVkResultToString(result) << std::endl;
			return 1;
		}


		uint32_t queueCount;
		vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueCount, nullptr);

		std::vector<VkQueueFamilyProperties> queueProps(queueCount);
		vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueCount, queueProps.data());

		// Will be used to present the swap chain images to the windowing system
		std::vector<VkBool32> supportsPresent(queueCount);
		for(uint32_t i = 0; i < queueCount; i++) {
			fpGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &supportsPresent[i]);

		}



		// Search for a graphics and a present queue in the array of queue
		// families, try to find one that supports both
		uint32_t graphicsQueueNodeIndex = UINT32_MAX;
		uint32_t presentQueueNodeIndex = UINT32_MAX;
		for(uint32_t i = 0; i < queueCount; i++) {
			if((queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
				if(graphicsQueueNodeIndex == UINT32_MAX) {
					graphicsQueueNodeIndex = i;
				}

				if(supportsPresent[i] == VK_TRUE) {
					graphicsQueueNodeIndex = i;
					presentQueueNodeIndex = i;
					break;
				}
			}
		}
		if(presentQueueNodeIndex == UINT32_MAX) {
			// If there's no queue that supports both present and graphics
			// try to find a separate present queue
			for(uint32_t i = 0; i < queueCount; ++i) {
				if(supportsPresent[i] == VK_TRUE) {
					presentQueueNodeIndex = i;
					break;
				}
			}
		}

		// Exit if either a graphics or a presenting queue hasn't been found
		if(graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX) {
			return 1;
		}

		// todo : Add support for separate graphics and presenting queue
		if(graphicsQueueNodeIndex != presentQueueNodeIndex) {
			return 1;
		}

		m_queueNodeIndex = graphicsQueueNodeIndex;

		// Get list of supported surface formats
		uint32_t formatCount;
		result = vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr);
		if(VK_SUCCESS != result) {
			std::cerr << "vkGetPhysicalDeviceSurfaceFormatsKHR failed: " << vkVkResultToString(result) << std::endl;
			return 1;
		}
		assert(formatCount > 0);

		std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
		result = vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, surfaceFormats.data());
		assert(!result);



		// If the surface format list only includes one entry with VK_FORMAT_UNDEFINED,
		// there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM
		if((formatCount == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED)) {
			m_colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
		} else {
			// Always select the first available color format
			// If you need a specific format (e.g. SRGB) you'd need to
			// iterate over the list of available surface format and
			// check for it's presence
			m_colorFormat = surfaceFormats[0].format;
		}

		m_colorSpace = surfaceFormats[0].colorSpace;

		return 0;
	}
Exemple #3
0
    // Creates an os specific surface
    // Tries to find a graphics and a present queue
    void initSurface(
        xcb_connection_t* connection, xcb_window_t window
    )
    {
        VkResult err;

        // Create surface depending on OS
        VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = {};
        surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
        surfaceCreateInfo.connection = connection;
        surfaceCreateInfo.window = window;
        err = vkCreateXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);

        // Get available queue family properties
        uint32_t queueCount;
        vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);
        assert(queueCount >= 1);

        std::vector<VkQueueFamilyProperties> queueProps(queueCount);
        vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data());

        // Iterate over each queue to learn whether it supports presenting:
        // Find a queue with present support
        // Will be used to present the swap chain images to the windowing system
        std::vector<VkBool32> supportsPresent(queueCount);
        for (uint32_t i = 0; i < queueCount; i++)
        {
            fpGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface, &supportsPresent[i]);
        }

        // Search for a graphics and a present queue in the array of queue
        // families, try to find one that supports both
        uint32_t graphicsQueueNodeIndex = UINT32_MAX;
        uint32_t presentQueueNodeIndex = UINT32_MAX;
        for (uint32_t i = 0; i < queueCount; i++)
        {
            if ((queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
            {
                if (graphicsQueueNodeIndex == UINT32_MAX)
                {
                    graphicsQueueNodeIndex = i;
                }

                if (supportsPresent[i] == VK_TRUE)
                {
                    graphicsQueueNodeIndex = i;
                    presentQueueNodeIndex = i;
                    break;
                }
            }
        }
        if (presentQueueNodeIndex == UINT32_MAX)
        {
            // If there's no queue that supports both present and graphics
            // try to find a separate present queue
            for (uint32_t i = 0; i < queueCount; ++i)
            {
                if (supportsPresent[i] == VK_TRUE)
                {
                    presentQueueNodeIndex = i;
                    break;
                }
            }
        }

        // Exit if either a graphics or a presenting queue hasn't been found
        if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX)
        {
            feather::vulkan::tools::exitFatal("Could not find a graphics and/or presenting queue!", "Fatal error");
        }

        // todo : Add support for separate graphics and presenting queue
        if (graphicsQueueNodeIndex != presentQueueNodeIndex)
        {
            feather::vulkan::tools::exitFatal("Separate graphics and presenting queues are not supported yet!", "Fatal error");
        }

        queueNodeIndex = graphicsQueueNodeIndex;

        // Get list of supported surface formats
        uint32_t formatCount;
        err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, NULL);
        assert(!err);
        assert(formatCount > 0);

        std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
        err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, surfaceFormats.data());
        assert(!err);

        // If the surface format list only includes one entry with VK_FORMAT_UNDEFINED,
        // there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM
        if ((formatCount == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED))
        {
            colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
        }
        else
        {
            // Always select the first available color format
            // If you need a specific format (e.g. SRGB) you'd need to
            // iterate over the list of available surface format and
            // check for it's presence
            colorFormat = surfaceFormats[0].format;
        }
        colorSpace = surfaceFormats[0].colorSpace;
    }
  void createSurface(
#if defined(_WIN32)
      HINSTANCE windowInstance, HWND window
#elif defined(__linux__)
      xcb_connection_t *connection, xcb_window_t window
#endif
      ) {
#if defined(_WIN32)
    VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {};
    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
    surfaceCreateInfo.pNext = NULL;
    surfaceCreateInfo.flags = 0;
    surfaceCreateInfo.hinstance = windowInstance;
    surfaceCreateInfo.hwnd = window;
    VkResult result =
        vkCreateWin32SurfaceKHR(instance, &surfaceCreateInfo, NULL, &surface);
#elif defined(__linux__)
    VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = {};
    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
    surfaceCreateInfo.pNext = NULL;
    surfaceCreateInfo.flags = 0;
    surfaceCreateInfo.connection = connection;
    surfaceCreateInfo.window = window;
    VkResult result =
        vkCreateXcbSurfaceKHR(instance, &surfaceCreateInfo, NULL, &surface);
#endif

    assert(result == VK_SUCCESS);

    uint32_t queueCount = 0;
    vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);

    assert(queueCount >= 1);

    std::vector<VkQueueFamilyProperties> queueProperties(queueCount);
    vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount,
                                             queueProperties.data());

    queueIndex = UINT32_MAX;
    std::vector<VkBool32> supportsPresenting(queueCount);

    for (uint32_t i = 0; i < queueCount; i++) {
      fpGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface,
                                           &supportsPresenting[i]);
      if ((queueProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
        if (supportsPresenting[i] == VK_TRUE) {
          queueIndex = i;
          break;
        }
      }
    }

    assert(queueIndex != UINT32_MAX);

    uint32_t formatCount = 0;
    result = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
                                                  &formatCount, NULL);

    assert(result == VK_SUCCESS && formatCount >= 1);

    std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
    result = fpGetPhysicalDeviceSurfaceFormatsKHR(
        physicalDevice, surface, &formatCount, surfaceFormats.data());

    assert(result == VK_SUCCESS);

    if (formatCount == 1 && surfaceFormats[0].format == VK_FORMAT_UNDEFINED)
      colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
    else
      colorFormat = surfaceFormats[0].format;

    colorSpace = surfaceFormats[0].colorSpace;
  }
Exemple #5
0
_agpu_swap_chain *_agpu_swap_chain::create(agpu_device *device, agpu_command_queue* graphicsCommandQueue, agpu_swap_chain_create_info *createInfo)
{
    VkSurfaceKHR surface = VK_NULL_HANDLE;
    if (!graphicsCommandQueue || !createInfo)
        return nullptr;

#if defined(_WIN32)
    if (!createInfo->window)
        return nullptr;
    VkWin32SurfaceCreateInfoKHR surfaceCreateInfo;
    memset(&surfaceCreateInfo, 0, sizeof(surfaceCreateInfo));
    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
    surfaceCreateInfo.hinstance = GetModuleHandle(nullptr);
    surfaceCreateInfo.hwnd = (HWND)createInfo->window;

    auto error = vkCreateWin32SurfaceKHR(device->vulkanInstance, &surfaceCreateInfo, nullptr, &surface);
#elif defined(__unix__)
    if(!device->displayHandle)
        device->displayHandle = XOpenDisplay(nullptr);

    if (!createInfo->window)
        return nullptr;

    VkXcbSurfaceCreateInfoKHR surfaceCreateInfo;
    memset(&surfaceCreateInfo, 0, sizeof(surfaceCreateInfo));
    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
    surfaceCreateInfo.connection = XGetXCBConnection((Display*)device->displayHandle);
    surfaceCreateInfo.window = (xcb_window_t)(uintptr_t)createInfo->window;

    auto error = vkCreateXcbSurfaceKHR(device->vulkanInstance, &surfaceCreateInfo, nullptr, &surface);
#else
#error unsupported platform
#endif
    if (error)
    {
        printError("Failed to create the swap chain surface\n");
        return nullptr;
    }

    agpu_command_queue *presentationQueue = graphicsCommandQueue;
    if (!graphicsCommandQueue->supportsPresentingSurface(surface))
    {
        // TODO: Find a presentation queue.
        vkDestroySurfaceKHR(device->vulkanInstance, surface, nullptr);
        printError("Surface presentation in different queue is not yet supported.\n");
        return nullptr;
    }

    uint32_t formatCount = 0;
    error = device->fpGetPhysicalDeviceSurfaceFormatsKHR(device->physicalDevice, surface, &formatCount, nullptr);
    if (error)
    {
        vkDestroySurfaceKHR(device->vulkanInstance, surface, nullptr);
        return nullptr;
    }

    std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
    error = device->fpGetPhysicalDeviceSurfaceFormatsKHR(device->physicalDevice, surface, &formatCount, &surfaceFormats[0]);
    if (error)
    {
        vkDestroySurfaceKHR(device->vulkanInstance, surface, nullptr);
        return nullptr;
    }

    // Create the swap chain object.
    auto swapChain = new agpu_swap_chain(device);
    swapChain->surface = surface;
    swapChain->graphicsQueue = graphicsCommandQueue;
    swapChain->presentationQueue = presentationQueue;
    graphicsCommandQueue->retain();
    presentationQueue->retain();

    // Set the format.
    agpu_texture_format actualFormat = createInfo->colorbuffer_format;
    if (formatCount == 1 && surfaceFormats[0].format == VK_FORMAT_UNDEFINED)
    {
        swapChain->format = mapTextureFormat(createInfo->colorbuffer_format);
        if (swapChain->format == VK_FORMAT_UNDEFINED)
        {
            swapChain->format = VK_FORMAT_B8G8R8A8_UNORM;
            actualFormat = AGPU_TEXTURE_FORMAT_B8G8R8A8_UNORM;
        }
        swapChain->colorSpace = surfaceFormats[0].colorSpace;
    }
    else
    {
        assert(formatCount >= 1);

        // Start selecting the first format.
        swapChain->format = surfaceFormats[0].format;
        swapChain->colorSpace = surfaceFormats[0].colorSpace;
        actualFormat = AGPU_TEXTURE_FORMAT_B8G8R8A8_UNORM;
        if(swapChain->format == VK_FORMAT_B8G8R8A8_SRGB)
            actualFormat = AGPU_TEXTURE_FORMAT_B8G8R8A8_UNORM_SRGB;

        // Try to select the expected format.
        auto wantedFormat = mapTextureFormat(createInfo->colorbuffer_format);
        for(size_t i = 0; i < formatCount; ++i)
        {
            auto &format = surfaceFormats[i];
            if(format.format == wantedFormat)
            {
                swapChain->format = format.format;
                swapChain->colorSpace = format.colorSpace;
                actualFormat = createInfo->colorbuffer_format;
                break;
            }
        }

    }
    swapChain->agpuFormat = actualFormat;

    // Initialize the rest of the swap chain.
    if (!swapChain->initialize(createInfo))
    {
        swapChain->release();
        return nullptr;
    }

    return swapChain;
}