C.2. Window System Integration (WSI) Extensions

C.2.1. Editors

Significant specification work was performed by the following editors:

  • Ian Elliott, LunarG
  • Jesse Hall, Google
  • James Jones, NVIDIA
  • Daniel Rakos, AMD

Relevant information is now documented for each extension.

C.2.2. VK_KHR_surface

Name String
VK_KHR_surface
Extension Type
Instance extension
Registered Extension Number
1
Last Modified Date
01/14/2016
Revision
25
IP Status
No known IP claims.
Dependencies
  • This extension is written against revision 1.0 of the Vulkan API.
Contributors
  • Patrick Doane, Blizzard
  • Ian Elliott, LunarG
  • Jesse Hall, Google
  • James Jones, NVIDIA
  • David Mao, AMD
  • Norbert Nopper, Freescale
  • Alon Or-bach, Samsung
  • Daniel Rakos, AMD
  • Graham Sellers, AMD
  • Jeff Vigil, Qualcomm
  • Chia-I Wu, LunarG
  • Jason Ekstrand, Intel
Contacts
  • James Jones, NVIDIA
  • Ian Elliott, LunarG

The VK_KHR_surface extension is an instance extension. It introduces VkSurfaceKHR objects, which abstract native platform surface or window objects for use with Vulkan. It also provides a way to determine whether a queue family in a physical device supports presenting to particular surface.

Separate extensions for each each platform provide the mechanisms for creating VkSurfaceKHR objects, but once created they may be used in this and other platform-independent extensions, in particular the VK_KHR_swapchain extension.

New Object Types

  • VkSurfaceKHR

New Enum Constants

  • Extending VkResult:

    • VK_ERROR_SURFACE_LOST_KHR
    • VK_ERROR_NATIVE_WINDOW_IN_USE_KHR

New Enums

  • VkSurfaceTransformFlagBitsKHR
  • VkPresentModeKHR
  • VkColorSpaceKHR
  • VkCompositeAlphaFlagBitsKHR

Examples

[Note]Note

The example code for the VK_KHR_surface and VK_KHR_swapchain extensions will be removed from future versions of this appendix. The WSI example code was ported to the cube demo, that is shipped with the official Khronos SDK, and has been kept up-to-date in that location. There is little reason to maintain this example code in the appendix as well.

Example 1

Show how to obtain function pointers for WSI commands. Most applications should not need to do this, because the functions for the WSI extensions that are relevant for a given platform are exported by the official loader for that platform (e.g. the official Khronos loader for Microsoft Windows and Linux, and the Android loader). Other examples, will directly call the relevant command, not through a function pointer.

extern VkInstance instance;

...

// Obtain function pointers for the VK_KHR_surface commands:
PFN_vkGetPhysicalDeviceSurfaceSupportKHR pfnGetPhysicalDeviceSurfaceSupportKHR =
    (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr(instance,
                                                                    "vkGetPhysicalDeviceSurfaceSupportKHR");
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR pfnGetPhysicalDeviceSurfaceCapabilitiesKHR =
    (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)vkGetInstanceProcAddr(instance,
                                                                         "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR pfnGetPhysicalDeviceSurfaceFormatsKHR =
    (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)vkGetInstanceProcAddr(instance,
                                                                    "vkGetPhysicalDeviceSurfaceFormatsKHR");
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR pfnGetPhysicalDeviceSurfacePresentModesKHR =
    (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)vkGetInstanceProcAddr(instance,
                                                                         "vkGetPhysicalDeviceSurfacePresentModesKHR");

Example 2

Pick which queues on a physical device to use for graphics and present operations for a given surface, and create a device with those queues.

    extern VkInstance instance;
    extern VkPhysicalDevice physicalDevice;
    extern VkSurfaceKHR surface;
    extern void Error(const char *);

    uint32_t queueFamilyCount;
    vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice,
                                             &queueFamilyCount, NULL);

    VkQueueFamilyProperties* pMainQueueInfo =
        (VkQueueFamilyProperties*)malloc(queueFamilyCount * sizeof(VkQueueFamilyProperties));
    VkBool32* pSupportsPresent =
        (VkBool32 *)malloc(queueFamilyCount * sizeof(VkBool32));

    vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount,
                                             pMainQueueInfo);

    for (uint32_t i = 0; i < queueFamilyCount; ++i)
        vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface,
                                             &pSupportsPresent[i]);

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

            if (pSupportsPresent[i] == VK_TRUE)
            {
                graphicsQueueFamilyIndex = i;
                presentQueueFamilyIndex = i;
                break;
            }
        }
    }

    if (presentQueueFamilyIndex == UINT32_MAX)
    {
        // If didn't find a queue that supports both graphics and present, then
        // find a separate present queue.
        for (size_t i = 0; i < queueFamilyCount; ++i)
            if (pSupportsPresent[i] == VK_TRUE)
            {
                presentQueueFamilyIndex = i;
                break;
            }
    }

    // Free the temporary queue info allocations
    free(pMainQueueInfo);
    free(pSupportsPresent);

    // Generate error if could not find both a graphics and a present queue
    if (graphicsQueueFamilyIndex == UINT32_MAX ||
        presentQueueFamilyIndex == UINT32_MAX)
    {
        Error("Could not find a graphics and a present queue");
    }

    // Put together the list of requested queues
    const float queuePriority = 1.0f;
    const VkDeviceQueueCreateInfo requestedQueues[] =
    {
        {
            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
            NULL,                                       // pNext
            0,                                          // flags
            graphicsQueueFamilyIndex,                   // queueFamilyIndex
            1,                                          // queueCount
            &queuePriority                              // pQueuePriorities
        },
        {
            VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
            NULL,                                       // pNext
            0,                                          // flags
            presentQueueFamilyIndex,                    // queueFamilyIndex
            1,                                          // queueCount
            &queuePriority                              // pQueuePriorities
        }
    };
    uint32_t requestedQueueCount = 2;

    if (graphicsQueueFamilyIndex == presentQueueFamilyIndex)
    {
        // We need only a single queue if the graphics queue is also the
        // present queue
        requestedQueueCount = 1;
    }

    // Create a device and request access to the specified queues
    const VkDeviceCreateInfo deviceCreateInfo =
    {
        VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,           // sType
        NULL,                                           // pNext
        0,                                              // flags
        requestedQueueCount,                            // queueCreateInfoCount
        &requestedQueues,                               // pQueueCreateInfos
        ...
    };

    VkDevice device;
    vkCreateDevice(physicalDevice, &deviceCreateInfo, &device);

    // Acquire graphics and present queue handle from device
    VkQueue graphicsQueue, presentQueue;
    vkGetDeviceQueue(device, graphicsQueueFamilyIndex, 0, &graphicsQueue);
    vkGetDeviceQueue(device, presentQueueFamilyIndex, 0, &presentQueue);

Issues

1) Should this extension include a method to query whether a physical device supports presenting to a specific window or native surface on a given platform?

RESOLVED: Yes.  Without this, applications would need to create
a device instance to determine whether a particular window can be
presented to.  Knowing that a device supports presentation to a
platform in general is not sufficient, as a single machine might
support multiple seats, or instances of the platform that each use
different underlying physical devices.  Additionally, some platforms,
such as X windows, different drivers and devices might be used for
different windows depending on which section of the desktop they
exist on.

2) Should the vkGetSurfacePropertiesKHR(), vkGetSurfaceFormatsKHR(), and vkGetSurfacePresentModesKHR() functions from VK_KHR_swapchain be modified to operate on physical devices and moved to this extension to implement the resolution of issue 1?

RESOLVED: No, separate query functions are needed, as the purposes
served are similar but incompatible.  The vkGetSurface*KHR functions
return information that could potentially depend on an initialized
device.  For example, the formats supported for presentation to the
surface might vary depending on which device extensions are enabled.
The query introduced to resolve issue 1 should be used only to query
generic driver or platform properties.  The physical device
parameter is intended to serve only as an identifier rather than
a stateful object.

3) Should Vulkan include support Xlib or XCB as the API for accessing the X Window System platform?

RESOLVED: Both.  XCB is a more modern and efficient API, but Xlib
usage is deeply ingrained in many applications and likely will remain
in use for the foreseeable future.  Not all drivers necessarily need to
support both, but including both as options in the core specification
will probably encourage support, which should in turn eases adoption of
the Vulkan API in older codebases.  Additionally, the performance
improvements possible with XCB likely won't have a measurable impact
on the performance of Vulkan presentation and other minimal window
system interactions defined here.

4) Should the GBM platform be included in the list of platform enums?

RESOLVED: Deferred, and will be addressed with a platform-specific
extension to be written in the future.

Version History

  • Revision 1, 2015-05-20 (James Jones)

    • Initial draft, based on LunarG KHR spec, other KHR specs, patches attached to bugs.
  • Revision 2, 2015-05-22 (Ian Elliott)

    • Created initial Description section.
    • Removed query for whether a platform requires the use of a queue for presentation, since it was decided that presentation will always be modeled as being part of the queue.
    • Fixed typos and other minor mistakes.
  • Revision 3, 2015-05-26 (Ian Elliott)

    • Improved the Description section.
  • Revision 4, 2015-05-27 (James Jones)

    • Fixed compilation errors in example code.
  • Revision 5, 2015-06-01 (James Jones)

    • Added issues 1 and 2 and made related spec updates.
  • Revision 6, 2015-06-01 (James Jones)

    • Merged the platform type mappings table previously removed from VK_KHR_swapchain with the platform description table in this spec.
    • Added issues 3 and 4 documenting choices made when building the initial list of native platforms supported.
  • Revision 7, 2015-06-11 (Ian Elliott)

    • Updated table 1 per input from the KHR TSG.
    • Updated issue 4 (GBM) per discussion with Daniel Stone. He will create a platform-specific extension sometime in the future.
  • Revision 8, 2015-06-17 (James Jones)

    • Updated enum-extending values using new convention.
    • Fixed the value of VK_SURFACE_PLATFORM_INFO_TYPE_SUPPORTED_KHR.
  • Revision 9, 2015-06-17 (James Jones)

    • Rebased on Vulkan API version 126.
  • Revision 10, 2015-06-18 (James Jones)

    • Marked issues 2 and 3 resolved.
  • Revision 11, 2015-06-23 (Ian Elliott)

    • Examples now show use of function pointers for extension functions.
    • Eliminated extraneous whitespace.
  • Revision 12, 2015-07-07 (Daniel Rakos)

    • Added error section describing when each error is expected to be reported.
    • Replaced the term "queue node index" with "queue family index" in the spec as that is the agreed term to be used in the latest version of the core header and spec.
    • Replaced bool32_t with VkBool32.
  • Revision 13, 2015-08-06 (Daniel Rakos)

    • Updated spec against latest core API header version.
  • Revision 14, 2015-08-20 (Ian Elliott)

    • Renamed this extension and all of its enumerations, types, functions, etc. This makes it compliant with the proposed standard for Vulkan extensions.
    • Switched from "revision" to "version", including use of the VK_MAKE_VERSION macro in the header file.
    • Did miscellaneous cleanup, etc.
  • Revision 15, 2015-08-20 (Ian Elliott—porting a 2015-07-29 change from James Jones)

    • Moved the surface transform enums here from VK_WSI_swapchain so they could be re-used by VK_WSI_display.
  • Revision 16, 2015-09-01 (James Jones)

    • Restore single-field revision number.
  • Revision 17, 2015-09-01 (James Jones)

    • Fix example code compilation errors.
  • Revision 18, 2015-09-26 (Jesse Hall)

    • Replaced VkSurfaceDescriptionKHR with the VkSurfaceKHR object, which is created via layered extensions. Added VkDestroySurfaceKHR.
  • Revision 19, 2015-09-28 (Jesse Hall)

    • Renamed from VK_EXT_KHR_swapchain to VK_EXT_KHR_surface.
  • Revision 20, 2015-09-30 (Jeff Vigil)

    • Add error result VK_ERROR_SURFACE_LOST_KHR.
  • Revision 21, 2015-10-15 (Daniel Rakos)

    • Updated the resolution of issue #2 and include the surface capability queries in this extension.
    • Renamed SurfaceProperties to SurfaceCapabilities as it better reflects that the values returned are the capabilities of the surface on a particular device.
    • Other minor cleanup and consistency changes.
  • Revision 22, 2015-10-26 (Ian Elliott)

    • Renamed from VK_EXT_KHR_surface to VK_KHR_surface.
  • Revision 23, 2015-11-03 (Daniel Rakos)

    • Added allocation callbacks to vkDestroySurfaceKHR.
  • Revision 24, 2015-11-10 (Jesse Hall)

    • Removed VkSurfaceTransformKHR. Use VkSurfaceTransformFlagBitsKHR instead.
    • Rename VkSurfaceCapabilitiesKHR member maxImageArraySize to maxImageArrayLayers.
  • Revision 25, 2016-01-14 (James Jones)

    • Moved VK_ERROR_NATIVE_WINDOW_IN_USE_KHR from the VK_KHR_android_surface to the VK_KHR_surface extension.
  • 2016-08-23 (Ian Elliott)

    • Update the example code, to not have so many characters per line, and to split out a new example to show how to obtain function pointers.
  • 2016-08-25 (Ian Elliott)

    • A note was added at the beginning of the example code, stating that it will be removed from future versions of the appendix.

