KhronosGroup / Vulkan-Docs

The Vulkan API Specification and related tools
Other
2.8k stars 467 forks source link

Enumerant validity rules seem incorrect #2077

Open krOoze opened 1 year ago

krOoze commented 1 year ago

1

Any parameter of an enumerated type must be a valid enumerant for that type.

Sentence feels confusing. Probably means "any argument". Even so the sentence feels weirdly formed; it misses verbs or something and partly redundant to the next sentence, and the "of that type" seem partly redundant to the first bullet point.


2

Rules do not cover functions without dispatchable handle, such as vkCreateInstance. This impacts use of VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR, enumerants usable in the pNext chain, and potential new enumerants in the VkAllocationCallbacks structure.


3

suffixed with _MAX_ENUM¹.

The "¹" points nowhere now.


4

it was added by a core version that is supported (as reported by vkEnumerateInstanceVersion)

That is slightly incorrect. Many enumerants were added by core version 1.0, and such version cannot be queried by vkEnumerateInstanceVersion. There seem to be a Querying Version Support chapter, so I suggest linking to that, and improving that chapter.


5

If the enumerant is used in a function that has a VkPhysicalDevice object as its first parameter

This seem incorrect for vkCreateDevice (something like #1540).

BTW, I think functions in Vulkan are generally called "commands".


6

it was added by a core version that is supported by that device (as reported by VkPhysicalDeviceProperties::apiVersion);

missing "or"

It seems insufficient, and contradictory to the Valid Usage for Newer Core Versions, which says:

Physical-device-level functionality or behavior added by a new core version of the API must not be used unless it is supported by the physical device as determined by VkPhysicalDeviceProperties::apiVersion and the specified version of VkApplicationInfo::apiVersion.


7

it was added by an instance extension that was enabled for the instance; or

Probably should be explicit which "the instance".


8

it was added by a device extension that is supported by that device.

Should say "physical device".

This seems incompatible with Vulkan 1.0 without VK_KHR_get_physical_device_properties2, which only permit use of enumerants added by instance extensions. Not sure if all extensions list these as dependency. Hypothetically, there could be an extension where use of its physical-device level commands is non-essential, therefore it does not list these dependencies.


9

If the enumerant is used in a function that has any other dispatchable object as its first parameter and either:

Brittle in case there is ever an instance-level handle added.


10

it was added by a core version that is supported for the device (as reported by VkPhysicalDeviceProperties::apiVersion); or

same as 6


11

it was added by a device extension that was enabled for the device.

Should say which device, similarly to 7. Since we have not even mentioned any device earlier, there is no "the device".


12

Any enumerated type returned from a query command or otherwise output from Vulkan to the application must not have a reserved value. Reserved values are values not defined by any extension for that enumerated type.

This is slightly confusing, since enumerants are being added all the time. It is not clear which values exactly are reserved at any given time. Based on the latest publicly released spec? Or in the patch version the driver reports (if it reports it)?


Most of it feels highly repetitive, and I feel the Valid Usage for Extensions and Valid Usage for Newer Core Versions sections should do the heavy lifting here. The same rules will apply for all the other non-enum entities too.

Tobski commented 1 year ago
  1. I'm just going to delete this sentence, it doesn't really add anything, and is technically incorrect for places in the spec where an enum parameter might be ignored.
  2. This was a deliberate choice - there's no global functions that include an enum, and none are expected to be added. We can add this in if we ever add such a function.
  3. Yea that was a leftover from prior to the change, this was already being removed by an unrelated change, but I'll pull it out as part of the fix for this.
  4. That section is borderline pointless; instead I'll add a thing to the version function stating that if it's not supported by the implementation then you've got Vulkan 1.0. I think that's probably useful for other reasons anyway.
  5. We should really get around to fixing #1540, but I don't want to make a point fix here in lieu of that. As for "command" we're incredibly inconsistent about this; so I'm not going to switch it right now. IIRC "command" was originally only meant to be vkCmd* calls - we should make a determination somewhere and update the spec for consistency, but not as part of this change.
  6. The or is deliberately omitted - it's meant to be like a standard sentence construction just broken up by bullets - i.e. "either A, B, or C". As for the correctness issue, yea I missed that this is bounded by the api version - will fix.
  7. I'll update to "the current instance", I don't think we need more detail here than that?
  8. I'll add "physical" and put gpdp2/vk1.1 ifdefs around this part. For completeness I shall extend this to say that 1.1 or gpdp2 must be supported/enabled, because technically there is a weird interaction here if you have Vulkan 1.0 and don't enable gpdp2 at instance creation.
  9. Incredibly unlikely (would break so much) but I'll clarify that it's objects created from a device.
  10. Yup, will fix.
  11. Will update to "current device", not planning to elaborate further.
  12. To be honest, I left this alone when I made the change for the rest of this, because I wasn't sure what to make of it. Might be best to just remove these two sentences to be honest.

Finally:

Most of it feels highly repetitive, and I feel the Valid Usage for Extensions and Valid Usage for Newer Core Versions sections should do the heavy lifting here. The same rules will apply for all the other non-enum entities too.

Yea I made the same observation - there's a couple reasons I didn't go down that route though. 1 is that although there's a lot of overlap with other versioned parts, there are actual differences in a handful of cases that are in the minutaie. Trying to tease that out is a pain without writing them down independently first. The other more immediately practical reason is that I didn't want to have to rewrite that entire section as part of this very deliberately more targeted change. A rewrite of that section isn't off the table, it's just not a priority for now.

I'll raise a PR for all of this so you can see what it looks like.

krOoze commented 1 year ago

ad 2: There is: vkCreateInstance is a global function that uses VkInstanceCreateFlags (and flags validity refers to enum validity), it has VkAllocationCallbacks which has VkSystemAllocationScope and VkInternalAllocationType enums, and it can have myriad of things in pNext.

ad 4: That would be nice, but does not technically fix it. Nothing can be "reported via vkEnumerateInstanceVersion" if the function does not exist, and the link would probably be dead in 1.0 spec.

ad 6: Yea ok, but still couldn't hurt to explicitly say "or" even if there are 3+ items. As it is it could be incorrectly read as "(sentence A, and sentence B), or sentence C)".

ad 7: IDK, this is not OpenGL; there is no "current instance". While this case is not unclear it is about the mindset\language-style when writing a specification. I would let it go if the alternative was particularly burdensome, but this just needs "the instance parent of the physical device"

ad 11: Same, except "the device implied by the dispatchable parameter"

ad 12: Yea, I would be perfectly happy if it said in can return anything (except probably *_MAX_ENUM, although I would leave even this open coz the whole 31 bit enum situation is dumb and one day could perhaps be resolved). A guarantee where I am not sure what I am being guaranteed precisely is pointless to me...

BTW there seems to be a Note refering to this below. But the note seem confused. It seems to me primarily a matter of whether the driver should bother filtering out outputs from non-enabled extensions or not, given the app can just ignore things it does not understand. Unlike what the Note communicates: Layers can generally act outside the spec (though should not unless it is in their contract with the user), and if driver has "hidden extensions" (whatever that means), then such implementation details should be opaque to users.

1 is that although there's a lot of overlap with other versioned parts, there are actual differences in a handful of cases that are in the minutaie.

I am not really cognizant of any (so duplicating this language probably does not do its job to emphasize the diffs). What are those differences over, say, structs?