Giter Site home page Giter Site logo

khronosgroup / vulkan-docs Goto Github PK

View Code? Open in Web Editor NEW
2.7K 227.0 454.0 41.33 MB

The Vulkan API Specification and related tools

License: Other

Makefile 1.28% Python 36.89% C 0.50% Shell 0.64% Ruby 1.45% CSS 2.01% JavaScript 46.20% Perl 0.47% C++ 0.06% HTML 10.51%

vulkan-docs's Introduction

Vulkan® and Vulkan® SC API Documentation Project

For Vulkan® API specific documentation see READMEVK.adoc

For Vulkan® SC API specific documentation see READMESC.adoc

Directory Structure

The directory structure is as follows:

README.adoc           This file
READMESC.adoc         Readme for the Vulkan SC specification
READMEVK.adoc         Readme for the Vulkan specification
BUILD.adoc            Documents how to build the specifications and reference pages
CONTRIBUTING.adoc     Requirements for external contributions to the repository
COPYING.adoc          Copyright and licensing information
CODE_OF_CONDUCT.adoc  Code of Conduct
LICENSE.adoc          Summary of licenses used by files in the repository
ChangeLog.adoc        Change log summary for each public Vulkan spec update
ChangeLogSC.adoc      Change log summary for each public Vulkan SC spec update
Makefile, make*       Makefile and helper build scripts (see BUILD.adoc)
antora/               Staging area for the docs.vulkan.org Antora 'proposals' and 'spec' modules
appendices/           Specification appendices
chapters/             Specification chapters
proposals/            Design documents for extensions
config/               Asciidoctor configuration, CSS, and index generator
images/               Images (figures, diagrams, icons)
gen/out/              Default directory for the generated documents
scripts/              Helper scripts used in specification, header, and reference page generation
style/                Sources for "styleguide" (Vulkan Documentation and Extensions: Procedures and Conventions)
xml/                  XML API Registry (`vk.xml`) as well as XML for non-Vulkan
                      data structures used with Video extensions (`video.xml`)
registry.adoc         Source for documentation of the XML format

Building the Specification and Reference Pages

The document sources are marked up in Asciidoctor format, and we use asciidoctor and related toolchain components to generate output documents. See BUILD.adoc for more information on installing the toolchain and building the Specification.

The header files (include/vulkan/vulkan*.h) and many parts of the specification and reference page documents are generated from descriptions in the XML API Registry (xml/vk.xml). The generated files are not checked into the repository. If you change vk.xml, you can regenerate the headers by going into xml/ and running:

$ make clean install

The other generated files are built as required via dependencies in the top-level Makefile.

vulkan-docs's People

Contributors

bestyeen avatar caramelli avatar dadschoorse avatar expipiplus1 avatar friz64 avatar gfxstrand avatar gpx1000 avatar jeffbolznv avatar krooze avatar marijns95 avatar marky-lunarg avatar martty avatar marty-johnson59 avatar mgorchak-blackberry avatar mtavenrath avatar mualphaomegaepsilon avatar oddhack avatar philiptaylor avatar qbojj avatar rua avatar saschawillems avatar shabbyx avatar sjfricke avatar star-e avatar stonesthrow avatar tobine avatar tobski avatar vallentin avatar vtec234 avatar whenning42 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vulkan-docs's Issues

Device memory mapping issues

Section 10.2.1 (Host Access to Device Memory Objects) says:

[... vkMapMemory ...]

  • offset must be less than the size of memory
  • If size is not equal to VK_WHOLE_SIZE, the sum of offset and size must be less than or equal to the size of the memory

There's nothing that says size must be greater than zero, so e.g. { size = 0, offset = size_of_memory - 1 } is perfectly fine. But { size = 0, offset = size_of_memory } fails the first condition, yet passes the second condition.

Is that intentional?

Most Vulkan commands seem to forbid sizes of zero, e.g. vkAllocateMemory requires allocationSize > 0. mmap() also fails if len is zero (http://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html).

If size is allowed to be zero, the restriction on offset seems weird to me. It's inconsistent with e.g. pointers in C, which are permitted to point to the element just after the end of the array (as long as you don't dereference more than 0 bytes of them).

If size isn't allowed to be zero, the "offset must be less than the size of memory" requirement seems entirely redundant with the next requirement.