C.2.3. VK_KHR_swapchain

Name String
VK_KHR_swapchain
Extension Type
Device extension
Registered Extension Number
2
Last Modified Date
04/05/2016
Revision
68
IP Status
No known IP claims.
Dependencies
  • This extension is written against revision 1.0 of the Vulkan API.
  • This extension requires VK_KHR_surface.
Contributors
  • Patrick Doane, Blizzard
  • Ian Elliott, LunarG
  • Jesse Hall, Google
  • Mathias Heyer, NVIDIA
  • James Jones, NVIDIA
  • David Mao, AMD
  • Norbert Nopper, Freescale
  • Alon Or-bach, Samsung
  • Daniel Rakos, AMD
  • Graham Sellers, AMD
  • Jeff Vigil, Qualcomm
  • Chia-I Wu, LunarG
  • Jason Ekstrand, Intel
  • Matthaeus G. Chajdas, AMD
  • Ray Smith, ARM
Contacts
  • James Jones, NVIDIA
  • Ian Elliott, LunarG

The VK_KHR_swapchain extension is the device-level companion to the VK_KHR_surface extension. It introduces VkSwapchainKHR objects, which provide the ability to present rendering results to a surface.

New Object Types

  • VkSwapchainKHR

New Enum Constants

  • Extending VkStructureType:

    • VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR
    • VK_STRUCTURE_TYPE_PRESENT_INFO_KHR
  • Extending VkImageLayout:

    • VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
  • Extending VkResult:

    • VK_SUBOPTIMAL_KHR
    • VK_ERROR_OUT_OF_DATE_KHR

New Enums

None

Issues

1) Does this extension allow the application to specify the memory backing of the presentable images?

RESOLVED: No.  Unlike standard images, the implementation will
allocate the memory backing of the presentable image.

2) What operations are allowed on presentable images?

RESOLVED: This is determined by the imageUsageFlags specified
when creating the presentable image's swapchain.

3) Does this extension support MSAA presentable images?

RESOLVED: No.  Presentable images are always single-sampled.
Multi-sampled rendering must use regular images.  To present the
rendering results the application must manually resolve the multi-
sampled image to a single-sampled presentable image prior to
presentation.

4) Does this extension support stereo/multi-view presentable images?

RESOLVED: Yes.  The number of views associated with a presentable
image is determined by the imageArraySize specified when creating
a swapchain.  All presentable images in a given swapchain use
the same array size.

5) Are the layers of stereo presentable images half-sized?

RESOLVED: No.  The image extents always match those requested
by the application.

6) Do the "present" and "acquire next image" commands operate on a queue? If not, do they need to include explicit semaphore objects to interlock them with queue operations?

RESOLVED: The present command operates on a queue.  The image
ownership operation it represents happens in order with other
operations on the queue, so no explicit semaphore object is
required to synchronize its actions.  Applications may want to
acquire the next image in separate threads from those in which
they manage their queue, or in multiple threads.  To make such
usage easier, the acquire next image command takes a semaphore
to signal as a method of explicit synchronization.  The
application must later queue a wait for this semaphore before
queuing execution of any commands using the image.

7) Does vkAcquireNextImageKHR() block if no images are available?

RESOLVED: The command takes a timeout parameter.  Special values
for the timeout are 0, which makes the call a non-blocking
operation, and UINT64_MAX, which blocks indefinitely.  Values in
between will block for up to the specified time.  The call will
return when an image becomes available or an error occurs.  It
may, but is not required to, return before the specified timeout
expires if the swapchain becomes out of date.

8) Can multiple presents be queued using one QueuePresent call?

RESOLVED: Yes.  VkPresentInfoKHR contains a list of swapchains
and corresponding image indices that will be presented.  When
supported, all presentations queued with a single vkQueuePresentKHR
call will be applied atomically as one operation.  The same swapchain
must not appear in the list more than once.  Later extensions may
provide applications stronger guarantees of atomicity for such present
operations, and/or allow them to query whether atomic presentation of a
particular group of swapchains is possible.

9) How do the presentation and acquire next image functions notify the application the targeted surface has changed?

RESOLVED: Two new result codes are introduced for this purpose:
VK_SUBOPTIMAL_KHR - Presentation will still succeed, subject to the
window resize behavior, but the swapchain is no longer configured
optimally for the surface it targets.  Applications should query
updated surface information and recreate their swapchain at the next
convenient opportunity.
VK_ERROR_OUT_OF_DATE_KHR - Failure.  The swapchain is no longer
compatible with the surface it targets.  The application must
query updated surface information and recreate the swapchain
before presentation will succeed.
These can be returned by both vkAcquireNextImageKHR and
vkQueuePresentKHR.

10) Does the vkAcquireNextImageKHR command return a semaphore to the application via an output parameter, or accept a semaphore to signal from the application as an object handle parameter?

RESOLVED: Accept a semaphore to signal as an object handle.  This
avoids the need to specify whether the application must destroy
the semaphore or whether it is owned by the swapchain, and if
the latter, what its lifetime is and whether it can be re-used
for other operations once it is received from
vkAcquireNextImageKHR.

11) What types of swapchain queuing behavior should be exposed? Options include swap interval specification, mailbox/most recent Vs. FIFO queue management, targeting specific vertical blank intervals or absolute times for a given present operation, and probably others. For some of these, whether they are specified at swapchain creation time or as per-present parameters needs to be decided as well.

RESOLVED: The base swapchain extension will expose 3 possible
behaviors (of which, FIFO will always be supported):
-Immediate present: Does not wait for vertical blanking period to
 update the current image, likely resulting in visible tearing.
 No internal queue is used.  Present requests are applied
 immediately.
-Mailbox queue: Waits for the next vertical blanking period to
 update the current image.  No tearing should be observed.  An
 internal single-entry queue is used to hold pending presentation
 requests.  If the queue is full when a new presentation
 request is received, the new request replaces the existing entry,
 and any images associated with the prior entry become available
 for re-use by the application.
-FIFO queue: Waits for the next vertical blanking period to update
 the current image.  No tearing should be observed.  An internal
 queue containing (numSwapchainImages - 1) entries is used to
 hold pending presentation requests.  New requests are appended to
 the end of the queue, and one request is removed from the beginning
 of the queue and processed during each vertical blanking period in
 which the queue is non-empty
Not all surfaces will support all of these modes, so the modes
supported will be returned using a surface info query.  All
surfaces must support the FIFO queue mode.  Applications must choose
one of these modes up front when creating a swapchain.  Switching
modes can be accomplished by recreating the swapchain.

12) Can VK_PRESENT_MODE_MAILBOX_KHR provide non-blocking guarantees for vkAcquireNextImageKHR()? If so, what is the proper criteria?

RESOLVED: Yes.  The difficulty is not immediately obvious here.
Naively, if at least 3 images are requested, mailbox mode should
always have an image available for the application if the application
does not own any images when the call to vkAcquireNextImageKHR() was
made.  However, some presentation engines may have more than one
"current" image, and would still need to block in some cases.  The
right requirement appears to be that if the application allocates the
surface's minimum number of images + 1 then it is guaranteed non-
blocking behavior when it does not currently own any images.

13) Is there a way to create and initialize a new swapchain for a surface that has generated a VK_SUBOPTIMAL_KHR return code while still using the old swapchain?

RESOLVED: Not as part of this specification.  This could be useful to
allow the application to create an "optimal" replacement swapchain
and rebuild all its command buffers using it in a background thread at
a low priority while continuing to use the "suboptimal" swapchain in
the main thread.  It could probably use the same "atomic replace"
semantics proposed for recreating direct-to-device swapchains without
incurring a mode switch.  However, after discussion, it was determined
some platforms probably could not support concurrent swapchains for
the same surface though, so this will be left out of the base KHR
extensions.  A future extension could add this for platforms where it
is supported.

14) Should there be a special value for VkSurfacePropertiesKHR::maxImageCount to indicate there are no practical limits on the number of images in a swapchain?

RESOLVED: Yes.  There where often be cases where there is no practical
limit to the number of images in a swapchain other than the amount of
available resources (I.e., memory) in the system.  Trying to derive a
hard limit from things like memory size is prone to failure.  It is
better in such cases to leave it to applications to figure such soft
limits out via trial/failure iterations.

15) Should there be a special value for VkSurfacePropertiesKHR::currentExtent to indicate the size of the platform surface is undefined?

RESOLVED: Yes.  On some platforms (Wayland, for example), the surface
size is defined by the images presented to it rather than the other
way around.

16) Should there be a special value for VkSurfacePropertiesKHR::maxImageExtent to indicate there is no practical limit on the surface size?

RESOLVED: No.  It seems unlikely such a system would exist.  0 could
be used to indicate the platform places no limits on the extents
beyond those imposed by Vulkan for normal images, but this query could
just as easily return those same limits, so a special "unlimited"
value doesn't seem useful for this field.

17) How should surface rotation and mirroring be exposed to applications? How do they specify rotation and mirroring transforms applied prior to presentation?

RESOLVED: Applications can query both the supported and current
transforms of a surface.  Both are specified relative to the device's
"natural" display rotation and direction.  The supported transforms
indicates which orientations the presentation engine accepts images
in.  For example, a presentation engine that does not support
transforming surfaces as part of presentation, and which is presenting
to a surface that is displayed with a 90-degree rotation, would return
only one supported transform bit: VK_SURFACE_TRANSFORM_ROT90_BIT_KHR.
Applications must transform their rendering by the transform they
specify when creating the swapchain in preTransform field.

18) Can surfaces ever not support VK_MIRROR_NONE? Can they support vertical and horizontal mirroring simultaneously? Relatedly, should VK_MIRROR_NONE[_BIT] be zero, or bit one, and should applications be allowed to specify multiple pre and current mirror transform bits, or exactly one?

RESOLVED: Since some platforms may not support presenting with a
transform other than the native window's current transform, and
prerotation/mirroring are specified relative to the device's
natural rotation and direction, rather than relative to the surface's
current rotation and direction, it is necessary to express lack of
support for no mirroring.  To allow this, the MIRROR_NONE enum must
occupy a bit in the flags.  Since MIRROR_NONE must be a bit in the
bitmask rather than a bitmask with no values set, allowing more
than one bit to be set in the bitmask would make it possible to
describe undefined transforms such as VK_MIRROR_NONE_BIT |
VK_MIRROR_HORIZONTAL_BIT, or a transform that includes both "no
mirroring" and "horizontal mirroring simultaneously.  Therefore, it
is desirable to allow specifying all supported mirroring transforms
using only one bit.  The question then becomes, should there be a
VK_MIRROR_HORIZONTAL_AND_VERTICAL_BIT to represent a simultaneous
horizontal and vertical mirror transform?  However, such a transform
is equivalent to a 180 degree rotation, so presentation engines and
applications that wish to support or use such a transform can express
it through rotation instead.  Therefore, 3 exclusive bits are
sufficient to express all needed mirroring transforms.

19) Should support for sRGB be required?

RESOLVED: In the advent of UHD and HDR display devices, proper
color space information is vital to the display pipeline
represented by the swapchain.  The app can discover the
supported format/color-space pairs and select a pair most suited
to its rendering needs.  Currently only the sRGB color space is
supported, future extensions may provide support for more
color spaces.  See issues 23) and 24).

20) Is there a mechanism to modify or replace an existing swapchain with one targeting the same surface?

RESOLVED: Yes.  This is described above in the text.

21) Should there be a way to set prerotation and mirroring using native APIs when presenting using a Vulkan swapchain?

RESOLVED: Yes.  The transforms that can be expressed in this extension
are a subset of those possible on native platforms.  If a platform
exposes a method to specify the transform of presented images for a
given surface using native methods and exposes more transforms or
other properties for surfaces than Vulkan supports, it might be
impossible, difficult, or inconvenient to set some of those properties
using Vulkan KHR extensions and some using the native interfaces.  To
avoid overwriting properties set using native commands when presenting
using a Vulkan swapchain, the application can set the pretransform to
"inherit", in which case the current native properties will be used, or
if none are available, a platform-specific default will be used.
Platforms that do not specify a reasonable default or do not provide
native mechanisms to specify such transforms should not include the
inherit bits in the supportedTransform bitmask they return in
VkSurfacePropertiesKHR.

22) Should the content of presentable images be clipped by objects obscuring their target surface?

RESOLVED: Applications can choose which behavior they prefer.  Allowing
the content to be clipped could enable more optimal presentation
methods on some platforms, but some applications might rely on the
content of presentable images to perform techniques such as partial
updates or motion blurs.

23) What is the purpose of specifying a VkColorSpaceKHR along with VkFormat when creating a swapchain?

RESOLVED: While Vulkan itself is color space agnostic (e.g. even the
meaning of R, G, B and A can be freely defined by the rendering
application), the swapchain eventually will have to present the
images on a display device with specific color reproduction
characteristics.  If any color space transformations are
necessary before an image can be displayed, the color space of
the presented image must be known to the swapchain.  A swapchain
will only support a restricted set of color format and -space
pairs.  This set can be discovered via vkGetSurfaceInfoKHR.  As
it can be expected that most display devices support the sRGB
color space, at least one format/color-space pair has to be
exposed, where the color space is VK_COLOR_SPACE_SRGB_NONLINEAR.

