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:
Jon Leech 2016-10-07 02:40:18 -07:00
parent 42fcc80976
commit 49adf2575c
14 changed files with 86 additions and 859 deletions

View File

@ -1452,3 +1452,32 @@ Other Issues:
* Use the terms ``allocation scope'' and ``extension scope'' instead of
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).

View File

@ -160,7 +160,7 @@ GENDEPENDS = api/timeMarker validity/timeMarker hostsynctable/timeMarker
COMMONDOCS = $(CHAPTERS) $(GENINCLUDE) $(GENDEPENDS)
# A generated included file containing the spec version, date, and git commit
SPECVERSION = specversion.txt
SPECREVISION = 1.0.29
SPECREVISION = 1.0.30
SPECREMARK =
# Spec targets

View File

@ -82,165 +82,12 @@ this and other platform-independent extensions, in particular the
.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.
was removed from the appendix after revision 1.0.29.
This WSI example code was ported to the cube demo that is shipped with the
official Khronos SDK, and is being kept up-to-date in that location (see:
https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/demos/cube.c).
====
**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
1) Should this extension include a method to query whether a physical device

View File

@ -457,665 +457,12 @@ None
.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.
was removed from the appendix after revision 1.0.29.
This WSI example code was ported to the cube demo that is shipped with the
official Khronos SDK, and is being kept up-to-date in that location (see:
https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/demos/cube.c).
====
**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
* Revision 1, 2015-05-20 (James Jones)

View File

@ -2,6 +2,7 @@
// Copyright notice at https://www.khronos.org/registry/speccopyright.html
[appendix]
[[invariance]]
= Invariance
The Vulkan specification is not pixel exact.
@ -59,7 +60,7 @@ Examples of these algorithms include:
== 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
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:*
* _Framebuffer contents (all bit planes)_
* _The color buffers enabled for writing_
* _Color and depth/stencil attachment contents_
* _Scissor parameters (other than enable)_
* _Writemasks (color, depth, stencil)_
* _Write masks (color, depth, stencil)_
* _Clear values (color, depth, stencil)_
*Strongly suggested:*
* _Stencil Parameters (other than enable)_
* _Stencil parameters (other than enable)_
* _Depth test parameters (other than enable)_
* _Blend parameters (other than enable)_
* _Logical operation parameters (other than enable)_
* _Pixel storage state_
*Corollary 1* _Fragment generation is invariant with respect to the state
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
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
sequence, are pixel identical._
*Rule 4* _The same vertex or fragment shader will produce the same result
when run multiple times with the same input.
The wording ``the same shader'' means a program object that is populated
with the same SPIR-V binary, which is used to create pipelines, possibly
multiple times, and which program object is then executed using the same
Vulkan state vector.
*Rule 4* _Identical pipelines will produce the same result when run multiple
times with the same input.
The wording ``Identical pipelines'' means sname:VkPipeline objects that have
been created with identical SPIR-V binaries and identical state, which are
then used by commands executed using the same Vulkan state vector.
Invariance is relaxed for shaders with side effects, such as performing
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
that initial Vulkan and framebuffer state._
*Rule 7* _The same vertex or fragment shader will produce the same result
when run multiple times with the same input as long as:_
*Rule 7* _Identical pipelines will produce the same result when run multiple
times with the same input as long as:_
* _shader invocations do not use image atomic operations;_
* _no framebuffer memory is written to more than once by image stores,
@ -141,7 +139,7 @@ be explicitly synchronized.
== 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
specified by an application and emits a new set of primitives.
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
tessellation levels, the tessellation primitive generator will emit an
identical set of point, line, or triangle primitives as long as the active
program used to process the patch primitives has tessellation evaluation
shaders specifying the same tessellation mode, spacing, vertex order, and
point mode decorations.
identical set of point, line, or triangle primitives as long as the pipeline
used to process the patch primitives has tessellation evaluation shaders
specifying the same tessellation mode, spacing, vertex order, and point mode
decorations.
Two sets of primitives are considered identical if and only if they contain
the same number and type of primitives and the generated tessellation
coordinates for the vertex numbered m of the primitive numbered n are

View File