(I'm assuming that "sum of offset and size" means a proper mathematical sum without any integer overflow. If it didn't mean that, and instead meant a VkDeviceSize-sized C addition with overflow, then { offset = 10, size = (VkDeviceSize)-10 } would be accepted, which would be silly, so presumably it's not that.)

the application must round down the start of the sub-range to the previous multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize

If nonCoherentAtomSize is 64, and I call vkMapAllocate with offset=0, this is saying I have to round down the sub-range offset to -64 (since that's the "previous multiple" of 64), which is nonsensical.

I think this should say "round down ... to the nearest multiple of nonCoherentAtomSize" (similarly to how it says "round the end of the range up to the nearest multiple") (with the implicit understanding that it means "nearest in the direction of rounding").

sub-range

The rest of the section talks about a "range", not a "sub-range". If there is no technical difference then they should use the same term.

[... vkFlushMappedMemoryRanges ...]

  • The memory ranges specified by pMemoryRanges must all currently be mapped

This doesn't account for the rounding to nonCoherentAtomSize that was previously described. I believe the memory between round_down(vkMapMemory.offset, nonCoherentAtomSize) and vkMapMemory.offset does not count as mapped, so this requirement forbids it being passed to vkFlushMappedMemoryRanges.

  • The memory ranges specified by pMemoryRanges must all currently be mapped

If I map a 64KB range, then want to flush the first 4KB of it, is that allowed? In one interpretation, I never mapped a 4KB memory range so I'm not allowed to flush a 4KB memory range. In another interpretation, that section of the memory object is mapped (as part of a larger section) so I am allowed to flush it.

I don't think the spec is clear about whether a "memory range" is a discrete thing with an offset/size, with a direct correspondence to VkMappedMemoryRange, or is a sequence of bytes that might happen to share the property of being mapped.

(If it's a discrete thing, and you can only flush exactly the range mapped by vkMapMemory, then it's impossible to flush a range that's not aligned to nonCoherentAtomSize.)

[... VkMappedMemoryRange ...]

  • offset is the zero-based byte offset from the beginning of the memory object.
  • [...]
  • offset must be less than the size of the currently mapped range of memory
  • If size is not equal to VK_WHOLE_SIZE, the sum of offset and size must be less than or equal to the size of the currently mapped range of memory

That means that if I map with { size = 64, offset = 4096 }, it's impossible to ever flush/invalidate that range. I'd have to set VkMappedMemoryRange.offset = 4096 to reach the mapped range, but 4096 > 64 so it violates the first of those requirements (and also violates the second unless I flush VK_WHOLE_SIZE).

Device memory type ordering

Section 10.2 (Device Memory) says:

Memory types are ordered in the list such that X is assigned a lesser memoryTypeIndex than Y if X≤Y according to the partial order.

That implies X is always assigned a lesser memoryTypeIndex than X (because X <= X), which is impossible. It should use a strict partial order instead, i.e. say X is assigned lesser than Y if X < Y (which is equivalent to saying X <= Y && !(Y <= X) using the earlier definition of '<=').

Note that the list of all allowed memory property flag combinations above satisfies this partial order

No it doesn't. E.g. "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT" is a subset of "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT" but comes later in that list.

Rearranging the list doesn't sound like a good solution, because then the slower non-DEVICE_LOCAL ones would be preferred over the DEVICE_LOCAL ones. Maybe the definition of the order should be changed to ignore DEVICE_LOCAL in the bits comparison (and rely on the performance clause to prefer the DEVICE_LOCAL ones).

Given two memory types X and Y, the partial order defines X≤Y if:

I think mathematically it's a preorder, not a partial order, under the widely-accepted definitions of those terms (e.g. http://mathworld.wolfram.com/PartialOrder.html, http://mathworld.wolfram.com/Preorder.html).

You could have two distinct memory types X != Y (e.g. they have different heapIndexes, or the same heapIndex and just different memoryTypeIndex) that have the same propertyFlags and the same performance, so that X <= Y and Y <= X. A partial order is defined to have antisymmetry, i.e. X <= Y && Y <= X implies X = Y, which is not true in this case. A preorder is a partial order without antisymmetry, which means two elements can be equivalent but non-equal, which is what we want here.

...But maybe that's possibly being too pedantic about terminology.

Can't add labels to issues

In the spec, "Filing Bug Reports" says:

Please tag issues with appropriate labels, such as “Specification”, “Ref Pages” or “Registry”, to help us triage and assign them appropriately.

But unless I'm being really dumb and failing to understand GitHub's UI, there is no way for me to add labels to new or existing issues. Perhaps it's some permissions thing?

Addition of a document type definition for safe API specification

A document type definition can help to work with corresponding explanations because it describes the involved data structures to some degree. Such a DTD can be added so that further improvements will become easier for the safe data exchange around this evolving software library.

A DTD format was standardised as a basis for XML documents. Some technical challenges and limitations were noticed so that another standard like W3C XML Schema evolved. Such a XML schema definition can also be added so that corresponding handling of provided application programming interfaces might become more consistent.

Shader memory model seems poorly defined

The "Shader Memory Access Ordering" section says:

For example, if one shader invocation does a series of writes, followed by an OpMemoryBarrier instruction, followed by another write, then another invocation that sees the results of the final write will also see the previous writes.

Isn't it also necessary that the second shader invocation has an OpMemoryBarrier instruction in between its reads? Otherwise the reads could be reordered too, so you can't say that they will "see" one of the writes before the other.

E.g. if a shader does

if (g_is_cached) {   // g_ variables are in some kind of global shared memory
  f(g_cached_value);
} else {
  int value = expensive_computation();
  g_cached_value = value;
  OpMemoryBarrier(...);
  g_is_cached = true;
  f(value);
}

then a second invocation might see g_is_cached==true but fail to see the computed value in g_cached_value, if I understand the memory model correctly. It would need another barrier between the reads.

Also it says:

OpMemoryBarrier guarantees that any memory transactions issued by the shader invocation prior to the instruction complete prior to the memory transactions issued after the instruction.

Is that actually true? The SPIR-V 1.0 Specification says OpMemoryBarrier can have several different scopes and several different semanticses, and it looks like not all of them will provide that guarantee. But it's kind of hard to understand because the SPIR-V Execution and Memory Model Specification seems to be written only for OpenCL, not Vulkan, and also talks about things like "the LocalMemory and GlobalMemory memory semantics flags" which don't appear to be defined by SPIR-V even for OpenCL (I guess they got renamed to WorkgroupMemory and CrossWorkgroupMemory). So I think this is a more general complaint that the memory model doesn't seem to be properly specified at all - is there some work in progress on improving that?

Typo Correction

Under

Chapter 24. Rasterization

The members of the VkPipelineMultisampleStateCreateInfo structure are as follows:

alphaToOne alphaToOneEnable controls whether the value of the alpha component of the fragment’s first color output is replaced with one as described in Multisample Coverage.

RGB to Shared Exponent Conversion

https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#textures-RGB-sexp says:

exp' = \max(-B-1, \left \lfloor \log_2(max_{clamped}+1+B) \right \rfloor)

I won't pretend to understand what this is actually doing, but adding 1+B before the log_2 seems weird to me (because it's a number of bits so why would you log it?). And I think that always results in exp' >= 4.

The similar equation in OpenGL looks more like

exp' = \max(-B-1, \left \lfloor \log_2(max_{clamped} \right \rfloor) + 1 + B

although I think that's also broken because max_{clamped} can be 0 and log(0) is undefined.

Maybe doing the max inside the log is better:

exp' = \left \lfloor \log_2(max(2^{-B-1}, max_{clamped})) \right \rfloor + 1 + B

which should give you a number 0 <= exp' <= E_max, which is hopefully closer to what's wanted, with no asymptotically undefined behaviour.

vulkan.h: VkResult groups VK_SUBOPTIMAL_KHR with VK_ERROR_*

https://github.com/KhronosGroup/Vulkan-Docs/blob/1.0/src/vulkan/vulkan.h#L141 has

typedef enum VkResult {
    VK_SUCCESS = 0,
    VK_NOT_READY = 1,
    VK_TIMEOUT = 2,
    VK_EVENT_SET = 3,
    VK_EVENT_RESET = 4,
    VK_INCOMPLETE = 5,
         VK_SUBOPTIMAL_KHR = 1000001003, // positive value, ideally should be declared here
    VK_ERROR_OUT_OF_HOST_MEMORY = -1,
    VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
    VK_ERROR_INITIALIZATION_FAILED = -3,
    VK_ERROR_DEVICE_LOST = -4,
    VK_ERROR_MEMORY_MAP_FAILED = -5,
    VK_ERROR_LAYER_NOT_PRESENT = -6,
    VK_ERROR_EXTENSION_NOT_PRESENT = -7,
    VK_ERROR_FEATURE_NOT_PRESENT = -8,
    VK_ERROR_INCOMPATIBLE_DRIVER = -9,
    VK_ERROR_TOO_MANY_OBJECTS = -10,
    VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
    VK_ERROR_SURFACE_LOST_KHR = -1000000000,
    VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
         VK_SUBOPTIMAL_KHR = 1000001003, // positive value, ideally should not be declared within negative values
    VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
    VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
    VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
    VK_RESULT_BEGIN_RANGE = VK_ERROR_FORMAT_NOT_SUPPORTED,
    VK_RESULT_END_RANGE = VK_INCOMPLETE,
    VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FORMAT_NOT_SUPPORTED + 1),
    VK_RESULT_MAX_ENUM = 0x7FFFFFFF
} VkResult;

ArrayStride/MatrixStride vs base alignment

https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#interfaces-resources-layout says:

Any ArrayStride or MatrixStride decoration must equal the base alignment of the array or matrix from above.

If I have

struct A {
    vec4 a, b; // base alignment of each member is 16
}; // base alignment of struct is largest of its members (16) rounded up to 16

uniform blk {
    A x[2]; // base alignment of array is equal to element (16) rounded up to 16
};

then I think this says the ArrayStride of x must be equal to its base alignment of 16. But sizeof(A) == 32, so the stride is smaller than the element size, which doesn't sound right.

Perhaps this meant the ArrayStride must be a multiple of the base alignment. (And specifically a positive multiple, or larger than or equal to the element size, or something.)

Equations in len attribute without latex:

registry.rnc says equations in the len attribute of <member> and <param> are prefixed by latex:, but of the three equations I saw, two had no prefix (codeSize/4 in VkShaderModuleCreateInfo, dataSize/4 in vkCmdUpdateBuffer) and the other is prefixed with latexmath: (in VkPipelineMultisampleStateCreateInfo).

It would be nice if they were consistently marked, so code attempting to generate code based on the len attribute can more easily tell which need special/manual processing.

From the rest of the XML file, I assume latexmath: is the correct prefix.

Xml spec: Converting C text to attributes

Hi.

Are there any plans to make the xml spec less dependent on the C language?

For example, for const and/or pointer arguments it would be possible to add a type/parameter modifier attribute:

<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
    <proto><type>VkResult</type> <name>vkCreateFence</name></proto>
    <param><type>VkDevice</type> <name>device</name></param>
    <param modifier="const"><type modifier="pointer">VkFenceCreateInfo</type> <name>pCreateInfo</name></param>
    <param modifier="const" optional="true"><type modifier="pointer">VkAllocationCallbacks</type> <name>pAllocator</name></param>
    <param><type modifier="pointer">VkFence</type> <name>pFence</name></param>
</command>

And for function pointers, it would be possible to wrap a command inside a type:

<type category="funcpointer">
    <command>
        <proto><type>void</type> <name>PFN_vkInternalAllocationNotification</name></proto>
        <param><type modifier="pointer">void</type> <name>pUserData</name></param>
        <param><type>size_t</type> <name>size</name></param>
        <param><type>VkInternalAllocationType</type> <name>allocationType</name></param>
        <param><type>VkSystemAllocationScope</type> <name>allocationScope</name></param>
    </command>
</type>

This would be useful to language bindings, since the definitions would be more aligned with xml, instead of text in between elements, and still without loosing the expressiveness of C.

Related with #10

Invocation Groups not well-defined by the Vulkan specification.

SPIR-V 1.00 R3 defines the concept of an invocation group. However, it only fully defines it for a compute operation (where it is defined as "a particular compute workgroup"). For other shader types, it is defined as a "graphical operation" which is further defined as:

implementation dependent, but at least as large as a single triangle
or patch, and at most as large as a single rendering command, as defined by the client API.

So the client API is supposed to fill in the details. But Vulkan never does. Or at least, not explicitly. I've read through Chapter 8, and the concept never comes up. Vulkan in fact never mentions the term "invocation group" at all (at least, as far as I can tell from doing a text search).

This is important because it's not clear what dynamically uniform means in some cases. Some examples:

  • Is a value from a flat interpolated fragment shader input "dynamically uniform"? Well, if "invocation group" for fragment shaders is defined as the primitive, then it is dynamically uniform. If "invocation group" for fragment shaders is defined as the whole rendering command, then it is not.
  • Is InstanceIndex dynamically uniform for Vertex Shaders? It could be, if "invocation group" were defined as the sequence of primitives within an instance, but it would not be if "invocation group for VS's were the whole rendering command.
  • Are patch inputs to TES shaders dynamically uniform? If "invocation group" means all of the invocations that cover a patch, then it is. If it is defined as the whole rendering command, then it isn't.
  • Are the input arrays to TCS shaders dynamically uniform? Again, if "invocation group" means all of the invocations that cover a patch, then it is. If it is defined as the whole rendering command, then it isn't.

Each shader stage definition in Chapter 8 should have an explicit paragraph stating how it defines "invocation group".

Editorial issues (sections 10-13)

A bunch of things. Section numbers are based on https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html

10.1

VK_SYSTEM_ALLOCATION_SCOPE_COMMAND - The allocation is scoped to the lifetime of the Vulkan command.

I don't understand what the "lifetime" of a command is - is that defined anywhere?

I guess it's just until the exit of the current vkFoo function call, in which case "duration of the Vulkan command" might be clearer.

(Lifetimes are much more obvious for all the other allocation scopes, because they're things that get explicitly created/allocated and destroyed/freed, so they're okay.)

pfnAllocation or pfnReallocation may be called in the following situations:

That doesn't list any cases where host memory scoped to the lifetime of a Vulkan command may be allocated. (I guess it should be added to the "may be allocated from any API command" category.)

11.1

Buffers represent linear arrays of data which are used for various purposes by binding them to the graphics pipeline via descriptor sets or via certain commands, or by directly specifying them as parameters to certain commands.

That just says "graphics pipeline", but I think they can be bound to compute pipelines too. Similar in the introduction to section 11.3 (Images).

11.2

  • The value of range must be greater than 0
  • The value of range, divided by the size of an element of format, must be less than or equal to the value of VkPhysicalDeviceLimits::maxTexelBufferElements

Is VK_WHOLE_SIZE greater than 0? and what is VK_WHOLE_SIZE divided by an integer? These probably need to be stated as "If range is not equal to VK_WHOLE_SIZE, ...".

11.3

The value of mipLevels must be less than or equal to or equal to the value of [...]

Duplication of "or equal to".

The value of mipLevels must be less than or equal to or equal to the value of ⌊log2(max(extent.width,extent.height,extent.depth))⌋+1

That means I can make an image with imageType = VK_IMAGE_TYPE_2D, extent = { 256, 256, 2^31 }, and mipLevels = 32, which seems silly.

I think either it should require extent.depth = 1 for 2D/1D and extent.height = 1 for 1D; or it should ignore the unused dimensions for the limit of mipLevels.

11.4

VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: [...] This layout is valid only for subresources of images created with both the VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT usage bit enabled.

Shouldn't say "both", it's only listing one bit.

  • (baseMipLevel+levelCount) must be less than or equal to the mipLevels specified in VkImageCreateInfo when the image was created
  • (baseArrayLayer+layerCount) must be less than or equal to the arrayLayers specified in VkImageCreateInfo when the image was created

These requirements should only apply when levelCount != VK_REMAINING_MIP_LEVELS, layerCount != VK_REMAINING_ARRAY_LAYERS.

11.6

if usage1 and usage2 of type VkBufferUsageFlags are such that usage2 contains a subset of the bits set in usage1 [...]

What does it mean to "contain a subset" here? I'd usually interpret "contain" as "is a superset of" - and the null set is always a subset of the bits set in usage1, and every set contains the null set, so this is trivially true and meaningless.

13.1.11

layout (input_attachment_index=i, set=m, binding=n) uniform subpass myInputAttachment;

The corresponding SPIR-V example doesn't use "i" anywhere. I guess it should have a "OpDecorate %7 InputAttachmentIndex i" to decorate the OpTypeImage.

13.2.1

myResult = vkCreateDescriptorSetLayout(
    myDevice,
    &myDescriptorSetLayoutCreateInfo[0],
    &myDescriptorSetLayout[0]);

Missing the pAllocator argument.

13.2.2

const VkDescriptorSetLayout layouts = { layout1, layout2 };

Should be "layouts[]".

const VkPipelineLayoutCreateInfo createInfo =
{
    VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,  // sType
    NULL,                                           // pNext
    2,                                              // setLayoutCount
    layouts,                                        // pSetLayouts
    2,                                              // pushConstantRangeCount
    ranges                                          // pPushConstantRanges
};

Missing the flags argument.

myResult = vkCreatePipelineLayout(
    myDevice,
    &createInfo,
    &myPipelineLayout);

Missing the pAllocator argument.

13.2.3

descriptorSetCount determines the number descriptor sets to be allocated from the pool.

Should be "number of".

All submitted commands that refer to any element of pDesciptorSets must have completed execution

Typo ("pDesciptorSets").

13.2.4

  • If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, the VkBuffer that pTexelBufferView was created from must have been created with VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT set
  • If descriptorType is VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, the VkBuffer that pTexelBufferView was created from must have been created with VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT set

pTexelBufferView wasn't created from anything - it's just an array. Maybe this should say "If ..., the VkBuffer that any given element of pTexelBufferView was created from must ...".

  • If descriptorType is VK_DESCRIPTOR_TYPE_STORAGE_IMAGE or VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, the imageView must have been created with identity swizzle

What imageView? Maybe this should say "the imageView member of any given element of pImageInfo must have been ...".

[... VkDescriptorBufferInfo ...]

  • If range is not equal to VK_WHOLE_SIZE, the sum of offset and range must be less than or equal to the size of buffer

What if range == VK_WHOLE_SIZE and offset > size_of_buffer? Seems like there should be a restriction that offset must be less than or equal to the size of buffer, to be consistent with the restriction on offset+size.

imageInfo is of type VkDescriptorImageInfo and is defined as:

What is "imageInfo"? That name isn't referenced anywhere else. Maybe should say "Each entry of pImageInfo is of type ...".

Each element in the pDescriptorCopies array in a VkCopyDescriptorSet structure describing an operation copying descriptors between sets.

Should be "describes", not "describing".

13.2.5

  • commandbuffer is the command buffer that the descriptor sets will be bound to.

Should be "commandBuffer".

If any of the sets being bound include dynamic uniform or storage buffers, then pDynamicOffsets includes one element for each array element in each dynamic descriptor type binding in each set. Values are taken from

Unexpected end of sentence after "from".

within a set, entries are ordered by the binding numbers in the decriptor set layouts

Typo ("decriptor").

  • Any given element of pDescriptorSets must have been created with a VkDescriptorSetLayout that matches the VkDescriptorSetLayout at set n in layout, where n is the sum of the index into pDescriptorSets and firstSet

I think it's unclear what "matches" means here. I guess it's like Pipeline Layout Compatibility's mention of "matching (the same, or identically defined)", rather than meaning handle equality, but it should be more explicit here.

13.2.6

  • commandbuffer is the command buffer in which the push constant update will be recorded.

Should be "commandBuffer".

Reentrancy and VkAllocationCallbacks

Is it safe for a VkAllocationCallbacks function to call into the Vulkan API? I don't see this specified anywhere.

I think reentrancy is not exactly the same as thread-safety: some functions are defined as internally synchronized, in which case it's safe for many threads to call them concurrently, but it might not be safe for an allocation callback to call them, because they might try to acquire an implementation-internal lock that's already held by the caller of the allocation callback, leading to deadlock.

(I can't think of any plausible reason why an application would want to do that, so it should probably just be forbidden.)

Inconsistent use of Vk*Flags vs Vk*FlagBits

Flags are defined as a pair of types: Vk*Flags, which is a typedef for uint32_t, and Vk*FlagBits which is an actual enum. Both are used to as the types of struct members and command params, so it isn't clear if there is some distinction being made or if all of the uses should have been Vk*Flags.

In particular, VkSurfaceTransformFlagsKHR and VkSurfaceTransformFlagBitsKHR are both used as type of members in VkSurfaceCapabilitiesKHR.
Other examples include VkShaderStageFlags, VkCompositeAlphaFlagsKHR, and VkDisplayPlaneAlphaFlagsKHR where the Flags variant is used in some members and FlagBits is used in others, and VkPipelineStageFlags where both variants are used as function params.

Integer color value 1

https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#textures-texel-replacement says:

VK_BORDER_COLOR_INT_OPAQUE_WHITE B=(1,1,1,1)

Shouldn't the "1" actually be "2^{number of bits in the integer component type}-1", or "the maximum representable positive integer value" or something? Otherwise, how does it ever get converted into the same numeric range as any non-normalized integer memory reads that went through the "Format Conversion" steps?

(It feels like there's probably something obvious that I'm missing here...)

Same with the "one=1 for integer formats and stencil aspects" in "Conversion to RGBA".

Same with the "one=1 for integer components" in "Component Swizzle".

Same with the "VK_COMPONENT_SWIZZLE_ONE: the component is set to either 1 or 1.0" in "Image Views".

Unclear if a device should advertise support for rendering to a desktop rendered by another device

On some systems there can be several cards available.

Examples are:
. Crossfire/SLI configurations: one of the cards is connected to the display and renders the desktop
. Laptops: iGPU renders the desktop and is connected to the display OR dGPU renders the desktop and iGPU is used to communicate the rendered content to the display.

With GL, rendering to another device than the one used to render the desktop implies some hidden operations (allocation of buffer both devices can understand in some shared memory, potentially some hidden copies, etc).

Current WSI spec of vkGetPhysicalDeviceSurfaceSupportKHR doesn't specify if the cards not used for the rendering of the desktop should advertise support or not.

Both not advertising support and supporting but with some hidden operations seem allowed by the current spec. Could it be clarified ?

I believe it is important to specify it.

  1. If only the device used for desktop rendering is allowed to advertise support, then apps would have to iterate over the devices to find the one supporting the surface (And I guess with some future extension it will be possible to render with other devices and share buffers such that you could present with the device supporting rendering to the surface).

  2. If all devices are allowed to advertise support, it seems rather difficult for the apps to pick one, and it may result in suboptimal choice.

I guess the behaviour is linked to the -likely being written- extension to share data accross devices, and my guess is that 1) implies that the work done to render to a different gpu than the desktop will have to be done by the app, whereas 2) will hide that in the driver.
I prefer 1) personally.

