Change log for October 7, 2016 Vulkan 1.0.30 spec update:
* Bump API patch number and header version number to 30 for this update. Github Issues: * Document missing pname:sType and pname:pNext parameters for slink:VkCommandBufferInheritanceInfo (public issue 224). * As promised, we are removing the example code, from the appendix, for the VK_KHR_surface and VK_KHR_swapchain extensions. The cube demo (shipped in the official Khronos SDK) has been updated, and is the example code that we want people to look at for how to use these two extensions (public issues 279, 308, and 311). * Clarify the formats for which the slink:VkClearColorValue pname:float32 member is used. Also clean up related language for flink:vkCmdBlitImage (public issue 369). * Reword the <<invariance, Invariance>> appendix chapter to better match Vulkan terminology (public issue 372). Internal Issues: * Update slink:VkMemoryRequirements to not require a host_visible memory type exists that can be bound to sparse buffers (internal issue 494). * Modify the <<features-supported-sample-counts,Supported Sample Counts>> language to allow multisampled depth-stencil images (internal issue 521).
This commit is contained in:
parent
42fcc80976
commit
49adf2575c
|
@ -1452,3 +1452,32 @@ Other Issues:
|
||||||
|
|
||||||
* Use the terms ``allocation scope'' and ``extension scope'' instead of
|
* Use the terms ``allocation scope'' and ``extension scope'' instead of
|
||||||
just ``scope'', and add them to the glossary.
|
just ``scope'', and add them to the glossary.
|
||||||
|
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
Change log for October 7, 2016 Vulkan 1.0.30 spec update:
|
||||||
|
|
||||||
|
* Bump API patch number and header version number to 30 for this update.
|
||||||
|
|
||||||
|
Github Issues:
|
||||||
|
|
||||||
|
* Document missing pname:sType and pname:pNext parameters for
|
||||||
|
slink:VkCommandBufferInheritanceInfo (public issue 224).
|
||||||
|
* As promised, we are removing the example code, from the appendix, for
|
||||||
|
the VK_KHR_surface and VK_KHR_swapchain extensions. The cube demo
|
||||||
|
(shipped in the official Khronos SDK) has been updated, and is the
|
||||||
|
example code that we want people to look at for how to use these two
|
||||||
|
extensions (public issues 279, 308, and 311).
|
||||||
|
* Clarify the formats for which the slink:VkClearColorValue pname:float32
|
||||||
|
member is used. Also clean up related language for flink:vkCmdBlitImage
|
||||||
|
(public issue 369).
|
||||||
|
* Reword the <<invariance, Invariance>> appendix chapter to better match
|
||||||
|
Vulkan terminology (public issue 372).
|
||||||
|
|
||||||
|
Internal Issues:
|
||||||
|
|
||||||
|
* Update slink:VkMemoryRequirements to not require a host_visible memory
|
||||||
|
type exists that can be bound to sparse buffers (internal issue 494).
|
||||||
|
* Modify the <<features-supported-sample-counts,Supported Sample Counts>>
|
||||||
|
language to allow multisampled depth-stencil images (internal issue
|
||||||
|
521).
|
||||||
|
|
|
@ -160,7 +160,7 @@ GENDEPENDS = api/timeMarker validity/timeMarker hostsynctable/timeMarker
|
||||||
COMMONDOCS = $(CHAPTERS) $(GENINCLUDE) $(GENDEPENDS)
|
COMMONDOCS = $(CHAPTERS) $(GENINCLUDE) $(GENDEPENDS)
|
||||||
# A generated included file containing the spec version, date, and git commit
|
# A generated included file containing the spec version, date, and git commit
|
||||||
SPECVERSION = specversion.txt
|
SPECVERSION = specversion.txt
|
||||||
SPECREVISION = 1.0.29
|
SPECREVISION = 1.0.30
|
||||||
SPECREMARK =
|
SPECREMARK =
|
||||||
|
|
||||||
# Spec targets
|
# Spec targets
|
||||||
|
|
|
@ -82,165 +82,12 @@ this and other platform-independent extensions, in particular the
|
||||||
.Note
|
.Note
|
||||||
====
|
====
|
||||||
The example code for the +VK_KHR_surface+ and +VK_KHR_swapchain+ extensions
|
The example code for the +VK_KHR_surface+ and +VK_KHR_swapchain+ extensions
|
||||||
will be removed from future versions of this appendix.
|
was removed from the appendix after revision 1.0.29.
|
||||||
The WSI example code was ported to the cube demo, that is shipped with the
|
This 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.
|
official Khronos SDK, and is being kept up-to-date in that location (see:
|
||||||
There is little reason to maintain this example code in the appendix as
|
https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/demos/cube.c).
|
||||||
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.
|
|
||||||
|
|
||||||
[source,{basebackend@docbook:c++:cpp}]
|
|
||||||
----------------------------------------
|
|
||||||
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.
|
|
||||||
|
|
||||||
[source,{basebackend@docbook:c++:cpp}]
|
|
||||||
----------------------------------------
|
|
||||||
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 did not 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
|
=== Issues
|
||||||
|
|
||||||
1) Should this extension include a method to query whether a physical device
|
1) Should this extension include a method to query whether a physical device
|
||||||
|
|
|
@ -457,665 +457,12 @@ None
|
||||||
.Note
|
.Note
|
||||||
====
|
====
|
||||||
The example code for the +VK_KHR_surface+ and +VK_KHR_swapchain+ extensions
|
The example code for the +VK_KHR_surface+ and +VK_KHR_swapchain+ extensions
|
||||||
will be removed from future versions of this appendix.
|
was removed from the appendix after revision 1.0.29.
|
||||||
The WSI example code was ported to the cube demo, that is shipped with the
|
This 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.
|
official Khronos SDK, and is being kept up-to-date in that location (see:
|
||||||
There is little reason to maintain this example code in the appendix as
|
https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/demos/cube.c).
|
||||||
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.
|
|
||||||
|
|
||||||
[source,{basebackend@docbook:c++:cpp}]
|
|
||||||
----------------------------------------
|
|
||||||
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.
|
|
||||||
|
|
||||||
[source,{basebackend@docbook:c++:cpp}]
|
|
||||||
----------------------------------------
|
|
||||||
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
|
|
||||||
|
|
||||||
[source,{basebackend@docbook:c++:cpp}]
|
|
||||||
----------------------------------------
|
|
||||||
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.
|
|
||||||
|
|
||||||
[source,{basebackend@docbook:c++:cpp}]
|
|
||||||
----------------------------------------
|
|
||||||
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.
|
|
||||||
|
|
||||||
[source,{basebackend@docbook:c++:cpp}]
|
|
||||||
----------------------------------------
|
|
||||||
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.
|
|
||||||
|
|
||||||
[source,{basebackend@docbook:c++:cpp}]
|
|
||||||
----------------------------------------
|
|
||||||
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
|
=== Version History
|
||||||
|
|
||||||
* Revision 1, 2015-05-20 (James Jones)
|
* Revision 1, 2015-05-20 (James Jones)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// Copyright notice at https://www.khronos.org/registry/speccopyright.html
|
// Copyright notice at https://www.khronos.org/registry/speccopyright.html
|
||||||
|
|
||||||
[appendix]
|
[appendix]
|
||||||
|
[[invariance]]
|
||||||
= Invariance
|
= Invariance
|
||||||
|
|
||||||
The Vulkan specification is not pixel exact.
|
The Vulkan specification is not pixel exact.
|
||||||
|
@ -59,7 +60,7 @@ Examples of these algorithms include:
|
||||||
|
|
||||||
== Invariance Rules
|
== Invariance Rules
|
||||||
|
|
||||||
For a given instantiation of an Vulkan rendering context:
|
For a given Vulkan device:
|
||||||
|
|
||||||
*Rule 1* _For any given Vulkan and framebuffer state vector, and for any
|
*Rule 1* _For any given Vulkan and framebuffer state vector, and for any
|
||||||
given Vulkan command, the resulting Vulkan and framebuffer state must: be
|
given Vulkan command, the resulting Vulkan and framebuffer state must: be
|
||||||
|
@ -71,19 +72,17 @@ use of any other state value is not affected by the change):_
|
||||||
|
|
||||||
*Required:*
|
*Required:*
|
||||||
|
|
||||||
* _Framebuffer contents (all bit planes)_
|
* _Color and depth/stencil attachment contents_
|
||||||
* _The color buffers enabled for writing_
|
|
||||||
* _Scissor parameters (other than enable)_
|
* _Scissor parameters (other than enable)_
|
||||||
* _Writemasks (color, depth, stencil)_
|
* _Write masks (color, depth, stencil)_
|
||||||
* _Clear values (color, depth, stencil)_
|
* _Clear values (color, depth, stencil)_
|
||||||
|
|
||||||
*Strongly suggested:*
|
*Strongly suggested:*
|
||||||
|
|
||||||
* _Stencil Parameters (other than enable)_
|
* _Stencil parameters (other than enable)_
|
||||||
* _Depth test parameters (other than enable)_
|
* _Depth test parameters (other than enable)_
|
||||||
* _Blend parameters (other than enable)_
|
* _Blend parameters (other than enable)_
|
||||||
* _Logical operation parameters (other than enable)_
|
* _Logical operation parameters (other than enable)_
|
||||||
* _Pixel storage state_
|
|
||||||
|
|
||||||
*Corollary 1* _Fragment generation is invariant with respect to the state
|
*Corollary 1* _Fragment generation is invariant with respect to the state
|
||||||
values listed in Rule 2._
|
values listed in Rule 2._
|
||||||
|
@ -91,16 +90,15 @@ values listed in Rule 2._
|
||||||
*Rule 3* _The arithmetic of each per-fragment operation is invariant except
|
*Rule 3* _The arithmetic of each per-fragment operation is invariant except
|
||||||
with respect to parameters that directly control it._
|
with respect to parameters that directly control it._
|
||||||
|
|
||||||
*Corollary 2* _Images rendered into different color buffers sharing the same
|
*Corollary 2* _Images rendered into different color attachments of the same
|
||||||
framebuffer, either simultaneously or separately using the same command
|
framebuffer, either simultaneously or separately using the same command
|
||||||
sequence, are pixel identical._
|
sequence, are pixel identical._
|
||||||
|
|
||||||
*Rule 4* _The same vertex or fragment shader will produce the same result
|
*Rule 4* _Identical pipelines will produce the same result when run multiple
|
||||||
when run multiple times with the same input.
|
times with the same input.
|
||||||
The wording ``the same shader'' means a program object that is populated
|
The wording ``Identical pipelines'' means sname:VkPipeline objects that have
|
||||||
with the same SPIR-V binary, which is used to create pipelines, possibly
|
been created with identical SPIR-V binaries and identical state, which are
|
||||||
multiple times, and which program object is then executed using the same
|
then used by commands executed using the same Vulkan state vector.
|
||||||
Vulkan state vector.
|
|
||||||
Invariance is relaxed for shaders with side effects, such as performing
|
Invariance is relaxed for shaders with side effects, such as performing
|
||||||
stores or atomics._
|
stores or atomics._
|
||||||
|
|
||||||
|
@ -124,8 +122,8 @@ indirectly affected by results of shader image or buffer variable stores or
|
||||||
atomic operations must: be identical each time the command is executed on
|
atomic operations must: be identical each time the command is executed on
|
||||||
that initial Vulkan and framebuffer state._
|
that initial Vulkan and framebuffer state._
|
||||||
|
|
||||||
*Rule 7* _The same vertex or fragment shader will produce the same result
|
*Rule 7* _Identical pipelines will produce the same result when run multiple
|
||||||
when run multiple times with the same input as long as:_
|
times with the same input as long as:_
|
||||||
|
|
||||||
* _shader invocations do not use image atomic operations;_
|
* _shader invocations do not use image atomic operations;_
|
||||||
* _no framebuffer memory is written to more than once by image stores,
|
* _no framebuffer memory is written to more than once by image stores,
|
||||||
|
@ -141,7 +139,7 @@ be explicitly synchronized.
|
||||||
|
|
||||||
== Tessellation Invariance
|
== Tessellation Invariance
|
||||||
|
|
||||||
When using a program containing tessellation evaluation shaders, the
|
When using a pipeline containing tessellation evaluation shaders, the
|
||||||
fixed-function tessellation primitive generator consumes the input patch
|
fixed-function tessellation primitive generator consumes the input patch
|
||||||
specified by an application and emits a new set of primitives.
|
specified by an application and emits a new set of primitives.
|
||||||
The following invariance rules are intended to provide repeatability
|
The following invariance rules are intended to provide repeatability
|
||||||
|
@ -154,10 +152,10 @@ positions of vertices along shared edges.
|
||||||
|
|
||||||
*Rule 1* _When processing two patches with identical outer and inner
|
*Rule 1* _When processing two patches with identical outer and inner
|
||||||
tessellation levels, the tessellation primitive generator will emit an
|
tessellation levels, the tessellation primitive generator will emit an
|
||||||
identical set of point, line, or triangle primitives as long as the active
|
identical set of point, line, or triangle primitives as long as the pipeline
|
||||||
program used to process the patch primitives has tessellation evaluation
|
used to process the patch primitives has tessellation evaluation shaders
|
||||||
shaders specifying the same tessellation mode, spacing, vertex order, and
|
specifying the same tessellation mode, spacing, vertex order, and point mode
|
||||||
point mode decorations.
|
decorations.
|
||||||
Two sets of primitives are considered identical if and only if they contain
|
Two sets of primitives are considered identical if and only if they contain
|
||||||
the same number and type of primitives and the generated tessellation
|
the same number and type of primitives and the generated tessellation
|
||||||
coordinates for the vertex numbered m of the primitive numbered n are
|
coordinates for the vertex numbered m of the primitive numbered n are
|
||||||
|
|
|
@ -223,13 +223,15 @@ The sname:VkClearColorValue structure is defined as:
|
||||||
include::../api/structs/VkClearColorValue.txt[]
|
include::../api/structs/VkClearColorValue.txt[]
|
||||||
|
|
||||||
* pname:float32 are the color clear values when the format of the image or
|
* pname:float32 are the color clear values when the format of the image or
|
||||||
attachment is floating point, unorm, snorm, uscaled, packed float, or
|
attachment is one of the formats in the
|
||||||
sRGB.
|
<<features-formats-numericformat, Interpretation of Numeric Format>>
|
||||||
|
table other than signed integer (etext:SINT) or unsigned integer
|
||||||
|
(etext:UINT).
|
||||||
Floating point values are automatically converted to the format of the
|
Floating point values are automatically converted to the format of the
|
||||||
image, with the clear value being treated as linear if the image is
|
image, with the clear value being treated as linear if the image is
|
||||||
sRGB.
|
sRGB.
|
||||||
* pname:int32 are the color clear values when the format of the image or
|
* pname:int32 are the color clear values when the format of the image or
|
||||||
attachment is signed integer.
|
attachment is signed integer (etext:SINT).
|
||||||
Signed integer values are converted to the format of the image by
|
Signed integer values are converted to the format of the image by
|
||||||
casting to the smaller type (with negative 32-bit values mapping to
|
casting to the smaller type (with negative 32-bit values mapping to
|
||||||
negative values in the smaller type).
|
negative values in the smaller type).
|
||||||
|
@ -237,7 +239,7 @@ include::../api/structs/VkClearColorValue.txt[]
|
||||||
would overflow in conversion to that type), the clear value is
|
would overflow in conversion to that type), the clear value is
|
||||||
undefined.
|
undefined.
|
||||||
* pname:uint32 are the color clear values when the format of the image or
|
* pname:uint32 are the color clear values when the format of the image or
|
||||||
attachment is unsigned integer.
|
attachment is unsigned integer (etext:UINT).
|
||||||
Unsigned integer values are converted to the format of the image by
|
Unsigned integer values are converted to the format of the image by
|
||||||
casting to the integer type with fewer bits.
|
casting to the integer type with fewer bits.
|
||||||
|
|
||||||
|
|
|
@ -418,6 +418,8 @@ be inherited from the primary command buffer:
|
||||||
|
|
||||||
include::../api/structs/VkCommandBufferInheritanceInfo.txt[]
|
include::../api/structs/VkCommandBufferInheritanceInfo.txt[]
|
||||||
|
|
||||||
|
* pname:sType is the type of this structure.
|
||||||
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
||||||
* pname:renderPass is a sname:VkRenderPass object defining which render
|
* pname:renderPass is a sname:VkRenderPass object defining which render
|
||||||
passes the sname:VkCommandBuffer will be <<renderpass-compatibility,
|
passes the sname:VkCommandBuffer will be <<renderpass-compatibility,
|
||||||
compatible>> with and can: be executed within.
|
compatible>> with and can: be executed within.
|
||||||
|
|
|
@ -759,13 +759,13 @@ The following filtering and conversion rules apply:
|
||||||
|
|
||||||
* Integer formats can: only be converted to other integer formats with the
|
* Integer formats can: only be converted to other integer formats with the
|
||||||
same signedness.
|
same signedness.
|
||||||
* No format conversion is supported between depth/stencil images - the
|
* No format conversion is supported between depth/stencil images.
|
||||||
formats must: match.
|
The formats must: match.
|
||||||
* Format conversions on unorm, snorm, unscaled and packed float formats of
|
* Format conversions on unorm, snorm, unscaled and packed float formats of
|
||||||
the copied aspect of the image are performed by first converting the
|
the copied aspect of the image are performed by first converting the
|
||||||
pixels to float values.
|
pixels to float values.
|
||||||
* In case of sRGB source format, nonlinear RGB values are converted to
|
* For sRGB source formats, nonlinear RGB values are converted to linear
|
||||||
linear representation prior to filtering.
|
representation prior to filtering.
|
||||||
* After filtering, the float values are first clamped and then cast to the
|
* After filtering, the float values are first clamped and then cast to the
|
||||||
destination image format.
|
destination image format.
|
||||||
In case of sRGB destination format, linear RGB values are converted to
|
In case of sRGB destination format, linear RGB values are converted to
|
||||||
|
|
|
@ -3828,9 +3828,10 @@ one of the following conditions is true:
|
||||||
* pname:tiling is ename:VK_IMAGE_TILING_LINEAR
|
* pname:tiling is ename:VK_IMAGE_TILING_LINEAR
|
||||||
* pname:type is not ename:VK_IMAGE_TYPE_2D
|
* pname:type is not ename:VK_IMAGE_TYPE_2D
|
||||||
* pname:flags contains ename:VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
|
* pname:flags contains ename:VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
|
||||||
* The ename:VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag in
|
* Neither the ename:VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT flag nor the
|
||||||
|
ename:VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT flag in
|
||||||
sname:VkFormatProperties::pname:optimalTilingFeatures returned by
|
sname:VkFormatProperties::pname:optimalTilingFeatures returned by
|
||||||
flink:vkGetPhysicalDeviceFormatProperties is not set
|
flink:vkGetPhysicalDeviceFormatProperties is set
|
||||||
|
|
||||||
Otherwise, the bits set in pname:sampleCounts will be the sample counts
|
Otherwise, the bits set in pname:sampleCounts will be the sample counts
|
||||||
supported for the specified values of pname:usage and pname:format.
|
supported for the specified values of pname:usage and pname:format.
|
||||||
|
|
|
@ -196,7 +196,7 @@ sname:VkPipelineShaderStageCreateInfo.
|
||||||
chapter
|
chapter
|
||||||
* pname:layout must: be
|
* pname:layout must: be
|
||||||
<<descriptorsets-pipelinelayout-consistency,consistent>> with the layout
|
<<descriptorsets-pipelinelayout-consistency,consistent>> with the layout
|
||||||
of the compute shader specified in pname:stage</usage>
|
of the compute shader specified in pname:stage
|
||||||
****
|
****
|
||||||
|
|
||||||
include::../validity/structs/VkComputePipelineCreateInfo.txt[]
|
include::../validity/structs/VkComputePipelineCreateInfo.txt[]
|
||||||
|
|
|
@ -1736,11 +1736,12 @@ requirements returned by flink:vkGetBufferMemoryRequirements and
|
||||||
flink:vkGetImageMemoryRequirements:
|
flink:vkGetImageMemoryRequirements:
|
||||||
|
|
||||||
* The pname:memoryTypeBits member always contains at least one bit set.
|
* The pname:memoryTypeBits member always contains at least one bit set.
|
||||||
* If pname:buffer is a sname:VkBuffer, or if pname:image is a
|
* If pname:buffer is a sname:VkBuffer not created with the
|
||||||
sname:VkImage that was created with a ename:VK_IMAGE_TILING_LINEAR value
|
ename:VK_BUFFER_CREATE_SPARSE_BINDING_BIT bit set, or if pname:image is
|
||||||
in the pname:tiling member of the sname:VkImageCreateInfo structure
|
a sname:VkImage that was created with a ename:VK_IMAGE_TILING_LINEAR
|
||||||
passed to fname:vkCreateImage, then the pname:memoryTypeBits member
|
value in the pname:tiling member of the sname:VkImageCreateInfo
|
||||||
always contains at least one bit set corresponding to a
|
structure passed to fname:vkCreateImage, then the pname:memoryTypeBits
|
||||||
|
member always contains at least one bit set corresponding to a
|
||||||
sname:VkMemoryType with a pname:propertyFlags that has both the
|
sname:VkMemoryType with a pname:propertyFlags that has both the
|
||||||
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit and the
|
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit and the
|
||||||
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit set.
|
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit set.
|
||||||
|
|
|
@ -19,17 +19,17 @@ from genspec import *
|
||||||
print('echo Building in Vulkan-Docs for public release')
|
print('echo Building in Vulkan-Docs for public release')
|
||||||
print('')
|
print('')
|
||||||
|
|
||||||
buildBranch('1.0-wsi_extensions',
|
buildBranch('1.0-extensions',
|
||||||
extensions = KHRextensions,
|
extensions = allExtensions,
|
||||||
apititle = '(with KHR extensions)',
|
apititle = '(with all registered Vulkan extensions)',
|
||||||
xmlTargets = 'clobber install',
|
xmlTargets = 'clobber install',
|
||||||
specTargets = 'xhtml pdf',
|
specTargets = 'xhtml pdf',
|
||||||
repoDir = '/home/tree/git/Vulkan-Docs',
|
repoDir = '/home/tree/git/Vulkan-Docs',
|
||||||
outDir = '/home/tree/git/Vulkan-Web-Registry/specs')
|
outDir = '/home/tree/git/Vulkan-Web-Registry/specs')
|
||||||
|
|
||||||
buildBranch('1.0-extensions',
|
buildBranch('1.0-wsi_extensions',
|
||||||
extensions = allExtensions,
|
extensions = KHRextensions,
|
||||||
apititle = '(with all registered Vulkan extensions)',
|
apititle = '(with KHR extensions)',
|
||||||
xmlTargets = 'clobber install',
|
xmlTargets = 'clobber install',
|
||||||
specTargets = 'xhtml pdf',
|
specTargets = 'xhtml pdf',
|
||||||
repoDir = '/home/tree/git/Vulkan-Docs',
|
repoDir = '/home/tree/git/Vulkan-Docs',
|
||||||
|
|
|
@ -104,7 +104,7 @@ maintained in the master branch of the Khronos Vulkan GitHub project.
|
||||||
<type category="define">// Vulkan 1.0 version number
|
<type category="define">// Vulkan 1.0 version number
|
||||||
#define <name>VK_API_VERSION_1_0</name> <type>VK_MAKE_VERSION</type>(1, 0, 0)</type> <!-- The patch version here should never be set to anything other than 0 -->
|
#define <name>VK_API_VERSION_1_0</name> <type>VK_MAKE_VERSION</type>(1, 0, 0)</type> <!-- The patch version here should never be set to anything other than 0 -->
|
||||||
<type category="define">// Version of this file
|
<type category="define">// Version of this file
|
||||||
#define <name>VK_HEADER_VERSION</name> 29</type>
|
#define <name>VK_HEADER_VERSION</name> 30</type>
|
||||||
|
|
||||||
<type category="define">
|
<type category="define">
|
||||||
#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;</type>
|
#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;</type>
|
||||||
|
|
|
@ -43,7 +43,7 @@ extern "C" {
|
||||||
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
|
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
|
||||||
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
|
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
|
||||||
// Version of this file
|
// Version of this file
|
||||||
#define VK_HEADER_VERSION 29
|
#define VK_HEADER_VERSION 30
|
||||||
|
|
||||||
|
|
||||||
#define VK_NULL_HANDLE 0
|
#define VK_NULL_HANDLE 0
|
||||||
|
|
Loading…
Reference in New Issue