24) How are sRGB formats and the sRGB color space related?

RESOLVED: While Vulkan exposes a number of SRGB texture formats, using
such formats does not guarantee working in a specific
color space.  It merely means that the hardware can directly
support applying the non-linear transfer functions defined by
the sRGB standard color space when reading from or writing to
images of that these formats.  Still, it is unlikely that a
swapchain will expose a _SRGB format along with any color space
other than VK_COLOR_SPACE_SRGB_NONLINEAR.
On the other hand, non-_SRGB formats will be very likely
exposed in pair with a SRGB color space.  This means, the
hardware will not apply any transfer function when reading
from or writing to such images, yet they will still be
presented on a device with sRGB display characteristics.
In this case the application is responsible for applying the
transfer function, for instance by using shader math.

25) How are the lifetime of surfaces and swapchains targeting them related?

RESOLVED: A surface must outlive any swapchains targeting it.  A
VkSurfaceKHR owns the binding of the native window to the Vulkan
driver.

26) How can the client control the way the alpha channel of swap chain images is treated by the presentation engine during compositing?

RESOLVED: We should add new enum values to allow the client to
negotiate with the presentation engine on how to treat image alpha
values during the compositing process.  Since not all platforms
can practically control this through the Vulkan driver, a value of
INHERIT is provided like for surface transforms.

27) Is vkCreateSwapchainKHR() the right function to return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR, or should the various platform- specific VkSurface factory functions catch this error earlier?

RESOLVED: For most platforms, the VkSurface structure is a simple
container holding the data that identifies a native window or
other object representing a surface on a particular platform.  For
the surface factory functions to return this error, they would
likely need to register a reference on the native objects with
the native display server some how, and ensure no other such
references exist.  Surfaces were not intended to be that heavy-
weight.
Swapchains are intended to be the objects that directly manipulate
native windows and communicate with the native presentation
mechanisms.  Swapchains will already need to communicate with the
native display server to negotiate allocation and/or presentation of
presentable images for a native surface.  Therefore, it makes more
sense for swapchain creation to be the point at which native object
exclusivity is enforced.  Platforms may choose to enforce further
restrictions on the number of VkSurface objects that may be created
for the same native window if such a requirement makes sense on a
particular platform, but a global requirement is only sensible at the
swapchain level.

Examples

[Note]Note

The example code for the VK_KHR_surface and VK_KHR_swapchain extensions will be removed from future versions of this appendix. The WSI example code was ported to the cube demo, that is shipped with the official Khronos SDK, and has been kept up-to-date in that location. There is little reason to maintain this example code in the appendix as well.

Example 1

Show how to obtain function pointers for WSI commands. Most applications shouldn’t need to do this, because the functions for the WSI extensions that are relevant for a given platform are exported by the official loader for that platform (e.g. the official Khronos loader for Microsoft Windows and Linux, and the Android loader). Other examples, will directly call the relevant command, not through a function pointer.

extern VkDevice device;

...

// Obtain function pointers for the VK_KHR_swapchain commands:
PFN_vkCreateSwapchainKHR pfnCreateSwapchainKHR =
    (PFN_vkCreateSwapchainKHR)vkGetDeviceProcAddr(device,
                                                  "vkCreateSwapchainKHR");
PFN_vkGetSwapchainImagesKHR pfnGetSwapchainImagesKHR =
    (PFN_vkGetSwapchainImagesKHR)vkGetDeviceProcAddr(device,
                                                     "vkGetSwapchainImagesKHR");
PFN_vkAcquireNextImageKHR pfnAcquireNextImageKHR =
    (PFN_vkAcquireNextImageKHR)vkGetDeviceProcAddr(device,
                                                   "vkAcquireNextImageKHR");
PFN_vkQueuePresentKHR pfnQueuePresentKHR =
    (PFN_vkQueuePresentKHR)vkGetDeviceProcAddr(device,
                                               "vkQueuePresentKHR");
PFN_vkDestroySwapchainKHR pfnDestroySwapchainKHR =
    (PFN_vkDestroySwapchainKHR)vkGetDeviceProcAddr(device,
                                                   "vkDestroySwapchainKHR");

Example 2

Create a swapchain for a surface on a particular instance of a native platform.

    extern VkPhysicalDevice physicalDevice;
    extern VkDevice device;
    extern VkSurfaceKHR surface;

    // Check the surface properties and formats
    VkSurfaceCapabilitiesKHR surfCapabilities;
    vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
                                              &surfCapabilities);

    uint32_t formatCount;
    vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
                                         &formatCount, NULL);

    VkSurfaceFormatKHR* pSurfFormats =
        (VkSurfaceFormatKHR*)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
    vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface,
                                         &formatCount, pSurfFormats);

    uint32_t presentModeCount;
    vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
                                              &presentModeCount, NULL);

    VkPresentModeKHR* pPresentModes =
        (VkPresentModeKHR*)malloc(presentModeCount * sizeof(VkPresentModeKHR));
    vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
                                              &presentModeCount, pPresentModes);

    VkExtent2D swapchainExtent;
    // width and height are either both 0xFFFFFFFF, or both not 0xFFFFFFFF.
    if (surfCapabilities.currentExtent.width == 0xFFFFFFFF)
    {
        // If the surface size is undefined, the size is set to the size
        // of the images requested, which must fit within the minimum and
        // maximum values.
        swapchainExtent.width = 320;
        swapchainExtent.height = 320;

        if (swapchainExtent.width < surfCapabilities.minImageExtent.width)
            swapchainExtent.width = surfCapabilities.minImageExtent.width;
        else if (swapchainExtent.width > surfCapabilities.maxImageExtent.width)
            swapchainExtent.width = surfCapabilities.maxImageExtent.width;

        if (swapchainExtent.height < surfCapabilities.minImageExtent.height)
            swapchainExtent.height = surfCapabilities.minImageExtent.height;
        else if (swapchainExtent.height > surfCapabilities.maxImageExtent.height)
            swapchainExtent.height = surfCapabilities.maxImageExtent.height;
    }
    else
    {
        // If the surface size is defined, the swapchain size must match
        swapchainExtent = surfCapabilities.currentExtent;
    }

    // Application desires to simultaneously acquire 2 images (which is one
    // more than "surfCapabilities.minImageCount").
    uint32_t desiredNumOfSwapchainImages = surfCapabilities.minImageCount + 1;
    if ((surfCapabilities.maxImageCount > 0) &&
        (desiredNumOfSwapchainImages > surfCapabilities.maxImageCount))
    {
        // Application must settle for fewer images than desired:
        desiredNumOfSwapchainImages = surfCapabilities.maxImageCount;
    }

    VkFormat swapchainFormat;
    // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
    // the surface has no preferred format.  Otherwise, at least one
    // supported format will be returned (assuming that the
    // vkGetPhysicalDeviceSurfaceSupportKHR function, in the
    // VK_KHR_surface extension returned support for the surface).
    if ((formatCount == 1) && (pSurfFormats[0].format == VK_FORMAT_UNDEFINED))
        swapchainFormat = VK_FORMAT_R8G8B8_UNORM;
    else
    {
        assert(formatCount >= 1);
        swapchainFormat = pSurfFormats[0].format;
    }
    VkColorSpaceKHR swapchainColorSpace = pSurfFormats[0].colorSpace;

    // If mailbox mode is available, use it, as it is the lowest-latency non-
    // tearing mode.  If not, fall back to FIFO which is always available.
    VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
    for (size_t i = 0; i < presentModeCount; ++i)
    {
        if (pPresentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
        {
            swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
            break;
        }
    }

    const VkSwapchainCreateInfoKHR createInfo =
    {
        VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,    // sType
        NULL,                                           // pNext
        0,                                              // flags
        surface,                                        // surface
        desiredNumOfSwapchainImages,                    // minImageCount
        swapchainFormat,                                // imageFormat
        swapchainColorSpace,                            // imageColorSpace
        swapchainExtent,                                // imageExtent
        1,                                              // imageArrayLayers
        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,            // imageUsage
        VK_SHARING_MODE_EXCLUSIVE,                      // imageSharingMode
        0,                                              // queueFamilyIndexCount
        NULL,                                           // pQueueFamilyIndices
        surfCapabilities.currentTransform,              // preTransform
        VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,             // compositeAlpha
        swapchainPresentMode,                           // presentMode
        VK_TRUE,                                        // clipped
        VK_NULL_HANDLE                                  // oldSwapchain
    };

    VkSwapchainKHR swapchain;
    vkCreateSwapchainKHR(device, &createInfo, NULL, &swapchain);

Example 3

Obtaining the persistent images of a swapchain

    extern VkDevice device;

    uint32_t swapchainImageCount;
    vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, NULL);

    VkImage* pSwapchainImages = (VkImage*)malloc(swapchainImageCount * sizeof(VkImage));
    vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, pSwapchainImages);

Example 4

Simple rendering and presenting using separate graphics and present queues.

    extern VkDevice device;

    // Construct command buffers rendering to the presentable images
    VkCmdBuffer cmdBuffers[swapchainImageCount];
    VkImageView views[swapchainImageCount];
    extern VkCmdBufferBeginInfo beginInfo;
    extern uint32_t graphicsQueueFamilyIndex, presentQueueFamilyIndex;

    for (size_t i = 0; i < swapchainImageCount; ++i)
    {
        const VkImageViewCreateInfo viewInfo =
        {
            VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // sType
            NULL,                                       // pNext
            0,                                          // flags
            pSwapchainImages[i],                        // image
            VK_IMAGE_VIEW_TYPE_2D,                      // viewType
            swapchainFormat,                            // format
            ...
        };
        vkCreateImageView(device, &viewInfo, &views[i]);

        ...

        vkBeginCommandBuffer(cmdBuffers[i], &beginInfo);

        // Need to transition image from presentable state before being able
        // to render
        const VkImageMemoryBarrier acquireImageBarrier =
        {
            VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // sType
            NULL,                                       // pNext
            VK_ACCESS_MEMORY_READ_BIT,                  // srcAccessMask
            VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // dstAccessMask
            VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,            // oldLayout
            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // newLayout
            presentQueueFamilyIndex,                    // srcQueueFamilyIndex
            graphicsQueueFamilyIndex,                   // dstQueueFamilyIndex
            pSwapchainImages[i].image,                  // image
            ...
        };

        vkCmdPipelineBarrier(
            cmdBuffers[i],
            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
            VK_FALSE,
            1,
            &acquireImageBarrier)

        // ... Render to views[i] ...

        // Need to transition image into presentable state before being able
        // to present
        const VkImageMemoryBarrier presentImageBarrier =
        {
            VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // sType
            NULL,                                       // pNext
            VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // srcAccessMask
            VK_ACCESS_MEMORY_READ_BIT,                  // dstAccessMask
            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // oldLayout
            VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,            // newLayout
            graphicsQueueFamilyIndex,                   // srcQueueFamilyIndex
            presentQueueFamilyIndex,                    // dstQueueFamilyIndex
            pSwapchainImages[i].image,                  // image
            ...
        };

        vkCmdPipelineBarrier(
            cmdBuffers[i],
            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
            VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
            VK_FALSE,
            1,
            &presentImageBarrier);

        ...

        vkEndCommandBuffer(cmdBuffers[i]);
    }

    const VkSemaphoreCreateInfo semaphoreCreateInfo =
    {
        VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,    // sType
        NULL,                                       // pNext
        0                                           // flags
    };

    VkSemaphore imageAcquiredSemaphore;
    vkCreateSemaphore(device,
                      &semaphoreCreateInfo,
                      &imageAcquiredSemaphore);

    VkSemaphore renderingCompleteSemaphore;
    vkCreateSemaphore(device,
                      &semaphoreCreateInfo,
                      &renderingCompleteSemaphore);

    VkResult result;
    do
    {
        uint32_t imageIndex = UINT32_MAX;

        // Get the next available swapchain image
        result = vkAcquireNextImageKHR(
            device,
            swapchain,
            UINT64_MAX,
            imageAcquiredSemaphore,
            VK_NULL_HANDLE,
            &imageIndex);

        // Swapchain cannot be used for presentation if failed to acquired
        // new image.
        if (result < 0)
            break;

        // Submit rendering work to the graphics queue
        const VkPipelineStageFlags waitDstStageMask =
            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
        const VkSubmitInfo submitInfo =
        {
            VK_STRUCTURE_TYPE_SUBMIT_INFO,          // sType
            NULL,                                   // pNext
            1,                                      // waitSemaphoreCount
            &imageAcquiredSemaphore,                // pWaitSemaphores
            &waitDstStageMask,                      // pWaitDstStageMasks
            1,                                      // commandBufferCount
            &cmdBuffers[imageIndex],                // pCommandBuffers
            1,                                      // signalSemaphoreCount
            &renderingCompleteSemaphore             // pSignalSemaphores
        };
        vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);

        // Submit present operation to present queue
        const VkPresentInfoKHR presentInfo =
        {
            VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,     // sType
            NULL,                                   // pNext
            1,                                      // waitSemaphoreCount
            &renderingCompleteSemaphore,            // pWaitSemaphores
            1,                                      // swapchainCount
            &swapchain,                             // pSwapchains
            &imageIndex,                            // pImageIndices
            NULL                                    // pResults
        };

        result = vkQueuePresentKHR(presentQueue, &presentInfo);
    } while (result >= 0);