Freeing memory that is mapped

As far as I can see there's no spec language that says memory which is mapped with vkMapMemory must then be unmapped with vkUnmapMemory before it is freed with vkFreeMemory.

Is this valid behaviour that unmap is optional if the memory is freed?

2.1. Execution Model, typo "device local" mentioned twice

The following paragraph has "device local" mentioned twice, it may need to be stricken or changed.

Examples of memory areas that may be available on an implementation include device local (memory that is physically connected to the device), device local, host visible (device local memory that is visible to the host) and host local, host visible (memory that is local to the host and visible to the device and host). On other architectures, there may only be a single heap that can be used for any purpose.

Misleading naming of section 5.2 (Command Buffer Lifetime)

Using a word "Lifetime" in naming of section 5.2 (Command Buffer Lifetime) is a bit misleading. The word "Lifetime" is better suitable for the cases when there are some kind of implicit rules for the period during which something is functional (e.g. objects and object names lifetime in OpenGL). In a case of section 5.2 of Vulkan specification there are no such implicit rules and section actually just describe the creation/destruction functions for Command Buffers.

Omit "optional" parameters from some API functions

Some functions are documented for this application programming interface in the way that a pointer can be passed. Some of these pointers can also be also be null as a regular value.

I imagine that null pointers will be passed often enough for a parameter like "VkAllocationCallbacks" so that it would make sense to provide functions which omit such an input value in their signature.
Will a reduced API variant be useful for less data transfer traffic in some use cases?