@ -223,13 +223,15 @@ The sname:VkClearColorValue structure is defined as:
include::../api/structs/VkClearColorValue.txt[]
* pname:float32 are the color clear values when the format of the image or
attachment is floating point, unorm, snorm, uscaled, packed float, or
sRGB.
attachment is one of the formats in the
<<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
image, with the clear value being treated as linear if the image is
sRGB.
* 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
casting to the smaller type (with negative 32-bit values mapping to
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
undefined.
* 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
casting to the integer type with fewer bits.

View File

@ -418,6 +418,8 @@ be inherited from the primary command buffer:
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
passes the sname:VkCommandBuffer will be <<renderpass-compatibility,
compatible>> with and can: be executed within.

View File

@ -759,13 +759,13 @@ The following filtering and conversion rules apply:
* Integer formats can: only be converted to other integer formats with the
same signedness.
* No format conversion is supported between depth/stencil images - the
formats must: match.
* No format conversion is supported between depth/stencil images.
The formats must: match.
* Format conversions on unorm, snorm, unscaled and packed float formats of
the copied aspect of the image are performed by first converting the
pixels to float values.
* In case of sRGB source format, nonlinear RGB values are converted to
linear representation prior to filtering.
* For sRGB source formats, nonlinear RGB values are converted to linear
representation prior to filtering.
* After filtering, the float values are first clamped and then cast to the
destination image format.
In case of sRGB destination format, linear RGB values are converted to

View File

@ -3828,9 +3828,10 @@ one of the following conditions is true:
* pname:tiling is ename:VK_IMAGE_TILING_LINEAR
* pname:type is not ename:VK_IMAGE_TYPE_2D
* 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
flink:vkGetPhysicalDeviceFormatProperties is not set
flink:vkGetPhysicalDeviceFormatProperties is set
Otherwise, the bits set in pname:sampleCounts will be the sample counts
supported for the specified values of pname:usage and pname:format.

View File

@ -196,7 +196,7 @@ sname:VkPipelineShaderStageCreateInfo.
chapter
* pname:layout must: be
<<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[]

View File

@ -1736,11 +1736,12 @@ requirements returned by flink:vkGetBufferMemoryRequirements and
flink:vkGetImageMemoryRequirements:
* The pname:memoryTypeBits member always contains at least one bit set.
* If pname:buffer is a sname:VkBuffer, or if pname:image is a
sname:VkImage that was created with a ename:VK_IMAGE_TILING_LINEAR value
in the pname:tiling member of the sname:VkImageCreateInfo structure
passed to fname:vkCreateImage, then the pname:memoryTypeBits member
always contains at least one bit set corresponding to a
* If pname:buffer is a sname:VkBuffer not created with the
ename:VK_BUFFER_CREATE_SPARSE_BINDING_BIT bit set, or if pname:image is
a sname:VkImage that was created with a ename:VK_IMAGE_TILING_LINEAR
value in the pname:tiling member of the sname:VkImageCreateInfo
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
ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT bit and the
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit set.

View File

@ -19,17 +19,17 @@ from genspec import *
print('echo Building in Vulkan-Docs for public release')
print('')
buildBranch('1.0-wsi_extensions',
extensions = KHRextensions,
apititle = '(with KHR extensions)',
buildBranch('1.0-extensions',
extensions = allExtensions,
apititle = '(with all registered Vulkan extensions)',
xmlTargets = 'clobber install',
specTargets = 'xhtml pdf',
repoDir = '/home/tree/git/Vulkan-Docs',
outDir = '/home/tree/git/Vulkan-Web-Registry/specs')
buildBranch('1.0-extensions',
extensions = allExtensions,
apititle = '(with all registered Vulkan extensions)',
buildBranch('1.0-wsi_extensions',
extensions = KHRextensions,
apititle = '(with KHR extensions)',
xmlTargets = 'clobber install',
specTargets = 'xhtml pdf',
repoDir = '/home/tree/git/Vulkan-Docs',

View File

@ -104,7 +104,7 @@ maintained in the master branch of the Khronos Vulkan GitHub project.
<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 -->
<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">
#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;</type>

View File

@ -43,7 +43,7 @@ extern "C" {
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
// Version of this file
#define VK_HEADER_VERSION 29
#define VK_HEADER_VERSION 30
#define VK_NULL_HANDLE 0