Example 5

Handle VK_ERROR_OUT_OF_DATE_KHR by recreating the swapchain and VK_SUBOPTIMAL_KHR by checking whether recreation is needed.

    extern VkInstance instance;
    extern VkPhysicalDevice physicalDevice;
    extern VkDevice device;
    extern VkQueue presentQueue;
    extern VkSurfaceKHR surface;

    // Contains code to build the application's reusable command buffers.
    extern void CreateCommandBuffers(VkDevice device,
                                     const VkImage* swapchainImages);

    // Returns non-zero if the application considers the swapchain out
    // of date even though it is still compatible with the platform
    // surface it is targeting.
    extern int MustRecreateSwapchain(VkDevice device,
                                     VkSwapchainKHR swapchain,
                                     VkSurfaceKHR surface);

    extern void CreateSwapchain(VkDevice device,
                                VkSurfaceKHR surface,
                                VkSwapchainKHR oldSwapchain,
                                VkSwapchainKHR* pSwapchain);
    {
        ...

        // Most of this function is identical to what is in Example 2.
        //  One differences is in the initialization of the following struct.

        const VkSwapchainCreateInfoKHR createInfo =
        {
            VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,  // sType
            NULL,                                         // pNext
            0,                                            // flags
            surface,                                      // surface
            desiredNumOfSwapchainImages,                  // minImageCount
            swapchainFormat,                              // imageFormat
            swapchainColorSpace,                          // imageColorSpace
            swapchainExtent,                              // imageExtent
            1,                                            // imageArrayLayers
            VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,          // imageUsage
            VK_SHARING_MODE_EXCLUSIVE,                    // imageSharingMode
            0,                                            // queueFamilyIndexCount
            NULL,                                         // pQueueFamilyIndices
            surfCapabilities.currentTransform,            // preTransform
            VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,           // compositeAlpha
            swapchainPresentMode,                         // presentMode
            VK_TRUE,                                      // clipped

            // If the caller specified an existing swapchain, replace it with
            // the new swapchain being created here.  This will allow a
            // seamless transition between the old and new swapchains on
            // platforms that support it.
            oldSwapchain                                  // oldSwapchain
        };

        ...

        // Another difference is in the need to destroy the old swapchain, if
        // it exists.
        //
        // Note: destroying the swapchain also cleans up all its associated
        // presentable images once the platform is done with them.
        if (oldSwapchain != VK_NULL_HANDLE)
        {
            vkDestroySwapchainKHR(device, oldSwapchain, NULL);
        }
    }

    void mainLoop(void)
    {
        VkSwapchainKHR swapchain = VK_NULL_HANDLE;

        const VkSemaphoreCreateInfo semaphoreCreateInfo =
        {
            VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,    // sType
            NULL,                                       // pNext
            0                                           // flags
        };

        VkSemaphore imageAcquiredSemaphore;
        vkCreateSemaphore(device,
                          &semaphoreCreateInfo,
                          &imageAcquiredSemaphore);

        VkSemaphore renderingCompleteSemaphore;
        vkCreateSemaphore(device,
                          &semaphoreCreateInfo,
                          &renderingCompleteSemaphore);

        while (1)
        {
            VkResult result;

            CreateSwapchain(device, surface, swapchain, &swapchain);

            uint32_t swapchainImageCount;
            vkGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, NULL);

            VkImage* pSwapchainImages =
                (VkImage*)malloc(swapchainImageCount * sizeof(VkImage));
            vkGetSwapchainImagesKHR(device, swapchain,
                                    &swapchainImageCount, pSwapchainImages);

            CreateCommandBuffers(device, pSwapchainImages);
            free(pSwapchainImages);

            while (1)
            {
                uint32_t imageIndex;

                // Get the next available swapchain image
                result = vkAcquireNextImageKHR(
                    device,
                    swapchain,
                    UINT64_MAX,
                    imageAcquiredSemaphore,
                    VK_NULL_HANDLE,
                    &imageIndex);

                if (result == VK_ERROR_OUT_OF_DATE_KHR)
                {
                    // swapchain is out of date.  Needs to be recreated for
                    // defined results.
                    break;
                }
                else if (result == VK_SUBOPTIMAL_KHR)
                {
                    // Ignore this result here.  If any expensive
                    // preprocessing work has already been done for this
                    // frame, it is likely in the application's interest to
                    // continue processing this frame with the current
                    // swapchain rather than recreate it and waste the
                    // preprocessing work.
                }
                else if (result < 0)
                {
                    // Unhandled error.  Abort.
                    return;
                }

                // Submit rendering work to the graphics queue
                const VkPipelineStageFlags waitDstStageMask =
                    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
                const VkSubmitInfo submitInfo =
                {
                    VK_STRUCTURE_TYPE_SUBMIT_INFO,      // sType
                    NULL,                               // pNext
                    1,                                  // waitSemaphoreCount
                    &imageAcquiredSemaphore,            // pWaitSemaphores
                    &waitDstStageMask,                  // pWaitDstStageMasks
                    1,                                  // commandBufferCount
                    &cmdBuffers[imageIndex],            // pCommandBuffers
                    1,                                  // signalSemaphoreCount
                    &renderingCompleteSemaphore         // pSignalSemaphores
                };
                vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);

                // Submit present operation to present queue
                const VkPresentInfoKHR presentInfo =
                {
                    VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
                    NULL,                               // pNext
                    1,                                  // waitSemaphoreCount
                    &renderingCompleteSemaphore,        // pWaitSemaphores
                    1,                                  // swapchainCount
                    &swapchain,                         // pSwapchains
                    &imageIndex,                        // pImageIndices
                    NULL                                // pResults
                };

                result = vkQueuePresentKHR(presentQueue, &presentInfo);

                if (result == VK_ERROR_OUT_OF_DATE_KHR)
                {
                    // The swapchain is out of date, and must be recreated for
                    // defined results.
                    break;
                }
                else if (result == VK_SUBOPTIMAL_KHR)
                {
                    // Something has changed about the native surface since
                    // the swapchain was created, but it is still compatible
                    // with the swapchain.  The app must choose whether it
                    // wants to create a more up to date swapchain before it
                    // begins processing the next frame.
                    if (MustRecreateSwapchain(device, swapchain, surface))
                        break;
                }
                else if (result < 0)
                {
                    // Unhandled error.  Abort.
                    return;
                }
            }
        }
    }

Example 6

Meter a CPU thread based on presentation rate. Note this will only limit the thread to the actual presentation rate when using VK_PRESENT_MODE_FIFO_KHR. When using VK_PRESENT_MODE_IMMEDIATE_KHR, presentation rate will be limited only by rendering rate, so this example will be equivalent to waiting on a command buffer fence. When using VK_PRESENT_MODE_MAILBOX_KHR, some presented images may be skipped if a newer image is available by the time the presentation target is ready to process a new frame, so this code would again be limited only by the rendering rate. Applications using mailbox mode should use some other mechanism to meter their rendering, and it is assumed applications using immediate mode have no desire to limit the rate of their rendering based on presentation rate.

    extern void CreateSemAndFences(VkDevice device, VkSemaphore sem,
                                   VkFence *fences,
                                   const int maxOutstandingPresents);
    extern void GenFrameCmdBuffer(VkCmdbuffer cmdBuffer);

    extern VkDevice device;
    extern VkQueue queue;
    extern VkCmdBuffer cmdBuffer;
    extern VkSwapchain fifoModeSwapchain;
    extern numSwapchainImages;

    // Allow a maximum of two outstanding presentation operations.
    static const int FRAME_LAG = 2

    VkPresentInfoKHR presentInfo;
    const VkSemaphoreCreateInfo semaphoreCreateInfo =
    {
        VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,    // sType
        NULL,                                       // pNext
        0                                           // flags
    };

    VkSemaphore imageAcquiredSemaphore;
    vkCreateSemaphore(device,
                      &semaphoreCreateInfo,
                      &imageAcquiredSemaphore);

    VkSemaphore renderingCompleteSemaphore;
    vkCreateSemaphore(device,
                      &semaphoreCreateInfo,
                      &renderingCompleteSemaphore);

    VkFence fences[FRAME_LAG];
    bool fencesInited[FRAME_LAG];
    int frameIdx = 0;
    int imageIdx = 0;
    int waitFrame;

    CreateFences(device, fences, FRAME_LAG);

    for (int i = 0; i < FRAME_LAG; ++i)
        fencesInited[i] = false;

    while (1) {
        if (fencesInited[frameIdx])
        {
            // Ensure no more than FRAME_LAG presentations are outstanding
            vkWaitForFences(device, 1, &fences[frameIdx], VK_TRUE, UINT64_MAX);
            vkResetFences(device, 1, &fences[frameIdx]);
        }

        vkAcquireNextImageKHR(
            device,
            fifoSwapchain,
            UINT64_MAX,
            imageAcquiredSemaphore,
            fences[frameIdx],
            &imageIdx);

        fencesInited[frameIdx] = true;

        // Generate a command buffer for the current frame.
        GenFrameCmdBuffer(cmdBuffer);

        // Submit rendering work to the graphics queue
        const VkPipelineStageFlags waitDstStageMask =
            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
        const VkSubmitInfo submitInfo =
        {
            VK_STRUCTURE_TYPE_SUBMIT_INFO,          // sType
            NULL,                                   // pNext
            1,                                      // waitSemaphoreCount
            &imageAcquiredSemaphore,                // pWaitSemaphores
            &waitDstStageMask,                      // pWaitDstStageMasks
            1,                                      // commandBufferCount
            &cmdBuffer,                             // pCommandBuffers
            1,                                      // signalSemaphoreCount
            &renderingCompleteSemaphore             // pSignalSemaphores
        };
        vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);

        // Submit present operation to present queue
        const VkPresentInfoKHR presentInfo =
        {
            VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,     // sType
            NULL,                                   // pNext
            1,                                      // waitSemaphoreCount
            &renderingCompleteSemaphore,            // pWaitSemaphores
            1,                                      // swapchainCount
            &fifoSwapchain,                         // pSwapchains
            &imageIdx,                              // pImageIndices
            NULL                                    // pResults
        };

        result = vkQueuePresentKHR(queue, &presentInfo);

        frameIdx += 1;
        frameIdx %= FRAME_LAG;
    }