Implicit location assignment in blocks

https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#interfaces-iointerfaces-locations says:

If it is a Block with a Location decoration, then its first member is assigned to the location specified for the Block, any member with its own Location decoration is assigned that location, and otherwise each subsequent member is assigned consecutive locations in declaration order.

This seems ambiguous.

If the first member has its own Location decoration (which might differ from the block's Location), which rule applies?

Also, what specifically does "consecutive" mean? E.g. if I have something in pseudo-GLSL like:

layout(location = 0) in blk {
  vec4 a;
  layout(location = 4) vec4 b;
  vec4 c;
};

and pretend that it gets compiled to:

         Decorate 8(blk) Block
         Decorate 8(blk) Location 0
         MemberDecorate 8(blk) 1 Location 4
8(blk):  TypeStruct 7(fvec4) 7(fvec4) 7(fvec4)

then would the third member be given location 1 (the next in the sequence of implicitly-assigned locations after the first member was given 0), or location 5 (the next after the previous member's location), or location 42 (it just needs to be consecutive with all other members that aren't first and don't have an explicit Location, and since it's the only such member that means it can be any arbitrary location)?

Ref page stubs need to be filled in with actual content

Vulkan as an API depends as much on struct documentation as it does function and enumerator docs. Every API function which has a unique Info struct for it does have documentation for that struct in its own documentation page. However, structs that are not bound to a particular function don't seem to be present.

For example, VkPipelineShaderStageCreateInfo. This data structure is used by several functions. And vkCreateRenderingPipelines does try to link to the definition of this struct. But it isn't anywhere, either in the individual files or the amalgam HTML document. This is a pretty big hole in the reference docs, and that struct is far from the only one.

C99 designated intializers

Since you made the excellent choice of basing Vulkan on C99, why not use its very useful syntax when instantiating structs? For example, this code sample from the specifications:

const VkSpecializationMapEntry entries[] =
{
    {
        0,                    // constantID
        0 * sizeof(int32_t),  // offset
        sizeof(int32_t)       // size
    },
    {
        12,                   // constantID
        1 * sizeof(int32_t),  // offset
        sizeof(float)         // size
    }
};

can be written as:

const VkSpecializationMapEntry entries[] =
{
    [0] = {
        .constantId = 0,
        .offset     = 0 * sizeof(int32_t),
        .size       = sizeof(int32_t),
    },
    [1] = {
        .constantId = 12,
        .offset     = 1 * sizeof(int32_t),
        .size       = sizeof(float)
    }
};

This not only makes the comments unnecessary, but is also future proof, in the sense that now you don't require the struct to actually contain the elements in that order. Overall, this is a safer way to initialize a struct. (I added [x] = as well for array initialization because it made sense in the context of where this code sample was introduced, but I'm mainly commenting on the struct initialization).

