vk: Add WSI implementation

This commit is contained in:
Kristian Høgsberg
2015-05-15 22:04:52 -07:00
parent f886647b75
commit a29df71dd2
6 changed files with 557 additions and 18 deletions

View File

@@ -0,0 +1,197 @@
//
// File: vk_wsi_display.h
//
/*
** Copyright (c) 2014 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#ifndef __VK_WSI_LUNARG_H__
#define __VK_WSI_LUNARG_H__
#include "vulkan.h"
#define VK_WSI_LUNARG_REVISION 3
#define VK_WSI_LUNARG_EXTENSION_NUMBER 1
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
// ------------------------------------------------------------------------------------------------
// Objects
VK_DEFINE_DISP_SUBCLASS_HANDLE(VkDisplayWSI, VkObject)
VK_DEFINE_DISP_SUBCLASS_HANDLE(VkSwapChainWSI, VkObject)
// ------------------------------------------------------------------------------------------------
// Enumeration constants
#define VK_WSI_LUNARG_ENUM(type,id) ((type)(VK_WSI_LUNARG_EXTENSION_NUMBER * -1000 + (id)))
// Extend VkPhysicalDeviceInfoType enum with extension specific constants
#define VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI VK_WSI_LUNARG_ENUM(VkPhysicalDeviceInfoType, 0)
#define VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PRESENT_PROPERTIES_WSI VK_WSI_LUNARG_ENUM(VkPhysicalDeviceInfoType, 1)
// Extend VkStructureType enum with extension specific constants
#define VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI VK_WSI_LUNARG_ENUM(VkStructureType, 0)
#define VK_STRUCTURE_TYPE_PRESENT_INFO_WSI VK_WSI_LUNARG_ENUM(VkStructureType, 1)
// Extend VkImageLayout enum with extension specific constants
#define VK_IMAGE_LAYOUT_PRESENT_SOURCE_WSI VK_WSI_LUNARG_ENUM(VkImageLayout, 0)
// Extend VkObjectType enum for new objects
#define VK_OBJECT_TYPE_DISPLAY_WSI VK_WSI_LUNARG_ENUM(VkObjectType, 0)
#define VK_OBJECT_TYPE_SWAP_CHAIN_WSI VK_WSI_LUNARG_ENUM(VkObjectType, 1)
// ------------------------------------------------------------------------------------------------
// Enumerations
typedef enum VkDisplayInfoTypeWSI_
{
// Info type for vkGetDisplayInfo()
VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI = 0x00000003, // Return the VkFormat(s) supported for swap chains with the display
VK_ENUM_RANGE(DISPLAY_INFO_TYPE, FORMAT_PROPERTIES_WSI, FORMAT_PROPERTIES_WSI)
} VkDisplayInfoTypeWSI;
typedef enum VkSwapChainInfoTypeWSI_
{
// Info type for vkGetSwapChainInfo()
VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI = 0x00000000, // Return information about the persistent images of the swapchain
VK_ENUM_RANGE(SWAP_CHAIN_INFO_TYPE, PERSISTENT_IMAGES_WSI, PERSISTENT_IMAGES_WSI)
} VkSwapChainInfoTypeWSI;
// ------------------------------------------------------------------------------------------------
// Flags
typedef VkFlags VkSwapModeFlagsWSI;
typedef enum VkSwapModeFlagBitsWSI_
{
VK_SWAP_MODE_FLIP_BIT_WSI = VK_BIT(0),
VK_SWAP_MODE_BLIT_BIT_WSI = VK_BIT(1),
} VkSwapModeFlagBitsWSI;
// ------------------------------------------------------------------------------------------------
// Structures
typedef struct VkDisplayPropertiesWSI_
{
VkDisplayWSI display; // Handle of the display object
VkExtent2D physicalResolution; // Max resolution for CRT?
} VkDisplayPropertiesWSI;
typedef struct VkDisplayFormatPropertiesWSI_
{
VkFormat swapChainFormat; // Format of the images of the swap chain
} VkDisplayFormatPropertiesWSI;
typedef struct VkSwapChainCreateInfoWSI_
{
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI
const void* pNext; // Pointer to next structure
// TBD: It is not yet clear what the use will be for the following two
// values. It seems to be needed for more-global window-system handles
// (e.g. X11 display). If not needed for the SDK, we will drop it from
// this extension, and from a future version of this header.
const void* pNativeWindowSystemHandle; // Pointer to native window system handle
const void* pNativeWindowHandle; // Pointer to native window handle
uint32_t displayCount; // Number of displays the swap chain is created for
const VkDisplayWSI* pDisplays; // displayCount number of display objects the swap chain is created for
uint32_t imageCount; // Number of images in the swap chain
VkFormat imageFormat; // Format of the images of the swap chain
VkExtent2D imageExtent; // Width and height of the images of the swap chain
uint32_t imageArraySize; // Number of layers of the images of the swap chain (needed for multi-view rendering)
VkFlags imageUsageFlags; // Usage flags for the images of the swap chain (see VkImageUsageFlags)
VkFlags swapModeFlags; // Allowed swap modes (see VkSwapModeFlagsWSI)
} VkSwapChainCreateInfoWSI;
typedef struct VkSwapChainImageInfoWSI_
{
VkImage image; // Persistent swap chain image handle
VkDeviceMemory memory; // Persistent swap chain image's memory handle
} VkSwapChainImageInfoWSI;
typedef struct VkPhysicalDeviceQueuePresentPropertiesWSI_
{
bool32_t supportsPresent; // Tells whether the queue supports presenting
} VkPhysicalDeviceQueuePresentPropertiesWSI;
typedef struct VkPresentInfoWSI_
{
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_PRESENT_INFO_WSI
const void* pNext; // Pointer to next structure
VkImage image; // Image to present
uint32_t flipInterval; // Flip interval
} VkPresentInfoWSI;
// ------------------------------------------------------------------------------------------------
// Function types
typedef VkResult (VKAPI *PFN_vkGetDisplayInfoWSI)(VkDisplayWSI display, VkDisplayInfoTypeWSI infoType, size_t* pDataSize, void* pData);
typedef VkResult (VKAPI *PFN_vkCreateSwapChainWSI)(VkDevice device, const VkSwapChainCreateInfoWSI* pCreateInfo, VkSwapChainWSI* pSwapChain);
typedef VkResult (VKAPI *PFN_vkDestroySwapChainWSI)(VkSwapChainWSI swapChain);
typedef VkResult (VKAPI *PFN_vkGetSwapChainInfoWSI)(VkSwapChainWSI swapChain, VkSwapChainInfoTypeWSI infoType, size_t* pDataSize, void* pData);
typedef VkResult (VKAPI *PFN_vkQueuePresentWSI)(VkQueue queue, const VkPresentInfoWSI* pPresentInfo);
// ------------------------------------------------------------------------------------------------
// Function prototypes
#ifdef VK_PROTOTYPES
VkResult VKAPI vkGetDisplayInfoWSI(
VkDisplayWSI display,
VkDisplayInfoTypeWSI infoType,
size_t* pDataSize,
void* pData);
VkResult VKAPI vkCreateSwapChainWSI(
VkDevice device,
const VkSwapChainCreateInfoWSI* pCreateInfo,
VkSwapChainWSI* pSwapChain);
VkResult VKAPI vkDestroySwapChainWSI(
VkSwapChainWSI swapChain);
VkResult VKAPI vkGetSwapChainInfoWSI(
VkSwapChainWSI swapChain,
VkSwapChainInfoTypeWSI infoType,
size_t* pDataSize,
void* pData);
VkResult VKAPI vkQueuePresentWSI(
VkQueue queue,
const VkPresentInfoWSI* pPresentInfo);
#endif // VK_PROTOTYPES
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // __VK_WSI_LUNARG_H__

View File

@@ -22,10 +22,11 @@
vulkan_includedir = $(includedir)/vulkan
vulkan_include_HEADERS = \
$(top_srcdir)/include/vulkan/vk_platform.h \
$(top_srcdir)/include/vulkan/vulkan.h \
$(top_srcdir)/include/vulkan/vulkan_intel.h
vulkan_include_HEADERS = \
$(top_srcdir)/include/vulkan/vk_platform.h \
$(top_srcdir)/include/vulkan/vulkan.h \
$(top_srcdir)/include/vulkan/vulkan_intel.h \
$(top_srcdir)/include/vulkan/vk_wsi_lunarg.h
lib_LTLIBRARIES = libvulkan.la
@@ -64,6 +65,7 @@ libvulkan_la_SOURCES = \
intel.c \
entrypoints.c \
entrypoints.h \
x11.c \
formats.c \
compiler.cpp

View File

@@ -187,9 +187,10 @@ VkResult anv_GetPhysicalDeviceInfo(
VkPhysicalDevicePerformance *performance;
VkPhysicalDeviceQueueProperties *queue_properties;
VkPhysicalDeviceMemoryProperties *memory_properties;
VkDisplayPropertiesWSI *display_properties;
uint64_t ns_per_tick = 80;
switch (infoType) {
switch ((uint32_t) infoType) {
case VK_PHYSICAL_DEVICE_INFO_TYPE_PROPERTIES:
properties = pData;
@@ -252,6 +253,23 @@ VkResult anv_GetPhysicalDeviceInfo(
memory_properties->supportsPinning = false;
return VK_SUCCESS;
case VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI:
anv_finishme("VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI");
*pDataSize = sizeof(*display_properties);
if (pData == NULL)
return VK_SUCCESS;
display_properties = pData;
display_properties->display = 0;
display_properties->physicalResolution = (VkExtent2D) { 0, 0 };
return VK_SUCCESS;
case VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PRESENT_PROPERTIES_WSI:
anv_finishme("VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PRESENT_PROPERTIES_WSI");
return VK_SUCCESS;
default:
return VK_UNSUPPORTED;
}
@@ -383,18 +401,28 @@ VkResult anv_GetGlobalExtensionInfo(
size_t* pDataSize,
void* pData)
{
uint32_t *count;
static const VkExtensionProperties extensions[] = {
{
.extName = "VK_WSI_LunarG",
.version = 3
}
};
uint32_t count = ARRAY_SIZE(extensions);
switch (infoType) {
case VK_EXTENSION_INFO_TYPE_COUNT:
count = pData;
assert(*pDataSize == 4);
*count = 0;
memcpy(pData, &count, sizeof(count));
*pDataSize = sizeof(count);
return VK_SUCCESS;
case VK_EXTENSION_INFO_TYPE_PROPERTIES:
return vk_error(VK_ERROR_INVALID_EXTENSION);
if (extensionIndex >= count)
return vk_error(VK_ERROR_INVALID_EXTENSION);
memcpy(pData, &extensions[extensionIndex], sizeof(extensions[0]));
*pDataSize = sizeof(extensions[0]);
return VK_SUCCESS;
default:
return VK_UNSUPPORTED;
}

View File

@@ -41,9 +41,10 @@ static const struct anv_tile_mode_info {
[WMAJOR] = { 128, 32 }
};
VkResult anv_CreateImage(
VkResult anv_image_create(
VkDevice _device,
const VkImageCreateInfo* pCreateInfo,
const struct anv_image_create_info * extra,
VkImage* pImage)
{
struct anv_device *device = (struct anv_device *) _device;
@@ -63,6 +64,7 @@ VkResult anv_CreateImage(
image->type = pCreateInfo->imageType;
image->format = pCreateInfo->format;
image->extent = pCreateInfo->extent;
image->swap_chain = NULL;
assert(image->extent.width > 0);
assert(image->extent.height > 0);
@@ -71,20 +73,28 @@ VkResult anv_CreateImage(
switch (pCreateInfo->tiling) {
case VK_IMAGE_TILING_LINEAR:
image->tile_mode = LINEAR;
/* Linear depth buffers must be 64 byte aligned, which is the strictest
* requirement for all kinds of linear surfaces.
*/
image->alignment = 64;
break;
case VK_IMAGE_TILING_OPTIMAL:
image->tile_mode = YMAJOR;
image->alignment = 4096;
break;
default:
break;
}
if (extra)
image->tile_mode = extra->tile_mode;
if (image->tile_mode == LINEAR) {
/* Linear depth buffers must be 64 byte aligned, which is the strictest
* requirement for all kinds of linear surfaces.
*/
image->alignment = 64;
} else {
image->alignment = 4096;
}
format = anv_format_for_vk_format(pCreateInfo->format);
assert(format->cpp > 0);
image->stride = ALIGN_I32(image->extent.width * format->cpp,
tile_mode_info[image->tile_mode].tile_width);
aligned_height = ALIGN_I32(image->extent.height,
@@ -96,6 +106,14 @@ VkResult anv_CreateImage(
return VK_SUCCESS;
}
VkResult anv_CreateImage(
VkDevice device,
const VkImageCreateInfo* pCreateInfo,
VkImage* pImage)
{
return anv_image_create(device, pCreateInfo, NULL, pImage);
}
VkResult anv_GetImageSubresourceInfo(
VkDevice device,
VkImage image,

View File

@@ -36,6 +36,7 @@
#define VK_PROTOTYPES
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_intel.h>
#include <vulkan/vk_wsi_lunarg.h>
#include "entrypoints.h"
@@ -661,6 +662,8 @@ struct anv_image {
/* Set when bound */
struct anv_bo * bo;
VkDeviceSize offset;
struct anv_swap_chain * swap_chain;
};
struct anv_surface_view {
@@ -671,6 +674,15 @@ struct anv_surface_view {
VkFormat format;
};
struct anv_image_create_info {
uint32_t tile_mode;
};
VkResult anv_image_create(VkDevice _device,
const VkImageCreateInfo *pCreateInfo,
const struct anv_image_create_info *extra,
VkImage *pImage);
void anv_image_view_init(struct anv_surface_view *view,
struct anv_device *device,
const VkImageViewCreateInfo* pCreateInfo,

282
src/vulkan/x11.c Normal file
View File

@@ -0,0 +1,282 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "private.h"
#include <xcb/xcb.h>
#include <xcb/dri3.h>
#include <xcb/present.h>
static const VkFormat formats[] = {
VK_FORMAT_B5G6R5_UNORM,
VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_B8G8R8A8_SRGB,
};
VkResult anv_GetDisplayInfoWSI(
VkDisplayWSI display,
VkDisplayInfoTypeWSI infoType,
size_t* pDataSize,
void* pData)
{
VkDisplayFormatPropertiesWSI *properties = pData;
size_t size;
if (pDataSize == NULL)
return VK_ERROR_INVALID_POINTER;
switch (infoType) {
case VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI:
size = sizeof(properties[0]) * ARRAY_SIZE(formats);
if (pData && *pDataSize < size)
return vk_error(VK_ERROR_INVALID_VALUE);
*pDataSize = size;
for (uint32_t i = 0; i < ARRAY_SIZE(formats); i++)
properties[i].swapChainFormat = formats[i];
return VK_SUCCESS;
default:
return VK_UNSUPPORTED;
}
}
struct anv_swap_chain {
struct anv_device * device;
xcb_connection_t * conn;
xcb_window_t window;
xcb_gc_t gc;
VkExtent2D extent;
uint32_t count;
struct {
struct anv_image * image;
struct anv_device_memory * memory;
xcb_pixmap_t pixmap;
} images[0];
};
VkResult anv_CreateSwapChainWSI(
VkDevice _device,
const VkSwapChainCreateInfoWSI* pCreateInfo,
VkSwapChainWSI* pSwapChain)
{
struct anv_device *device = (struct anv_device *) _device;
struct anv_swap_chain *chain;
xcb_void_cookie_t cookie;
VkResult result;
size_t size;
int ret;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI);
size = sizeof(*chain) + pCreateInfo->imageCount * sizeof(chain->images[0]);
chain = anv_device_alloc(device, size, 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (chain == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
chain->device = device;
chain->conn = (xcb_connection_t *) pCreateInfo->pNativeWindowSystemHandle;
chain->window = (xcb_window_t) (uintptr_t) pCreateInfo->pNativeWindowHandle;
chain->count = pCreateInfo->imageCount;
chain->extent = pCreateInfo->imageExtent;
for (uint32_t i = 0; i < chain->count; i++) {
struct anv_image *image;
struct anv_device_memory *memory;
anv_image_create((VkDevice) device,
&(VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D,
.format = pCreateInfo->imageFormat,
.extent = {
.width = pCreateInfo->imageExtent.width,
.height = pCreateInfo->imageExtent.height,
.depth = 1
},
.mipLevels = 1,
.arraySize = 1,
.samples = 1,
/* FIXME: Need a way to use X tiling to allow scanout */
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.flags = 0,
},
&(struct anv_image_create_info) {
.tile_mode = XMAJOR
},
(VkImage *) &image);
anv_AllocMemory((VkDevice) device,
&(VkMemoryAllocInfo) {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
.allocationSize = image->size,
},
(VkDeviceMemory *) &memory);
anv_QueueBindObjectMemory(VK_NULL_HANDLE,
VK_OBJECT_TYPE_IMAGE,
(VkImage) image, 0,
(VkDeviceMemory) memory, 0);
ret = anv_gem_set_tiling(device, memory->bo.gem_handle,
image->stride, I915_TILING_X);
if (ret) {
result = vk_error(VK_ERROR_UNKNOWN);
goto fail;
}
int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle);
if (fd == -1) {
result = vk_error(VK_ERROR_UNKNOWN);
goto fail;
}
uint32_t bpp = 32;
uint32_t depth = 24;
xcb_pixmap_t pixmap = xcb_generate_id(chain->conn);
cookie =
xcb_dri3_pixmap_from_buffer_checked(chain->conn,
pixmap,
chain->window,
image->size,
pCreateInfo->imageExtent.width,
pCreateInfo->imageExtent.height,
image->stride,
depth, bpp, fd);
chain->images[i].image = image;
chain->images[i].memory = memory;
chain->images[i].pixmap = pixmap;
image->swap_chain = chain;
xcb_discard_reply(chain->conn, cookie.sequence);
}
chain->gc = xcb_generate_id(chain->conn);
if (!chain->gc) {
result = vk_error(VK_ERROR_UNKNOWN);
goto fail;
}
cookie = xcb_create_gc(chain->conn,
chain->gc,
chain->window,
XCB_GC_GRAPHICS_EXPOSURES,
(uint32_t []) { 0 });
xcb_discard_reply(chain->conn, cookie.sequence);
*pSwapChain = (VkSwapChainWSI) chain;
return VK_SUCCESS;
fail:
return result;
}
VkResult anv_DestroySwapChainWSI(
VkSwapChainWSI swapChain)
{
struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain;
struct anv_device *device = chain->device;
anv_device_free(device, chain);
return VK_SUCCESS;
}
VkResult anv_GetSwapChainInfoWSI(
VkSwapChainWSI swapChain,
VkSwapChainInfoTypeWSI infoType,
size_t* pDataSize,
void* pData)
{
struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain;
VkSwapChainImageInfoWSI *images;
size_t size;
switch (infoType) {
case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI:
size = sizeof(*images) * chain->count;
if (pData && *pDataSize < size)
return VK_ERROR_INVALID_VALUE;
*pDataSize = size;
if (!pData)
return VK_SUCCESS;
images = pData;
for (uint32_t i = 0; i < chain->count; i++) {
images[i].image = (VkImage) chain->images[i].image;
images[i].memory = (VkDeviceMemory) chain->images[i].memory;
}
return VK_SUCCESS;
default:
return VK_UNSUPPORTED;
}
}
VkResult anv_QueuePresentWSI(
VkQueue queue_,
const VkPresentInfoWSI* pPresentInfo)
{
struct anv_image *image = (struct anv_image *) pPresentInfo->image;
struct anv_swap_chain *chain = image->swap_chain;
xcb_void_cookie_t cookie;
xcb_pixmap_t pixmap;
assert(pPresentInfo->sType == VK_STRUCTURE_TYPE_PRESENT_INFO_WSI);
if (chain == NULL)
return vk_error(VK_ERROR_INVALID_VALUE);
pixmap = XCB_NONE;
for (uint32_t i = 0; i < chain->count; i++) {
if ((VkImage) chain->images[i].image == pPresentInfo->image) {
pixmap = chain->images[i].pixmap;
break;
}
}
if (pixmap == XCB_NONE)
return vk_error(VK_ERROR_INVALID_VALUE);
cookie = xcb_copy_area(chain->conn,
pixmap,
chain->window,
chain->gc,
0, 0,
0, 0,
chain->extent.width,
chain->extent.height);
xcb_discard_reply(chain->conn, cookie.sequence);
xcb_flush(chain->conn);
return VK_SUCCESS;
}