Version History

  • Revision 1, 2015-05-20 (James Jones)

    • Initial draft, based on LunarG KHR spec, other KHR specs, patches attached to bugs.
  • Revision 2, 2015-05-22 (Ian Elliott)

    • Made many agreed-upon changes from 2015-05-21 KHR TSG meeting. This includes using only a queue for presentation, and having an explicit function to acquire the next image.
    • Fixed typos and other minor mistakes.
  • Revision 3, 2015-05-26 (Ian Elliott)

    • Improved the Description section.
    • Added or resolved issues that were found in improving the Description. For example, pSurfaceDescription is used consistently, instead of sometimes using pSurface.
  • Revision 4, 2015-05-27 (James Jones)

    • Fixed some grammatical errors and typos
    • Filled in the description of imageUseFlags when creating a swapchain.
    • Added a description of swapInterval.
    • Replaced the paragraph describing the order of operations on a queue for image ownership and presentation.
  • Revision 5, 2015-05-27 (James Jones)

    • Imported relevant issues from the (abandoned) vk_wsi_persistent_swapchain_images extension.
    • Added issues 6 and 7, regarding behavior of the acquire next image and present commands with respect to queues.
    • Updated spec language and examples to align with proposed resolutions to issues 6 and 7.
  • Revision 6, 2015-05-27 (James Jones)

    • Added issue 8, regarding atomic presentation of multiple swapchains
    • Updated spec language and examples to align with proposed resolution to issue 8.
  • Revision 7, 2015-05-27 (James Jones)

    • Fixed compilation errors in example code, and made related spec fixes.
  • Revision 8, 2015-05-27 (James Jones)

    • Added issue 9, and the related VK_SUBOPTIMAL_KHR result code.
    • Renamed VK_OUT_OF_DATE_KHR to VK_ERROR_OUT_OF_DATE_KHR.
  • Revision 9, 2015-05-27 (James Jones)

    • Added inline proposed resolutions (marked with [JRJ]) to some XXX questions/issues. These should be moved to the issues section in a subsequent update if the proposals are adopted.
  • Revision 10, 2015-05-28 (James Jones)

    • Converted vkAcquireNextImageKHR back to a non-queue operation that uses a VkSemaphore object for explicit synchronization.
    • Added issue 10 to determine whether vkAcquireNextImageKHR generates or returns semaphores, or whether it operates on a semaphore provided by the application.
  • Revision 11, 2015-05-28 (James Jones)

    • Marked issues 6, 7, and 8 resolved.
    • Renamed VkSurfaceCapabilityPropertiesKHR to VkSurfacePropertiesKHR to better convey the mutable nature of the info it contains.
  • Revision 12, 2015-05-28 (James Jones)

    • Added issue 11 with a proposed resolution, and the related issue 12.
    • Updated various sections of the spec to match the proposed resolution to issue 11.
  • Revision 13, 2015-06-01 (James Jones)

    • Moved some structures to VK_EXT_KHR_swap_chain to resolve the spec’s issues 1 and 2.
  • Revision 14, 2015-06-01 (James Jones)

    • Added code for example 4 demonstrating how an application might make use of the two different present and acquire next image KHR result codes.
    • Added issue 13.
  • Revision 15, 2015-06-01 (James Jones)

    • Added issues 14 - 16 and related spec language.
    • Fixed some spelling errors.
    • Added language describing the meaningful return values for vkAcquireNextImageKHR and vkQueuePresentKHR.
  • Revision 16, 2015-06-02 (James Jones)

    • Added issues 17 and 18, as well as related spec language.
    • Removed some erroneous text added by mistake in the last update.
  • Revision 17, 2015-06-15 (Ian Elliott)

    • Changed special value from "-1" to "0" so that the data types can be unsigned.
  • Revision 18, 2015-06-15 (Ian Elliott)

    • Clarified the values of VkSurfacePropertiesKHR::minImageCount and the timeout parameter of the vkAcquireNextImageKHR function.
  • Revision 19, 2015-06-17 (James Jones)

    • Misc. cleanup. Removed resolved inline issues and fixed typos.
    • Fixed clarification of VkSurfacePropertiesKHR::minImageCount made in version 18.
    • Added a brief "Image Ownership" definition to the list of terms used in the spec.
  • Revision 20, 2015-06-17 (James Jones)

    • Updated enum-extending values using new convention.
  • Revision 21, 2015-06-17 (James Jones)

    • Added language describing how to use VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR.
    • Cleaned up an XXX comment regarding the description of which queues vkQueuePresentKHR can be used on.
  • Revision 22, 2015-06-17 (James Jones)

    • Rebased on Vulkan API version 126.
  • Revision 23, 2015-06-18 (James Jones)

    • Updated language for issue 12 to read as a proposed resolution.
    • Marked issues 11, 12, 13, 16, and 17 resolved.
    • Temporarily added links to the relevant bugs under the remaining unresolved issues.
    • Added issues 19 and 20 as well as proposed resolutions.
  • Revision 24, 2015-06-19 (Ian Elliott)

    • Changed special value for VkSurfacePropertiesKHR::currentExtent back to "-1" from "0". This value will never need to be unsigned, and "0" is actually a legal value.
  • Revision 25, 2015-06-23 (Ian Elliott)

    • Examples now show use of function pointers for extension functions.
    • Eliminated extraneous whitespace.
  • Revision 26, 2015-06-25 (Ian Elliott)

    • Resolved Issues 9 & 10 per KHR TSG meeting.
  • Revision 27, 2015-06-25 (James Jones)

    • Added oldSwapchain member to VkSwapchainCreateInfoKHR.
  • Revision 28, 2015-06-25 (James Jones)

    • Added the "inherit" bits to the rotatation and mirroring flags and the associated issue 21.
  • Revision 29, 2015-06-25 (James Jones)

    • Added the "clipped" flag to VkSwapchainCreateInfoKHR, and the associated issue 22.
    • Specified that presenting an image does not modify it.
  • Revision 30, 2015-06-25 (James Jones)

    • Added language to the spec that clarifies the behavior of vkCreateSwapchainKHR() when the oldSwapchain field of VkSwapchainCreateInfoKHR is not NULL.
  • Revision 31, 2015-06-26 (Ian Elliott)

    • Example of new VkSwapchainCreateInfoKHR members, "oldSwapchain" and "clipped".
    • Example of using VkSurfacePropertiesKHR::{min|max}ImageCount to set VkSwapchainCreateInfoKHR::minImageCount.
    • Rename vkGetSurfaceInfoKHR()'s 4th param to "pDataSize", for consistency with other functions.
    • Add macro with C-string name of extension (just to header file).
  • Revision 32, 2015-06-26 (James Jones)

    • Minor adjustments to the language describing the behavior of "oldSwapchain"
    • Fixed the version date on my previous two updates.
  • Revision 33, 2015-06-26 (Jesse Hall)

    • Add usage flags to VkSwapchainCreateInfoKHR
  • Revision 34, 2015-06-26 (Ian Elliott)

    • Rename vkQueuePresentKHR()'s 2nd param to "pPresentInfo", for consistency with other functions.
  • Revision 35, 2015-06-26 (Jason Ekstrand)

    • Merged the VkRotationFlagBitsKHR and VkMirrorFlagBitsKHR enums into a single VkSurfaceTransformFlagBitsKHR enum.
  • Revision 36, 2015-06-26 (Jason Ekstrand)

    • Added a VkSurfaceTransformKHR enum that isn’t a bitmask. Each value in VkSurfaceTransformKHR corresponds directly to one of the bits in VkSurfaceTransformFlagBitsKHR so transforming from one to the other is easy. Having a separate enum means that currentTransform and preTransform are now unambiguous by definition.
  • Revision 37, 2015-06-29 (Ian Elliott)

    • Corrected one of the signatures of vkAcquireNextImageKHR, which had the last two parameters switched from what it is elsewhere in the specification and header files.
  • Revision 38, 2015-06-30 (Ian Elliott)

    • Corrected a typo in description of the vkGetSwapchainInfoKHR() function.
    • Corrected a typo in header file comment for VkPresentInfoKHR::sType.
  • Revision 39, 2015-07-07 (Daniel Rakos)

    • Added error section describing when each error is expected to be reported.
    • Replaced bool32_t with VkBool32.
  • Revision 40, 2015-07-10 (Ian Elliott)

    • Updated to work with version 138 of the "vulkan.h" header. This includes declaring the VkSwapchainKHR type using the new VK_DEFINE_NONDISP_HANDLE macro, and no longer extending VkObjectType (which was eliminated).
  • Revision 41 2015-07-09 (Mathias Heyer)

    • Added color space language.
  • Revision 42, 2015-07-10 (Daniel Rakos)

    • Updated query mechanism to reflect the convention changes done in the core spec.
    • Removed "queue" from the name of VK_STRUCTURE_TYPE_QUEUE_PRESENT_INFO_KHR to be consistent with the established naming convention.
    • Removed reference to the no longer existing VkObjectType enum.
  • Revision 43, 2015-07-17 (Daniel Rakos)

    • Added support for concurrent sharing of swapchain images across queue families.
    • Updated sample code based on recent changes
  • Revision 44, 2015-07-27 (Ian Elliott)

    • Noted that support for VK_PRESENT_MODE_FIFO_KHR is required. That is ICDs may optionally support IMMEDIATE and MAILBOX, but must support FIFO.
  • Revision 45, 2015-08-07 (Ian Elliott)

    • Corrected a typo in spec file (type and variable name had wrong case for the imageColorSpace member of the VkSwapchainCreateInfoKHR struct).
    • Corrected a typo in header file (last parameter in PFN_vkGetSurfacePropertiesKHR was missing "KHR" at the end of type: VkSurfacePropertiesKHR).
  • Revision 46, 2015-08-20 (Ian Elliott)

    • Renamed this extension and all of its enumerations, types, functions, etc. This makes it compliant with the proposed standard for Vulkan extensions.
    • Switched from "revision" to "version", including use of the VK_MAKE_VERSION macro in the header file.
    • Made improvements to several descriptions.
    • Changed the status of several issues from PROPOSED to RESOLVED, leaving no unresolved issues.
    • Resolved several TODOs, did miscellaneous cleanup, etc.
  • Revision 47, 2015-08-20 (Ian Elliott—porting a 2015-07-29 change from James Jones)

    • Moved the surface transform enums to VK_WSI_swapchain so they could be re-used by VK_WSI_display.
  • Revision 48, 2015-09-01 (James Jones)

    • Various minor cleanups.
  • Revision 49, 2015-09-01 (James Jones)

    • Restore single-field revision number.
  • Revision 50, 2015-09-01 (James Jones)

    • Update Example #4 to include code that illustrates how to use the oldSwapchain field.
  • Revision 51, 2015-09-01 (James Jones)

    • Fix example code compilation errors.
  • Revision 52, 2015-09-08 (Matthaeus G. Chajdas)

    • Corrected a typo.
  • Revision 53, 2015-09-10 (Alon Or-bach)

    • Removed underscore from SWAP_CHAIN left in VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR.
  • Revision 54, 2015-09-11 (Jesse Hall)

    • Described the execution and memory coherence requirements for image transitions to and from VK_IMAGE_LAYOUT_PRESENT_SOURCE_KHR.
  • Revision 55, 2015-09-11 (Ray Smith)

    • Added errors for destroying and binding memory to presentable images
  • Revision 56, 2015-09-18 (James Jones)

    • Added fence argument to vkAcquireNextImageKHR
    • Added example of how to meter a CPU thread based on presentation rate.
  • Revision 57, 2015-09-26 (Jesse Hall)

    • Replace VkSurfaceDescriptionKHR with VkSurfaceKHR.
    • Added issue 25 with agreed resolution.
  • Revision 58, 2015-09-28 (Jesse Hall)

    • Renamed from VK_EXT_KHR_device_swapchain to VK_EXT_KHR_swapchain.
  • Revision 59, 2015-09-29 (Ian Elliott)

    • Changed vkDestroySwapchainKHR() to return void.
  • Revision 60, 2015-10-01 (Jeff Vigil)

    • Added error result VK_ERROR_SURFACE_LOST_KHR.
  • Revision 61, 2015-10-05 (Jason Ekstrand)

    • Added the VkCompositeAlpha enum and corresponding structure fields.
  • Revision 62, 2015-10-12 (Daniel Rakos)

    • Added VK_PRESENT_MODE_FIFO_RELAXED_KHR.
  • Revision 63, 2015-10-15 (Daniel Rakos)

    • Moved surface capability queries to VK_EXT_KHR_surface.
  • Revision 64, 2015-10-26 (Ian Elliott)

    • Renamed from VK_EXT_KHR_swapchain to VK_KHR_swapchain.
  • Revision 65, 2015-10-28 (Ian Elliott)

    • Added optional pResult member to VkPresentInfoKHR, so that per-swapchain results can be obtained from vkQueuePresentKHR().
  • Revision 66, 2015-11-03 (Daniel Rakos)

    • Added allocation callbacks to create and destroy functions.
    • Updated resource transition language.
    • Updated sample code.
  • Revision 67, 2015-11-10 (Jesse Hall)

    • Add reserved flags bitmask to VkSwapchainCreateInfoKHR.
    • Modify naming and member ordering to match API style conventions, and so the VkSwapchainCreateInfoKHR image property members mirror corresponding VkImageCreateInfo members but with an image prefix.
    • Make VkPresentInfoKHR::pResults non-const; it’s an output array parameter.
    • Make pPresentInfo parameter to vkQueuePresentKHR const.
  • Revision 68, 2016-04-05 (Ian Elliott)

    • Moved the "validity" include for vkAcquireNextImage to be in its proper place, after the prototype and list of parameters.
    • Clarified language about presentable images, including how they are acquired, when applications can and can’t use them, etc. As part of this, removed language about "ownership" of presentable images, and replaced it with more-consistent language about presentable images being "acquired" by the application.
  • 2016-08-23 (Ian Elliott)

    • Update the example code, to use the final API command names, to not have so many characters per line, and to split out a new example to show how to obtain function pointers. This code is more similar to the LunarG "cube" demo program.
  • 2016-08-25 (Ian Elliott)

    • A note was added at the beginning of the example code, stating that it will be removed from future versions of the appendix.

C.2.4. VK_KHR_display

Name String
VK_KHR_display
Extension Type
Instance extension
Registered Extension Number
3
Status
Draft.
Last Modified Date
11/10/2015
Revision
21
IP Status
No known IP claims.
Dependencies
  • This extension is written against revision 1.0 of the Vulkan API.
  • This extension requires VK_KHR_surface.
Contributors
  • James Jones, NVIDIA
  • Norbert Nopper, Freescale
  • Jeff Vigil, Qualcomm
  • Daniel Rakos, AMD
Contacts
  • James Jones (jajones at nvidia.com)
  • Norbert Nopper (Norbert.Nopper at freescale.com)

This extension provides the API to enumerate displays and available modes on a given device.

New Object Types

  • VkDisplayKHR
  • VkDisplayModeKHR

New Enum Constants

  • Extending VkStructureType:

    • VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR
    • VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR

New Enums

  • VkDisplayPlaneAlphaFlagBitsKHR

Issues

1) Which properties of a mode should be fixed in the mode info Vs. settable in some other function when setting the mode? E.g., do we need to double the size of the mode pool to include both stereo and non-stereo modes? YUV and RGB scanout even if they both take RGB input images? BGR Vs. RGB input? etc.

PROPOSED RESOLUTION: Many modern displays support at most
a handful of resolutions and timings natively.  Other "modes" are
expected to be supported using scaling hardware on the display engine
or GPU.  Other properties, such as rotation and mirroring shouldn't
require duplicating hardware modes just to express all combinations.
Further, these properties may be implemented on a per-display or
per-overlay granularity.
To avoid the exponential growth of modes as mutable properties are
added, as was the case with EGLConfig/WGL pixel formats/GLXFBConfig,
this specification should separate out hardware properties and
configurable state into separate objects.  Modes and overlay planes
will express capabilities of the hardware, while a separate structure
will allow applications to configure scaling, rotation, mirroring,
color keys, LUT values, alpha masks, etc. for a given swapchain
independent of the mode in use.  Constraints on these settings will
be established by properties of the immutable objects.
Note the resolution of this issue may affect issue (5) as well.