XML misc enum issues

The following section of vk.xml has some issues if one was wanting to use the file to generate a binding for non C/C++ languages. Because the language target may not support it properly. Also technically it seems the LL extended literals came with C99 and C++11 so this could be an issue even with the target language if you have some odd compiler maybe and you want to use C++03 and C89? Not certain on that though.

Plus its just weird that these values would need to be computed in C99/C++11 and up to get the proper value for them....

<enums name="API Constants" comment="Misc. hardcoded constants - not an enumerated type">
        <!-- This is part of the header boilerplate -->
    <enum value="256"   name="VK_MAX_PHYSICAL_DEVICE_NAME_SIZE"/>
    <enum value="16"    name="VK_UUID_SIZE"/>
    <enum value="256"   name="VK_MAX_EXTENSION_NAME_SIZE"/>
    <enum value="256"   name="VK_MAX_DESCRIPTION_SIZE"/>
    <enum value="32"    name="VK_MAX_MEMORY_TYPES"/>
    <enum value="16"    name="VK_MAX_MEMORY_HEAPS"/> <!-- The maximum number of unique memory heaps, each of which supporting 1 or more memory types. -->
    <enum value="1000.0f" name="VK_LOD_CLAMP_NONE"/>
    <enum value="(~0U)" name="VK_REMAINING_MIP_LEVELS"/>
    <enum value="(~0U)" name="VK_REMAINING_ARRAY_LAYERS"/>
    <enum value="(~0ULL)" name="VK_WHOLE_SIZE"/>
    <enum value="(~0U)" name="VK_ATTACHMENT_UNUSED"/>
    <enum value="1"     name="VK_TRUE"/>
    <enum value="0"     name="VK_FALSE"/>
    <enum value="(~0U)" name="VK_QUEUE_FAMILY_IGNORED"/>
    <enum value="(~0U)" name="VK_SUBPASS_EXTERNAL"/>
</enums>

Editorial issues (sections 1-6)

There's a few minor editorial things I noticed on reading the first part of the spec. Section numbers are based on https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html

Section 2.1.1

"Command buffers submitted to a single queue play back the commands in the order they were recorded, both within and across command buffer boundaries."

That sounds like it's suggesting that if I record commands in command buffer A, then record in command buffer B, and then submit B then A, it'll "play back the commands" in the recording order A B instead.

I suspect it's more accurate to say they're only played back in the order they were recorded within command buffer boundaries, and they're played back across command buffer boundaries in the order the command buffers were submitted (...except for secondary command buffers which make it even harder to summarise).

Section 2.2

"Each object of a dispatchable type has a unique handle value."

Might be clearer to say it has "a unique handle value during its lifetime.", because two different objects whose lifetimes don't overlap could presumably end up with the same value by chance.

"Objects of a non-dispatchable type may not have unique handle values within a type or across types."

The "may not" is formatted like an RFC 2119 term, but it's not defined by RFC 2119 or by the Terminology section. With the lack of a precise definition it's a confusing term, because "may not" often means "must not" in normal English, implying that it's not permitted to have unique values. Only the "may" should be the RFC 2119 term here (like "may: not have unique handle values" or perhaps "may: have non-unique handle values").

There are quite a few other occurrences of 'maynot:' in the source, they should all be fixed.

Section 2.2.1

"except when the parent is explicitly defined to free its children when it is destroyed (i.e. for pool objects, as defined below)."

I think that should be "e.g.", not "i.e.", because it's not the only case where that exception applies - e.g. it also applies in the VkQueue/VkDevice and VkPhysicalDevice/VkInstance cases.

Section 2.5.1

"A value is valid for an enumerant if: [...] The value is not one of the special values defined for an enumerant type, which are suffixed with _BEGIN_RANGE, _END_RANGE, _RANGE_SIZE or _MAX_ENUM."

That's saying that e.g. VK_STRUCTURE_TYPE_APPLICATION_INFO is never valid, because its value (0) is also VK_STRUCTURE_TYPE_BEGIN_RANGE.

This should be clearer that a value is valid if it's defined as part of the enumerant type, by a definition which is not one of those special definitions. (The specialness of the definition is important, not the specialness of the value.)

Section 3.1

"In order to support systems with multiple Vulkan implementations comprising heterogenous collections of hardware and software"

Should be "heterogeneous".

Section 4.1

  • If pPhysicalDevices is NULL, [...]. If pPhysicalDevices is not NULL,
  • pPhysicalDeviceCount must point to [...].

Looks like the bullet point is in the wrong place, it should be just before the "If pPhysicalDevices is not NULL," instead of just after.

"pPhysicalDeviceCount must point to a variable set by the user to the size of the array pointed to by pPhysicalDevices"

What is the size of an array? The number of elements, or the number of bytes?

"deviceName is a pointer to a null-terminated UTF-8 string containing the name of the device."

It's not a pointer, it's an array.

Section 5.2

"+ If flags includes VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT, [...]"

Unexpected "+" at start of line.

Section 5.4

"Any given element of pCommandBuffers must either have been recorded with the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, or not currently be executing on the device"

The VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT is in the wrong font.

There's also a lot of inconsistency in that section (and elsewhere in the document), e.g. VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT is non-italic while VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT is italic, even though they're both enum things. It's a bit awkward when reading since the typographical difference makes me think there might be some semantic difference, and I have to think a bit harder to realise there isn't.

Section 6.1

It's not clear to me if calling vkResetFences on an unsignaled fence is permitted - I suspect it is, but it doesn't fit the "after a queue submission completes" condition. It would be nice for the spec to be more explicit.

Section 6.6

"Host writes to mappable device memory that occured before the call [...]"

Typo, should be "occurred".

VkAllocationCallbacks application requirements

Section 10.1 (Host Memory) says:

An allocator indicates an error condition by returning NULL from pfnAllocation or pfnReallocation. If this occurs, the implementation should treat it as a run time error [...]

and:

pfnAllocation must either return NULL (in case of allocation failure or if size is zero) or a valid pointer [...]

If size is zero, the second statement indicates it's okay (and required) for the application to return NULL, but the first statement indicates the NULL return should always be treated as an error, which is inconsistent.

The "must" requirement to return NULL if size is zero also means that C's malloc() (or posix_memalign etc for alignment) is not an acceptable implementation of pfnAllocation, because malloc(0) may simply act as if the size is non-zero and return a non-NULL pointer (which the caller must later free()). I'm not sure if that's an intentional difference - it seems unnecessary and surprising.

The return value of pfnReallocation with pOriginal != NULL, size == 0 also seems unclear. It "must behave similarly to PFN_vkFreeFunction" but that doesn't have a return value. Is it allowed or required or forbidden to return NULL? (In C, realloc(p, 0) may return NULL but is not required to.)

I think it'd be better to follow C's malloc/realloc/free semantics exactly, given that many applications will probably want to simply call standard malloc/realloc/free-like functions with a bit of tracking code around them.

Also:

pfnReallocation must alter the size of the allocation pOriginal, either by shrinking or growing it, to accommodate the new size.

If the application uses an arena allocator, it can't shrink or free an allocation, so the most efficient thing it can do when asked to reallocate smaller is to return the original pointer and not modify any internal state at all. That's a perfectly sensible thing to do, but it would clearly violate this requirement, so it seems a bad requirement.

(And if I was being pedantic, a standard realloc() returning an entirely new pointer is not really "alter[ing] the size of allocation pOriginal" either.)