2) What properties of a display itself are useful?

PROPOSED RESOLUTION: This issue is too broad.  It was meant to
prompt general discussion, but resolving this issue amounts to
completing this specification.  All interesting properties should
be included.  The issue will remain as a placeholder since
removing it would make it hard to parse existing discussion notes
that refer to issues by number.

3) How are multiple overlay planes within a display or mode enumerated?

PROPOSED RESOLUTION: They are referred to by an index.  Each display
will report the number of overlay planes it contains.

4) Should swapchains be created relative to a mode or a display?

PROPOSED RESOLUTION: When using this extension, swapchains are
created relative to a mode and a plane.  The mode implies the display
object the swapchain will present to.  If the specified mode is not
the display's current mode, the new mode will be applied when the
first image is presented to the swapchain, and the default operating
system mode, if any, will be restored when the swapchain is destroyed.

5) Should users query generic ranges from displays and construct their own modes explicitly using those constraints rather than querying a fixed set of modes (Most monitors only have one real "mode" these days, even though many support relatively arbitrary scaling, either on the monitor side or in the GPU display engine, making "modes" something of a relic/compatibility construct).

PROPOSED RESOLUTION: Expose both.  Display info structures will
expose a set of predefined modes, as well as any attributes
necessary to construct a customized mode.

6) Is it fine if we return the display and display mode handles in the structure used to query their properties?

PROPOSED RESOLUTION: Yes.

7) Is there a possibility that not all displays of a device work with all of the present queues of a device? If yes, how do we determine which displays work with which present queues?

PROPOSED RESOLUTION: No known hardware has such limitations, but
determining such limitations is supported automatically using the
existing VK_EXT_KHR_surface and VK_EXT_KHR_swapchain query mechanisms.

8) Should all presentation need to be done relative to an overlay plane, or can a display mode + display be used alone to target an output?

PROPOSED RESOLUTION: Require specifying a plane explicitly.

9) Should displays have an associated window system display, such as an HDC or Display*?

PROPOSED RESOLUTION: No.  Displays are independent of any windowing
system in use on the system.  Further, neither HDC nor Display* refer
to a physical display object.

10) Are displays queried from a physical GPU or from a device instance?

PROPOSED RESOLUTION: Developers prefer to query modes directly from
the physical GPU so they can use display information as an input
to their device selection algorithms prior to device creation.  This
avoids the need to create dummy device instances to enumerate
displays.
This preference must be weighed against the extra initialization
that must be done by driver vendors prior to device instance
creation to support this usage.

11) Should displays and/or modes be dispatchable objects? If functions are to take displays, overlays, or modes as their first parameter, they must be dispatchable objects as defined in Khronos bug 13529. If they aren’t added to the list of dispatchable objects, functions operating on them must take some higher-level object as their first parameter. There is no performance case against making them dispatchable objects, but they would be the first extension objects to be dispatchable.

PROPOSED RESOLUTION: Do not make displays or modes dispatchable.
They will dispatch based on their associated physical device.

12) Should hardware cursor capabilities be exposed?

PROPOSED RESOLUTION: Defer.  This could be a separate extension on
top of the base WSI specs.
if they are one physical display device to an end user, but may
internally be implemented as two side-by-side displays using the
same display engine (and sometimes cabling) resources as two
physically separate display devices.
PROPOSED RESOLUTION: Tiled displays will appear as a single display
object in this API.

14) Should the raw EDID data be included in the display information?

PROPOSED RESOLUTION: None.  Unclear whether this is a good idea.
Provides a path for forward-compatibility as new EDID extensions
are introduced, but may be complicated by the outcome of issue 13.

15) Should min and max scaling factor capabilities of overlays be exposed?

PROPOSED RESOLUTION: Yes.  This is exposed indirectly by allowing
applications to query the min/max position and extent of the source
and destination regions from which image contents are fetched by
the display engine when using a particular mode and overlay pair.

16) Should devices be able to expose planes that can be moved between displays? If so, how?

PROPOSED RESOLUTION: None.

17) Should there be a way to destroy display modes? If so, does it support destroying "built in" modes?

PROPOSED RESOLUTION: None.

18) What should the lifetime of display and built-in display mode objects be?

PROPOSED RESOLUTION: The lifetime of the instance.  These objects can
not be destroyed.  A future extension may be added to expose a way to
destroy these objects and/or support display hotplug.

19) Should persistent mode for smart panels be enabled/disabled at swap chain creation time, or on a per-present basis.

PROPOSED RESOLUTION: On a per-present basis.

Examples

Example 1

Enumerating displays, display modes, and planes, and creating a VkSurfaceKHR

    extern VkBool32 ModeMatchesMyCriteria(const VkDisplayModePropertiesKHR *m);
    extern VkInstance instance;
    extern VkPhysicalDevice physDevice;
    extern VkSurfaceKHR surface;

    uint32_t displayCount, planeCount, i, j, k;
    VkDisplayPropertiesKHR* pDisplayProps;
    VkDisplayPlanePropertiesKHR* pPlaneProps;
    VkDisplayModeKHR myMode = VK_NULL_HANDLE;
    VkDisplayKHR myDisplay = VK_NULL_HANDLE;
    uint32_t bestPlane = UINT32_MAX;
    VkDisplayPlaneAlphaFlagBitsKHR alphaMode = 0;
    PFN_vkGetPhysicalDeviceDisplayPropertiesKHR pfnGetPhysicalDeviceDisplayPropertiesKHR;
    PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR pfnGetPhysicalDeviceDisplayPlanePropertiesKHR;
    PFN_vkGetDisplayModePropertiesKHR pfnGetDisplayModePropertiesKHR;
    PFN_vkGetDisplayPlaneCapabilitiesKHR pfnGetDisplayPlaneCapabilitiesKHR;
    PFN_vkGetDisplayPlaneSupportedDisplaysKHR pfnGetDisplayPlaneSupportedDisplaysKHR;
    PFN_vkCreateDisplayPlaneSurfaceKHR pfnCreateDisplayPlaneSurfaceKHR;

    pfnGetPhysicalDeviceDisplayPropertiesKHR =
        (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)
        vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR");
    pfnGetPhysicalDeviceDisplayPlanePropertiesKHR =
        (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)
        vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
    pfnGetDisplayModePropertiesKHR =
        (PFN_vkGetDisplayModePropertiesKHR)
        vkGetInstanceProcAddr(instance, "vkGetDisplayModePropertiesKHR");
    pfnGetDisplayPlaneCapabilitiesKHR =
        (PFN_vkGetDisplayPlaneCapabilitiesKHR)
        vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneCapabilitiesKHR");
    pfnGetDisplayPlaneSupportedDisplaysKHR =
        (PFN_vkGetDisplayPlaneSupportedDisplaysKHR)
        vkGetInstanceProcAddr(instance, "vkGetDisplayPlaneSupportedDisplaysKHR");
    pfnCreateDisplayPlaneSurfaceKHR =
        (PFN_vkCreateDisplayPlaneSurfaceKHR)
        vkGetInstanceProcAddr(instance, "vkCreateDisplayPlaneSurfaceKHR");

    // Get a list of displays on a physical device
    displayCount = 0;
    pfnGetPhysicalDeviceDisplayPropertiesKHR(physDevice, &displayCount, NULL);

    pDisplayProps = (VkDisplayPropertiesKHR*)malloc(sizeof(VkDisplayPropertiesKHR) * displayCount);
    pfnGetPhysicalDeviceDisplayPropertiesKHR(physDevice, &displayCount, pDisplayProps);

    // Get a list of display planes on a physical device
    planeCount = 0;
    pfnGetPhysicalDeviceDisplayPlanePropertiesKHR(physDevice, &planeCount, NULL);
    pPlaneProps = (VkDisplayPlanePropertiesKHR*)malloc(sizeof(VkDisplayPlanePropertiesKHR) * planeCount);
    pfnGetPhysicalDeviceDisplayPlanePropertiesKHR(physDevice, &planeCount, pPlaneProps);

    // Get the list of pModes each display supports
    for (i = 0; i < displayCount; ++i)
    {
        VkDisplayKHR display = pDisplayProps[i].display;
        VkDisplayModePropertiesKHR* pModes;
        uint32_t modeCount;

        vkGetDisplayModePropertiesKHR(physDevice, display, &modeCount, NULL);

        pModes = (VkDisplayModePropertiesKHR*)malloc(sizeof(VkDisplayModePropertiesKHR) * modeCount);
        vkGetDisplayModePropertiesKHR(physDevice, display, &modeCount, pModes);

        myMode = VK_NULL_HANDLE;
        for (j = 0; j < modeCount; ++j)
        {
            const VkDisplayModePropertiesKHR* mode = &pModes[i];

            if (ModeMatchesMyCriteria(mode))
            {
                myMode = mode->displayMode;
                break;
            }
        }

        free(pModes);

        // If there are no usable pModes found then check the next display.
        if (myMode == VK_NULL_HANDLE)
            continue;

        // Find a plane that matches these criteria, in order of preference:
        // -Is compatible with the chosen display + mode.
        // -Isn't currently bound to another display.
        // -Supports per-pixel alpha, if possible.
        for (j = 0; j < planeCount; ++j)
        {
            uint32_t supportedCount = 0;
            VkDisplayKHR* pSupportedDisplays;
            VkDisplayPlaneCapabilitiesKHR planeCaps;
            // See if the plane is compatible with the current display.
            pfnGetDisplayPlaneSupportedDisplaysKHR(physDevice, j, &supportedCount, NULL);

            // Plane doesn't support any displays.  This might happen on a card
            // that has a fixed mapping between planes and connectors when no
            // displays are currently attached to this plane's connector, for
            // example.
            if (supportedCount == 0)
                continue;

            pSupportedDisplays = (VkDisplayKHR*)malloc(sizeof(VkDisplayKHR) * supportedCount);
            pfnGetDisplayPlaneSupportedDisplaysKHR(physDevice, j, &supportedCount, pSupportedDisplays);

            for (k = 0; k < supportedCount; ++k)
                if (pSupportedDisplays[k] == display) {
                    // If no supported plane has yet been found, this is
                    // currently the best available plane.
                    if (bestPlane == UINT32_MAX)
                        bestPlane = j;
                    break;
                }

            // If the plane can't be used with the chosen display, keep looking.
            // Each display must have at least one compatible plane.
            if (k == supportedCount)
                continue;

            // If the plane passed the above test and is currently bound to the
            // desired display, or is not in use, it is the best plane found so
            // far.
            if ((pPlaneProps[j].currentDisplay == VK_NULL_HANDLE) &&
                (pPlaneProps[j].currentDisplay == display))
                bestPlane = j;
            else
                continue;

            pfnGetDisplayPlaneCapabilitiesKHR(physDevice, myMode, j, &planeCaps);

            // Prefer a plane that supports per-pixel alpha.
            if (planeCaps.supportedAlpha & VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR)
            {
                // This is the perfect plane for the given criteria.  Use it.
                bestPlane = j;
                alphaMode = VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR;
                break;
            }
        }
    }

    free(pDisplayProps);

    if (myDisplay == VK_NULL_HANDLE || myMode == VK_NULL_HANDLE) {
        // No suitable display + mode could be found.  Abort.
        abort();
    } else {
        // Success.  Create a VkSurfaceKHR object for this plane.
        const VkDisplaySurfaceCreateInfoKHR createInfo =
        {
            VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR,  // sType
            NULL,                                               // pNext
            0,                                                  // flags
            myMode,                                             // displayMode
            bestPlane,                                          // planeIndex
            pPlaneProps[bestPlane].currentStackIndex,           // planeStackIndex
            VK_SURFACE_TRANSFORM_IDENTITY_KHR,                  // transform
            1.0f,                                               // globalAlpha
            alphaMode,                                          // alphaMode
            ...
        }

        pfnCreateDisplayPlaneSurfaceKHR(instance, &createInfo, NULL, &surface);
    }