It would probably be better to say something like: "If pOriginal is not NULL, and size is not zero, then pfnReallocation must return a valid pointer to a memory allocation of at least size bytes, which may be the same pointer as pOriginal or may be a different pointer". Don't try to prescribe how the function chooses such a pointer.

Similar for the "must be freed by the function" in pfnFree. If the application wants to implement pfnFree as a noop, and just free an entire scope's allocations in one go later on, it sounds like it'd be violating that requirement.

Passing only one allocation callback configuration for each API item

I find that information like the following will need further considerations.

…
If VkAllocationCallbacks were provided when instance was created,
a compatible set of callbacks must be provided here.
…

I guess that my knowledge is insufficient here to express exact compatibility requirements safely for the involved interfaces. But I imagine that something can be achieved in this direction if a specific software design will ensure that the same allocation callback configuration would be passed to the initialisation and finalisation function of the affected API item.
I suggest to consider the introduction of the following function pattern where another callback function will be passed for the desired work execution.

typedef
VkResult
(VKAPI_PTR* vkWorkOnItem)(VkItem* Item);
typedef
VkResult
(VKAPI_PTR* vkWorkOnItemWithUserData)
(VkItem* Item,
 void* UserData);

VkResult
vkPerformWorkItem(vkWorkOnItem WorkCallback,
                  VkAllocationCallbacks const* Allocator);
VkResult
vkPerformWorkItemWithUserData(vkWorkOnItemWithUserData WorkCallback,
                              VkAllocationCallbacks* Allocator);
…

VkCopyDescriptorSet with srcSet == dstSet

In Section 13.2.4 (Descriptor Set Updates), VkCopyDescriptorSet is defined as copying descriptors from one set to another.

What happens if srcSet == dstSet? Is it like memcpy where only non-overlapping ranges are okay, or like memmove where overlapping ranges are okay, or is it not okay at all? The behaviour or restrictions should be specified.

VK_KHR_swapchain specification missing from XHTML and PDF

Core specs define function signatures, and describe the structures consumed by the functions. These extensions don't - they mention the existence of the methods and structures and include examples of use, but don't provide explanation of the parameters and fields. I can infer and guess at them from the demo files in the SDK and some of the issues in the extension, but it'd be nice to have something more formal that matches the core spec.

Moving some information from "Valid Usage" to field or function parameter descriptions

I skimmed the current application programming interface specification to some degree. Now I wonder about the usefulness of information which is provided in sections like "Valid Usage".

I find that several descriptions there should belong to the explanation of data structure members or function parameters directly.

  • How do you think about any more fine-tuning around involved data type constraints?
  • Would you like to reduce the presentation of duplicate information?

vulkan.h : VkPipelineCacheHeaderVersion enumeration

Hi !
at Vulkan.h header file we have the following enumeration:
///////////////////////////////////////////////////////
typedef enum VkPipelineCacheHeaderVersion {
VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1,
VK_PIPELINE_CACHE_HEADER_VERSION_BEGIN_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE,
VK_PIPELINE_CACHE_HEADER_VERSION_END_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE,
VK_PIPELINE_CACHE_HEADER_VERSION_RANGE_SIZE = (VK_PIPELINE_CACHE_HEADER_VERSION_ONE - VK_PIPELINE_CACHE_HEADER_VERSION_ONE + 1),
VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF
} VkPipelineCacheHeaderVersion;
////////////////////////////////////////////////

Note that
VK_PIPELINE_CACHE_HEADER_VERSION_RANGE_SIZE
should be defined as

(VK_PIPELINE_CACHE_HEADER_VERSION_BEGIN_RANGE - VK_PIPELINE_CACHE_HEADER_VERSION_END_RANGE + 1)

instead of
(VK_PIPELINE_CACHE_HEADER_VERSION_ONE - VK_PIPELINE_CACHE_HEADER_VERSION_ONE + 1)

Sounds silly, but once fixed, future versions would have only to update VK_PIPELINE_CACHE_HEADER_VERSION_END_RANGE value.

Buffer view sizes

Section 11.2 (Buffer Views) says:

  • range is a size in bytes of the buffer view. If range is equal to VK_WHOLE_SIZE, the range from offset to the end of the buffer is used. If VK_WHOLE_SIZE is used and the remaining size of the buffer is not a multiple of the element size of format, then the nearest smaller multiple is used.
  • [...]
  • The value of range must be greater than 0

So I'm not allowed to create a buffer view with range == 0, but I am allowed to create one with offset == size_of_buffer and range == VK_WHOLE_SIZE which will have size zero. That seems inconsistent - if the implementation is happy to accept an empty buffer view via VK_WHOLE_SIZE, I don't see why it can't accept an explicit size of 0. Or if it's not happy with an empty buffer view, it shouldn't be happy with zero size via VK_WHOLE_SIZE either.

  • If range is not equal to VK_WHOLE_SIZE, the sum of offset and range must be less than or equal to the size of buffer

What happens if offset > size_of_buffer and range == VK_WHOLE_SIZE? I don't see anything restricting it to point inside the buffer.

See also #27 about vkMapMemory which has a similar offset+size interface but with quite different requirements. I think it'd be less confusing if all the similar APIs had similar requirements.

Vulkan Specification lacks certain niceties in PDF format

In the OpenGL specification PDF, you can look at the page header to see exactly what section you are in. The Vulkan PDF seems more like a printout from a web-browser; the header has the name of the document, but not the name of each section on each page. That makes it hard when you link from one area to another to tell exactly where you are.

Also, the bookmarks on the Vulkan PDF lack chapter names. So if you find a section header that says 8.4, you have to count the items in the bookmarks to find out the name of Chapter 8. The OpenGL PDF puts the chapter numbers before the chapter names in the PDF bookmarks.

required values for sType members in vk.xml not in useful form

The sType struct members (and a few others) have xml comments saying they "Should be" or "Must be" some value. Parsing it out of the comment by hand is annoying, particularly when the surrounding text is inconsistent. An attribute on the member would be much more useful.

Typo: Constants Documentation for VkMemoryPropertyFlags

It appears that the documentation page for VkMemoryPropertyFlags incorrectly documents the following enumerations for VkMemoryPropertyFlagBits:

  • VK_MEMORY_PROPERTY_DEVICE_ONLY is incorrectly used in place of VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
  • VK_MEMORY_PROPERTY_HOST_NON_COHERENT_BIT is incorrectly used in place of VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
  • VK_MEMORY_PROPERTY_HOST_UNCACHED_BIT is incorrectly used in place of VK_MEMORY_PROPERTY_HOST_CACHED_BIT