Version History

  • Revision 1, 2015-02-24 (James Jones)

    • Initial draft
  • Revision 2, 2015-03-12 (Norbert Nopper)

    • Added overlay enumeration for a display.
  • Revision 3, 2015-03-17 (Norbert Nopper)

    • Fixed typos and namings as discussed in Bugzilla.
    • Reordered and grouped functions.
    • Added functions to query count of display, mode and overlay.
    • Added native display handle, which is maybe needed on some platforms to create a native Window.
  • Revision 4, 2015-03-18 (Norbert Nopper)

    • Removed primary and virtualPostion members (see comment of James Jones in Bugzilla).
    • Added native overlay handle to info structure.
    • Replaced , with ; in struct.
  • Revision 6, 2015-03-18 (Daniel Rakos)

    • Added WSI extension suffix to all items.
    • Made the whole API more "Vulkanish".
    • Replaced all functions with a single vkGetDisplayInfoKHR function to better match the rest of the API.
    • Made the display, display mode, and overlay objects be first class objects, not subclasses of VkBaseObject as they don’t support the common functions anyways.
    • Renamed *Info structures to *Properties.
    • Removed overlayIndex field from VkOverlayProperties as there is an implicit index already as a result of moving to a "Vulkanish" API.
    • Displays aren’t get through device, but through physical GPU to match the rest of the Vulkan API. Also this is something ISVs explicitly requested.
    • Added issue (6) and (7).
  • Revision 7, 2015-03-25 (James Jones)

    • Added an issues section
    • Added rotation and mirroring flags
  • Revision 8, 2015-03-25 (James Jones)

    • Combined the duplicate issues sections introduced in last change.
    • Added proposed resolutions to several issues.
  • Revision 9, 2015-04-01 (Daniel Rakos)

    • Rebased extension against Vulkan 0.82.0
  • Revision 10, 2015-04-01 (James Jones)

    • Added issues (10) and (11).
    • Added more straw-man issue resolutions, and cleaned up the proposed resolution for issue (4).
    • Updated the rotation and mirroring enums to have proper bitmask semantics.
  • Revision 11, 2015-04-15 (James Jones)

    • Added proposed resolution for issues (1) and (2).
    • Added issues (12), (13), (14), and (15)
    • Removed pNativeHandle field from overlay structure.
    • Fixed small compilation errors in example code.
  • Revision 12, 2015-07-29 (James Jones)

    • Rewrote the guts of the extension against the latest WSI swapchain specifications and the latest Vulkan API.
    • Address overlay planes by their index rather than an object handle and refer to them as "planes" rather than "overlays" to make it slightly clearer that even a display with no "overlays" still has at least one base "plane" that images can be displayed on.
    • Updated most of the issues.
    • Added an "extension type" section to the specification header.
    • Re-used the VK_EXT_KHR_surface surface transform enumerations rather than redefining them here.
    • Updated the example code to use the new semantics.
  • Revision 13, 2015-08-21 (Ian Elliott)

    • Renamed this extension and all of its enumerations, types, functions, etc. This makes it compliant with the proposed standard for Vulkan extensions.
    • Switched from "revision" to "version", including use of the VK_MAKE_VERSION macro in the header file.
  • Revision 14, 2015-09-01 (James Jones)

    • Restore single-field revision number.
  • Revision 15, 2015-09-08 (James Jones)

    • Added alpha flags enum.
    • Added premultiplied alpha support.
  • Revision 16, 2015-09-08 (James Jones)

    • Added description section to the spec.
    • Added issues 16 - 18.
  • Revision 17, 2015-10-02 (James Jones)

    • Planes are now a property of the entire device rather than individual displays. This allows planes to be moved between multiple displays on devices that support it.
    • Added a function to create a VkSurfaceKHR object describing a display plane and mode to align with the new per-platform surface creation conventions.
    • Removed detailed mode timing data. It was agreed that the mode extents and refresh rate are sufficient for current use cases. Other information could be added back2 in as an extension if it is needed in the future.
    • Added support for smart/persistent/buffered display devices.
  • Revision 18, 2015-10-26 (Ian Elliott)

    • Renamed from VK_EXT_KHR_display to VK_KHR_display.
  • Revision 19, 2015-11-02 (James Jones)

    • Updated example code to match revision 17 changes.
  • Revision 20, 2015-11-03 (Daniel Rakos)

    • Added allocation callbacks to creation functions.
  • Revision 21, 2015-11-10 (Jesse Hall)

    • Added VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, and use VkDisplayPlaneAlphaFlagBitsKHR for VkDisplayPlanePropertiesKHR::alphaMode instead of VkDisplayPlaneAlphaFlagsKHR, since it only represents one mode.
    • Added reserved flags bitmask to VkDisplayPlanePropertiesKHR.
    • Use VkSurfaceTransformFlagBitsKHR instead of obsolete VkSurfaceTransformKHR.
    • Renamed vkGetDisplayPlaneSupportedDisplaysKHR parameters for clarity.
  • Revision 22, 2015-12-18 (James Jones)

    • Added missing "planeIndex" parameter to vkGetDisplayPlaneSupportedDisplaysKHR()

C.2.5. VK_KHR_display_swapchain

Name String
VK_KHR_display_swapchain
Extension Type
Device extension
Registered Extension Number
4
Status
Draft.
Last Modified Date
11/10/2015
Revision
9
IP Status
No known IP claims.
Dependencies
  • This extension is written against revision 1.0 of the Vulkan API.
  • This extension requires VK_KHR_swapchain and VK_KHR_display
Contributors
  • James Jones, NVIDIA
  • Jeff Vigil, Qualcomm
  • Jesse Hall, Google
Contacts
  • James Jones (jajones at nvidia.com)

This extension provides an API to create a swapchain directly on a device’s display without any underlying window system.

New Object Types

None

New Enum Constants

  • Extending VkStructureType:

    • VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR
  • Extending VkResult:

    • VK_ERROR_INCOMPATIBLE_DISPLAY_KHR

New Enums

None

New Structures

Issues

1) Should swapchains sharing images each hold a reference to the images, or should it be up to the application to destroy the swapchains and images in an order that avoids the need for reference counting?

PROPOSED RESOLUTION: Take a reference.  The lifetime of presentable
images is already complex enough.

2) Should the srcRect/dstRect parameters be specified as part of the present command, or at swapchain creation time?

PROPOSED RESOLUTION: As part of the presentation command.  This allows
moving and scaling the image on the screen without the need to
respecify the mode or create a new swapchain presentable images.

3) Should srcRect/dstRect be specified as rects, or separate offset/extent values?

PROPOSED RESOLUTION: As rects.  Specifying them separately might make
it easier for hardware to expose support for one but not the other, but
in such cases applications must just take care to obey the reported
capabilities and not use non-zero offsets or extents that require
scaling, as appropriate.

4) How can applications create multiple swapchains that use the same images?

RESOLUTION: By calling vkCreateSharedSwapchainsKHR().
An earlier resolution used vkCreateSwapchainKHR(), chaining multiple
VkSwapchainCreateInfoKHR structures through pNext.  In order to allow each
swapchain to also allow other extension structs, a level of indirection
was used: VkSwapchainCreateInfoKHR::pNext pointed to a different structure,
which had both an sType/pNext for additional extensions, and also had a
pointer to the next VkSwapchainCreateInfoKHR structure.  The number of
swapchains to be created could only be found by walking this linked list
of alternating structures, and the pSwapchains out parameter was
reinterpreted to be an array of VkSwapchainKHR handles.
Another option considered was a method to specify a "shared"
swapchain when creating a new swapchain, such that groups of swapchains
using the same images could be built up one at a time.  This was deemed
unusable because drivers need to know all of the displays an image
will be used on when determining which internal formats and layouts to
use for that image.

Examples

Example 1

Create a swapchain on a display mode and plane

    // See VK_KHR_display for an example of how to pick a display,
    // display mode, plane, and how to create a VkSurfaceKHR for
    // that plane.
    extern VkPhysicalDevice physDevice;
    extern VkDisplayModePropertiesKHR myModeProps;
    extern VkSurfaceKHR mySurface;
    extern VkDevice device;

    uint32_t queueCount, i;
    uint32_t presentQueueFamilyIndex = UINT32_MAX;
    VkBool32 supportsPresent;

    // Find a queue family that supports presenting to this surface
    uint32_t familyCount;
    vkGetPhysicalDeviceQueueFamilyProperties(physDevice, &familyCount, NULL);

    for (i = 0; i < familyCount; ++i)
    {
        vkGetPhysicalDeviceSurfaceSupportKHR(physDevice, i, mySurface, &supportsPresent);

        if (supportsPresent) {
            // Found a queue family that supports present.  See
            // VK_KHR_surface for an example of how to find a queue that
            // supports both presentation and graphics
            presentQueueFamilyIndex = i;
            break;
        }
    }

    // Figure out which formats and present modes this surface supports.
    uint32_t formatCount;
    vkGetPhysicalDeviceSurfaceFormatsKHR(physDevice, mySurface, &formatCount, NULL);

    VkSurfaceFormatKHR* formats = (VkSurfaceFormatKHR*)malloc(sizeof(VkSurfaceFormatKHR) * formatCount);
    vkGetPhysicalDeviceSurfaceFormatsKHR(physDevice, mySurface, &formatCount, formats);

    const VkSwapchainCreateInfoKHR createInfo =
    {
        VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,    // sType
        NULL,                                           // pNext
        0,                                              // flags
        mySurface,                                      // surface
        3,                                              // minImageCount
        formats[0].format,                              // imageFormat
        formats[0].colorSpace,                          // imageColorSpace
        myModeProps.parameters.visibleRegion,           // imageExtent
        1,                                              // imageArrayLayers
        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,            // imageUsage
        VK_SHARING_MODE_EXCLUSIVE,                      // imageSharingMode
        0,                                              // queueFamilyIndexCount
        NULL,                                           // pQueueFamilyIndices
        VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,          // preTransform
        VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,              // compositeAlpha
        VK_PRESENT_MODE_FIFO_KHR,                       // presentMode
        VK_TRUE,                                        // clipped
        VK_NULL_HANDLE                                  // oldSwapchain
    };

    VkSwapchainKHR swapchain;
    // This is equivalent to vkCreateSwapchainKHR.
    vkCreateSharedSwapchainsKHR(device, 1, &createInfo, NULL, &swapchain);

Version History

  • Revision 1, 2015-07-29 (James Jones)

    • Initial draft
  • Revision 2, 2015-08-21 (Ian Elliott)

    • Renamed this extension and all of its enumerations, types, functions, etc. This makes it compliant with the proposed standard for Vulkan extensions.
    • Switched from "revision" to "version", including use of the VK_MAKE_VERSION macro in the header file.
  • Revision 3, 2015-09-01 (James Jones)

    • Restore single-field revision number.
  • Revision 4, 2015-09-08 (James Jones)

    • Allow creating multiple swap chains that share the same images using a single call to vkCreateSwapChainKHR().
  • Revision 5, 2015-09-10 (Alon Or-bach)

    • Removed underscores from SWAP_CHAIN in two enums.
  • Revision 6, 2015-10-02 (James Jones)

    • Added support for smart panels/buffered displays.
  • Revision 7, 2015-10-26 (Ian Elliott)

    • Renamed from VK_EXT_KHR_display_swapchain to VK_KHR_display_swapchain.
  • Revision 8, 2015-11-03 (Daniel Rakos)

    • Updated sample code based on the changes to VK_KHR_swapchain.
  • Revision 9, 2015-11-10 (Jesse Hall)

    • Replaced VkDisplaySwapchainCreateInfoKHR with vkCreateSharedSwapchainsKHR, changing resolution of issue #4.

C.2.6. VK_KHR_android_surface

Name String
VK_KHR_android_surface
Extension Type
Instance extension
Registered Extension Number
9
Last Modified Date
01/14/2016
Revision
6
IP Status
No known IP claims.
Dependencies
  • This extension is written against revision 1.0 of the Vulkan API.
  • This extension requires VK_KHR_surface.
Contributors
  • Patrick Doane, Blizzard
  • Jason Ekstrand, Intel
  • Ian Elliott, LunarG
  • Courtney Goeltzenleuchter, LunarG
  • Jesse Hall, Google
  • James Jones, NVIDIA
  • Antoine Labour, Google
  • Jon Leech, Khronos
  • David Mao, AMD
  • Norbert Nopper, Freescale
  • Alon Or-bach, Samsung
  • Daniel Rakos, AMD
  • Graham Sellers, AMD
  • Ray Smith, ARM
  • Jeff Vigil, Qualcomm
  • Chia-I Wu, LunarG
Contacts
  • Jesse Hall, Google

The VK_KHR_android_surface extension is an instance extension. It provides a mechanism to create a VkSurfaceKHR object (defined by the VK_KHR_surface extension) that refers to an ANativeWindow, Android’s native surface type. The ANativeWindow represents the producer endpoint of any buffer queue, regardless of consumer endpoint. Common consumer endpoints for ANativeWindows are the system window compositor, video encoders, and application-specific compositors importing the images through a SurfaceTexture.

New Object Types

None

New Enum Constants

  • Extending VkStructureType:

    • VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR

New Enums

None

Issues

1) Does Android need a way to query for compatibility between a particular physical device (and queue family?) and a specific Android display?

RESOLVED: No.  Currently on Android, any GPU is expected to be able to
present to the system compositor, and all queue families must support the
necessary image layout transitions and synchronization operations.

Version History

  • Revision 1, 2015-09-23 (Jesse Hall)

    • Initial draft.
  • Revision 2, 2015-10-26 (Ian Elliott)

    • Renamed from VK_EXT_KHR_android_surface to VK_KHR_android_surface.
  • Revision 3, 2015-11-03 (Daniel Rakos)

    • Added allocation callbacks to surface creation function.
  • Revision 4, 2015-11-10 (Jesse Hall)

    • Removed VK_ERROR_INVALID_ANDROID_WINDOW_KHR.
  • Revision 5, 2015-11-28 (Daniel Rakos)

    • Updated the surface create function to take a pCreateInfo structure.
  • Revision 6, 2016-01-14 (James Jones)

    • Moved VK_ERROR_NATIVE_WINDOW_IN_USE_KHR from the VK_KHR_android_surface to the VK_KHR_surface extension.

C.2.7. VK_KHR_mir_surface