The documentation summaries for VK_MEMORY_PROPERTY_HOST_NON_COHERENT_BIT and VK_MEMORY_PROPERTY_HOST_UNCACHED_BIT appear to reflect these names as well.


VkMemoryPropertyFlagBits is defined as the following in /src/vulkan/vulkan.h:

typedef enum VkMemoryPropertyFlagBits {
    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001,
    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002,
    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
    VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
} VkMemoryPropertyFlagBits;

These flags are documented in the Constants section of \doc\specs\vulkan\man\VkMemoryPropertyFlags.txt and appear as follows:

ename:VK_MEMORY_PROPERTY_DEVICE_ONLY::
    Unless any other flag is used to enable other uses this constant
    identifies memory that's only accessible by the device.

ename:VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT::
    Identifies a memory pool that can be mapped into host memory address
    space and thus is accessible by the host.

ename:VK_MEMORY_PROPERTY_HOST_NON_COHERENT_BIT::
    Identifies a memory pool where accesses beteen the host and the
    coherency domain are not conherent. Memory with this property needs
    explicit use of flink:vkFlushMappedMemoryRanges after host writes to
    this type of memory, and use of flink:vkInvalidateMappedMemoryRanges
    before host reads from that memory.

ename:VK_MEMORY_PROPERTY_HOST_UNCACHED_BIT::
    Identifies memory that is not cached by the host.

ename:VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT::
    Identifies memory where an object's backing may be provided lazily
    (when needed) by the implementation.

Float/int aliasing in code sample for section 9.7

Another few trivial things. Section numbers are based on https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html

7.1

During a renderpass instance, input/color attachments [...]

Should be "render pass".

7.4

The subpasses indices for a render pass begin at zero when vkCmdBeginRenderPass is recorded, and increments each time vkCmdNextSubpass is recorded.

Inconsistent pluralisation ("indices begin ... and increments").

"subpasses indices" sounds really awkward too, I think "subpass indices" would be better English.

8.9

With few exceptions, fragment shaders do not have access to any data associated with other fragments and is considered to execute in isolation of fragment shader invocations associated with other fragments.

Inconsistent pluralisation ("fragment shaders do not ... and is considered ...").

9.1

VK_SHADER_STAGE_ALL_GRAPHICS = 0x1F,

All other enum values are defined with 8 digits, so this should be 0x0000001F.

9.2

  • The value of stageCount must be greater than 0
  • [...]
  • stageCount must be greater than or equal to 1

Redundant requirements.

9.6

The contents and size of the pipeline cache objects is managed by the implementation.

Should be "are", not "is".

The details of the merge operation are implementation dependent, but implementations are recommended: to merge the contents of the specified pipelines and prune duplicate entries.

I guess the "recommended:" is meant to be an RFC 2119 term, but it's not formatted properly in the HTML and its colon is visible.

This field is a VkPipelineCacheHeaderVersion value.

VkPipelineCacheHeaderVersion is not defined anywhere in the document.

9.7

VkSpecializationMapEntry entries[2];
const VkSpecializationMapEntry entries[] =

Duplicate definition.

((float*)data)[1] = 42.0f;

I think that's undefined behaviour in C. It'd be more correct to do "float f = 42.0f; memcpy(&data[1], &f, sizeof(float))", or easier to just define a "struct { int a; float b; } data" instead of an incorrectly-typed array.

(I think having code samples in the spec is generally a good thing, to help clarify the prose, but it ought to be valid code in case people are tempted to copy-and-paste it into their applications.)

A wiki, lower entry barrier and API stability

Migrated from KhronosGroup/Vulkan-LoaderAndValidationLayers#5:

Vulkan has the potential to become the most popular graphics API, but:

  • I hope, in order to minimize the complexity, boilerplate libraries will emerge and provide abstraction layers fitting for different applications. Some of those should probably be officially supported/listed.

    Only then, those small hobby projects will have a chance to use Vulkan and developers get familiar with it. Just targetting AAA engines will lead to having very few developers that use and understand the API which makes it popular.

  • In order to prevent totally outdated guides and scattering the community, a central wiki should be in place from the beginning. There, howtos, examples, tutorials and tipps & tricks should be placed and maintained.

  • After programs have been written, they will most likely not be updated for new Vulkan versions. Although that was never the problem with e.g. OpenGL, I can only hope Vulkan won't do things like the Python2->3 breakage, qt3->4->5, gtk2->3, gnome2->3, kde4->5, etc.
    Instead, following the Linux kernel way will guarantee ABI stability for a minimalistic interface that provides space for internal improvements and reliably sane behavior.

If the interface remains stable and the community is actively integrated and supported into further evolvement of Vulkan and not only industry giants, the success is probably guaranteed.

Thanks for making all this possible 😄

(and please, use better/shorter repo names: "Vulkan-LoaderAndValidationLayers" ...)

Change the way out parameters are defined.

The creation, allocation and capability-query functions use out parameters to return the created/allocated object (and the actual return value for errors). However not all languages support this and automatically mapping the pointer arguments to return values can be tricky.

Instead marking them explicitly will make it clearer where the result goes.

        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_LAYER_NOT_PRESENT,VK_ERROR_EXTENSION_NOT_PRESENT,VK_ERROR_INCOMPATIBLE_DRIVER">
            <proto><type>VkResult</type> <name>vkCreateInstance</name></proto>
            <param>const <type>VkInstanceCreateInfo</type>* <name>pCreateInfo</name></param>
            <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
            <param out="true"><type>VkInstance</type>* <name>pInstance</name></param>
        </command>
        <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED">
            <proto><type>VkResult</type> <name>vkEnumeratePhysicalDevices</name></proto>
            <param><type>VkInstance</type> <name>instance</name></param>
            <param optional="false,true" out="true"><type>uint32_t</type>* <name>pPhysicalDeviceCount</name></param>
            <param optional="true" len="pPhysicalDeviceCount" out="true"><type>VkPhysicalDevice</type>* <name>pPhysicalDevices</name></param>
        </command>

FragDepth for discarded fragments

https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#interfaces-builtin-variables says:

That is, if the fragment shader enables depth replacing, then it must always write it.

That sounds like it applies even if the fragment shader uses OpKill to discard the fragment. Should it really be required to write to FragDepth in that case?

I guess a similar problem applies if the shader modifies SampleMask so that it doesn't cover any samples - it shouldn't need FragDepth in that case either.

It might be sufficient to simply remove that sentence - the previous sentence already says the depth is undefined on code paths that don't write it, and it seems obvious that a non-discarded fragment/sample mustn't use an undefined depth but a discarded one may.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.