Name String
VK_KHR_mir_surface
Extension Type
Instance extension
Registered Extension Number
8
Last Modified Date
10/28/2015
Revision
4
IP Status
No known IP claims.
Dependencies
  • This extension is written against revision 1.0 of the Vulkan API.
  • This extension requires VK_KHR_surface.
Contributors
  • Patrick Doane, Blizzard
  • Jason Ekstrand, Intel
  • Ian Elliott, LunarG
  • Courtney Goeltzenleuchter, LunarG
  • Jesse Hall, Google
  • James Jones, NVIDIA
  • Antoine Labour, Google
  • Jon Leech, Khronos
  • David Mao, AMD
  • Norbert Nopper, Freescale
  • Alon Or-bach, Samsung
  • Daniel Rakos, AMD
  • Graham Sellers, AMD
  • Ray Smith, ARM
  • Jeff Vigil, Qualcomm
  • Chia-I Wu, LunarG
Contacts
  • Jesse Hall, Google
  • Ian Elliott, LunarG

The VK_KHR_mir_surface extension is an instance extension. It provides a mechanism to create a VkSurfaceKHR object (defined by the VK_KHR_surface extension) that refers to a Mir surface, as well as a query to determine support for rendering to the windows desktop.

New Object Types

None

New Enum Constants

  • Extending VkStructureType:

    • VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR

New Enums

None

Issues

1) Does Mir need a way to query for compatibility between a particular physical device (and queue family?) and a specific Mir connection, screen, window, etc.?

RESOLVED: Yes, vkGetPhysicalDeviceMirPresentationSupportKHR() was added to
address this.

Version History

  • Revision 1, 2015-09-23 (Jesse Hall)

    • Initial draft, based on the previous contents of VK_EXT_KHR_swapchain (later renamed VK_EXT_KHR_surface).
  • Revision 2, 2015-10-02 (James Jones)

    • Added vkGetPhysicalDeviceMirPresentationSupportKHR() to resolve issue #1.
  • Revision 3, 2015-10-26 (Ian Elliott)

    • Renamed from VK_EXT_KHR_mir_surface to VK_KHR_mir_surface.
  • Revision 4, 2015-11-28 (Daniel Rakos)

    • Updated the surface create function to take a pCreateInfo structure.

C.2.8. VK_KHR_wayland_surface

Name String
VK_KHR_wayland_surface
Extension Type
Instance extension
Registered Extension Number
7
Last Modified Date
11/28/2015
Revision
5
IP Status
No known IP claims.
Dependencies
  • This extension is written against revision 1.0 of the Vulkan API.
  • This extension requires VK_KHR_surface.
Contributors
  • Patrick Doane, Blizzard
  • Jason Ekstrand, Intel
  • Ian Elliott, LunarG
  • Courtney Goeltzenleuchter, LunarG
  • Jesse Hall, Google
  • James Jones, NVIDIA
  • Antoine Labour, Google
  • Jon Leech, Khronos
  • David Mao, AMD
  • Norbert Nopper, Freescale
  • Alon Or-bach, Samsung
  • Daniel Rakos, AMD
  • Graham Sellers, AMD
  • Ray Smith, ARM
  • Jeff Vigil, Qualcomm
  • Chia-I Wu, LunarG
Contacts
  • Jesse Hall, Google
  • Ian Elliott, LunarG

The VK_KHR_wayland_surface extension is an instance extension. It provides a mechanism to create a VkSurfaceKHR object (defined by the VK_KHR_surface extension) that refers to a Wayland wl_surface, as well as a query to determine support for rendering to the windows desktop.

New Object Types

None

New Enum Constants

  • Extending VkStructureType:

    • VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR

New Enums

None

Issues

1) Does Wayland need a way to query for compatibility between a particular physical device and a specific Wayland display? This would be a more general query than vkGetPhysicalDeviceSurfaceSupportKHR: if the Wayland- specific query returned true for a (VkPhysicalDevice, struct wl_display*) pair, then the physical device could be assumed to support presentation to any VkSurface for surfaces on the display.

RESOLVED: Yes.  vkGetPhysicalDeviceWaylandPresentationSupportKHR() was added
to address this issue.

Version History

  • Revision 1, 2015-09-23 (Jesse Hall)

    • Initial draft, based on the previous contents of VK_EXT_KHR_swapchain (later renamed VK_EXT_KHR_surface).
  • Revision 2, 2015-10-02 (James Jones)

    • Added vkGetPhysicalDeviceWaylandPresentationSupportKHR() to resolve issue #1.
    • Adjusted wording of issue #1 to match the agreed-upon solution.
    • Renamed "window" parameters to "surface" to match Wayland conventions.
  • Revision 3, 2015-10-26 (Ian Elliott)

    • Renamed from VK_EXT_KHR_wayland_surface to VK_KHR_wayland_surface.
  • Revision 4, 2015-11-03 (Daniel Rakos)

    • Added allocation callbacks to vkCreateWaylandSurfaceKHR.
  • Revision 5, 2015-11-28 (Daniel Rakos)

    • Updated the surface create function to take a pCreateInfo structure.

C.2.9. VK_KHR_win32_surface

Name String
VK_KHR_win32_surface
Extension Type
Instance extension
Registered Extension Number
10
Last Modified Date
11/28/2015
Revision
5
IP Status
No known IP claims.
Dependencies
  • This extension is written against revision 1.0 of the Vulkan API.
  • This extension requires VK_KHR_surface.
Contributors
  • Patrick Doane, Blizzard
  • Jason Ekstrand, Intel
  • Ian Elliott, LunarG
  • Courtney Goeltzenleuchter, LunarG
  • Jesse Hall, Google
  • James Jones, NVIDIA
  • Antoine Labour, Google
  • Jon Leech, Khronos
  • David Mao, AMD
  • Norbert Nopper, Freescale
  • Alon Or-bach, Samsung
  • Daniel Rakos, AMD
  • Graham Sellers, AMD
  • Ray Smith, ARM
  • Jeff Vigil, Qualcomm
  • Chia-I Wu, LunarG
Contacts
  • Jesse Hall, Google
  • Ian Elliott, LunarG

The VK_KHR_win32_surface extension is an instance extension. It provides a mechanism to create a VkSurfaceKHR object (defined by the VK_KHR_surface extension) that refers to a Win32 HWND, as well as a query to determine support for rendering to the windows desktop.

New Object Types

None

New Enum Constants

  • Extending VkStructureType:

    • VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR

New Enums

None

Issues

1) Does Win32 need a way to query for compatibility between a particular physical device and a specific screen? Compatibility between a physical device and a window generally only depends on what screen the window is on. However, there isn’t an obvious way to identify a screen without already having a window on the screen.

RESOLVED: No. While it may be useful, there isn't a clear way to do this on
Win32.  However, a method was added to query support for presenting to the
windows desktop as a whole.

Version History

  • Revision 1, 2015-09-23 (Jesse Hall)

    • Initial draft, based on the previous contents of VK_EXT_KHR_swapchain (later renamed VK_EXT_KHR_surface).
  • Revision 2, 2015-10-02 (James Jones)

    • Added presentation support query for win32 desktops.
  • Revision 3, 2015-10-26 (Ian Elliott)

    • Renamed from VK_EXT_KHR_win32_surface to VK_KHR_win32_surface.
  • Revision 4, 2015-11-03 (Daniel Rakos)

    • Added allocation callbacks to vkCreateWin32SurfaceKHR.
  • Revision 5, 2015-11-28 (Daniel Rakos)

    • Updated the surface create function to take a pCreateInfo structure.

C.2.10. VK_KHR_xcb_surface

Name String
VK_KHR_xcb_surface
Extension Type
Instance extension
Registered Extension Number
6
Last Modified Date
11/28/2015
Revision
6
IP Status
No known IP claims.
Dependencies
  • This extension is written against revision 1.0 of the Vulkan API.
  • This extension requires VK_KHR_surface.
Contributors
  • Patrick Doane, Blizzard
  • Jason Ekstrand, Intel
  • Ian Elliott, LunarG
  • Courtney Goeltzenleuchter, LunarG
  • Jesse Hall, Google
  • James Jones, NVIDIA
  • Antoine Labour, Google
  • Jon Leech, Khronos
  • David Mao, AMD
  • Norbert Nopper, Freescale
  • Alon Or-bach, Samsung
  • Daniel Rakos, AMD
  • Graham Sellers, AMD
  • Ray Smith, ARM
  • Jeff Vigil, Qualcomm
  • Chia-I Wu, LunarG
Contacts
  • Jesse Hall, Google
  • Ian Elliott, LunarG

The VK_KHR_xcb_surface extension is an instance extension. It provides a mechanism to create a VkSurfaceKHR object (defined by the VK_KHR_surface extension) that refers to an X11 window, using the XCB client-side library, as well as a query to determine support for rendering via XCB.

New Object Types

None

New Enum Constants

  • Extending VkStructureType:

    • VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR

New Enums

None

Issues

1) Does XCB need a way to query for compatibility between a particular physical device and a specific screen? This would be a more general query than vkGetPhysicalDeviceSurfaceSupportKHR: If it returned true, then the physical device could be assumed to support presentation to any window on that screen.

RESOLVED: Yes, this is needed for toolkits that want to create a VkDevice
before creating a window.  To ensure the query is reliable, it must be
made against a particular X visual rather than the screen in general.

Version History

  • Revision 1, 2015-09-23 (Jesse Hall)

    • Initial draft, based on the previous contents of VK_EXT_KHR_swapchain (later renamed VK_EXT_KHR_surface).
  • Revision 2, 2015-10-02 (James Jones)

    • Added presentation support query for an (xcb_connection_t*, xcb_visualid_t) pair.
    • Removed "root" parameter from CreateXcbSurfaceKHR(), as it is redundant when a window on the same screen is specified as well.
    • Adjusted wording of issue #1 and added agreed upon resolution.
  • Revision 3, 2015-10-14 (Ian Elliott)

    • Removed "root" parameter from CreateXcbSurfaceKHR() in one more place.
  • Revision 4, 2015-10-26 (Ian Elliott)

    • Renamed from VK_EXT_KHR_xcb_surface to VK_KHR_xcb_surface.
  • Revision 5, 2015-10-23 (Daniel Rakos)

    • Added allocation callbacks to vkCreateXcbSurfaceKHR.
  • Revision 6, 2015-11-28 (Daniel Rakos)

    • Updated the surface create function to take a pCreateInfo structure.

C.2.11. VK_KHR_xlib_surface

Name String
VK_KHR_xlib_surface
Extension Type
Instance extension
Registered Extension Number
5
Last Modified Date
11/28/2015
Revision
6
IP Status
No known IP claims.
Dependencies
  • This extension is written against revision 1.0 of the Vulkan API.
  • This extension requires VK_KHR_surface.
Contributors
  • Patrick Doane, Blizzard
  • Jason Ekstrand, Intel
  • Ian Elliott, LunarG
  • Courtney Goeltzenleuchter, LunarG
  • Jesse Hall, Google
  • James Jones, NVIDIA
  • Antoine Labour, Google
  • Jon Leech, Khronos
  • David Mao, AMD
  • Norbert Nopper, Freescale
  • Alon Or-bach, Samsung
  • Daniel Rakos, AMD
  • Graham Sellers, AMD
  • Ray Smith, ARM
  • Jeff Vigil, Qualcomm
  • Chia-I Wu, LunarG
Contacts
  • Jesse Hall, Google
  • Ian Elliott, LunarG

The VK_KHR_xlib_surface extension is an instance extension. It provides a mechanism to create a VkSurfaceKHR object (defined by the VK_KHR_surface extension) that refers to an X11 window, using the Xlib client-side library, as well as a query to determine support for rendering via Xlib.

New Object Types

None

New Enum Constants

  • Extending VkStructureType:

    • VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR

New Enums

None

Issues

1) Does X11 need a way to query for compatibility between a particular physical device and a specific screen? This would be a more general query than vkGetPhysicalDeviceSurfaceSupportKHR: If it returned true, then the physical device could be assumed to support presentation to any window on that screen.

RESOLVED: Yes, this is needed for toolkits that want to create a VkDevice
before creating a window.  To ensure the query is reliable, it must be
made against a particular X visual rather than the screen in general.

Version History

  • Revision 1, 2015-09-23 (Jesse Hall)

    • Initial draft, based on the previous contents of VK_EXT_KHR_swapchain (later renamed VK_EXT_KHR_surface).
  • Revision 2, 2015-10-02 (James Jones)

    • Added presentation support query for (Display*, VisualID) pair.
    • Removed "root" parameter from CreateXlibSurfaceKHR(), as it is redundant when a window on the same screen is specified as well.
    • Added appropriate X errors.
    • Adjusted wording of issue #1 and added agreed upon resolution.
  • Revision 3, 2015-10-14 (Ian Elliott)

    • Renamed this extension from VK_EXT_KHR_x11_surface to VK_EXT_KHR_xlib_surface.
  • Revision 4, 2015-10-26 (Ian Elliott)

    • Renamed from VK_EXT_KHR_xlib_surface to VK_KHR_xlib_surface.
  • Revision 5, 2015-11-03 (Daniel Rakos)

    • Added allocation callbacks to vkCreateXlibSurfaceKHR.
  • Revision 6, 2015-11-28 (Daniel Rakos)

    • Updated the surface create function to take a pCreateInfo structure.