Change log for March 18, 2019 Vulkan 1.1.104 spec update:

* Update release number to 104.

Public Issues:

  * Remove the incorrect line from "`Initial`" to "`Invalid`" state in the
    <<commandbuffer-lifecycle-diagram, Lifecycle of a command buffer>>
    diagram (public issue 881).
  * Add Fuchsia platform to <<boilerplate-wsi-header-table, Window System
    Extensions and Headers>> table (public pull request 933).
  * Change the type of
    slink:VkBufferDeviceAddressCreateInfoEXT::pname:deviceAddress from
    basetype:VkDeviceSize to basetype:VkDeviceAddress. These are both
    typedefs of code:uint64_t, so it is an ABI-compatible change (public
    issue 934).

Internal Issues:

  * Remove generated header files and update the CI tests to build a copy of
    the headers for use by the hpp-generate / hpp-compile CI stages. Targets
    to generate the headers will not be removed, but keeping these generated
    files in the repository increased the frequency of conflicts between
    branches when merging to master (internal issue 745).
  * Reword "`undefined: behavior if *action*" to "`must: not do *action*`"
    in the places the old terminology was used, and add a new
    <<writing-undefined, Describing Undefined Behavior>> section of the
    style guide to explain how to write such language in the future
    (internal issue 1579).
  * Move almost all Python scripts into the toplevel `scripts/` directory.
    Apply extensive internal edits to clean up and simplify the scripts, and
    try to follow PEP8 guidelines. Generalize the scripts with the use of a
    Conventions object controlling many aspects of output generation, to
    enable their use in other Khronos projects with similar requirements.
    Autogenerate extension interface refpages (these are experimental and
    may be retired going forward).

New Extensions:

  * `VK_AMD_display_native_hdr`
  * `VK_EXT_full_screen_exclusive` (internal issue 1439)
  * `VK_EXT_host_query_reset`
  * `VK_EXT_pipeline_creation_feedback` (internal issue 1560)
  * `VK_KHR_surface_protected_capabilities` (internal issue 1520)
This commit is contained in:
Jon Leech 2019-03-17 06:05:46 -07:00
parent 8cc971fb3e
commit 476e3f422d
98 changed files with 4108 additions and 12080 deletions

View File

@ -5,7 +5,7 @@ spec-generate:
stage: build
before_script:
- apt-get update -qq
- apt-get install -y -qq gcc git python3 python3-termcolor python3-pytest ruby
- apt-get install -y -qq gcc git python3 python3-termcolor python3-pytest ruby jing
- apt-get install -y -qq cmake bison flex libffi-dev libxml2-dev libgdk-pixbuf2.0-dev libcairo2-dev libpango1.0-dev ttf-lyx
# Force-install an older version of i18n so the 1.5.2 version, which
# won't work with ruby 2.1, doesn't abort the CI job when installing
@ -14,17 +14,19 @@ spec-generate:
- gem install asciidoctor asciidoctor-mathematical coderay json-schema
script:
# Internal self-test of the check_spec_links script
- ( cd xml && py.test-3 )
- ( cd scripts && py.test-3 test*.py )
- mkdir -p out/checks
- xml/check_spec_links.py --html=out/checks/problems.html > /dev/null || true
- scripts/check_spec_links.py --html=out/checks/problems.html > /dev/null || true
# Breaking the build if # of errors increases. We should manually ratchet ignore_count down as errors get fixed.
# If there are unfixable errors, add '--ignore_count #' where '#' is the
# number of them. This is a slightly crude way of enforcing "don't add
# errors" but simpler than the alternatives (running against master,
# diff, etc)
- xml/check_spec_links.py -Werror --ignore_count 0
- scripts/check_spec_links.py -Werror --ignore_count 0
# Build the actual spec
- ./makeAllExts QUIET= -j${nproc} -Otarget checkinc checklinks validusage html styleguide registry manhtmlpages
- ./makeAllExts QUIET= -j${nproc} -Otarget validusage html styleguide registry manhtmlpages
# Build headers, for use by all later stages
- ( cd xml && make validate test install )
artifacts:
when: always
paths:
@ -48,6 +50,8 @@ hpp-generate:
- git submodule update --init --recursive -- tinyxml2
- rm -rf Vulkan-Docs
- cp -r "${SPEC_DIR}" Vulkan-Docs
# Copy Vulkan C headers into subdir copy used by Vulkan-Hpp
- cp -p ${SPEC_DIR}/include/vulkan/*.h Vulkan-Docs/include/vulkan/
script:
- cd /tmp/Vulkan-Hpp
- cmake -H. -Bbuild

View File

@ -8,6 +8,53 @@ public pull requests that have been accepted.
-----------------------------------------------------
Change log for March 18, 2019 Vulkan 1.1.104 spec update:
* Update release number to 104.
Public Issues:
* Remove the incorrect line from "`Initial`" to "`Invalid`" state in the
<<commandbuffer-lifecycle-diagram, Lifecycle of a command buffer>>
diagram (public issue 881).
* Add Fuchsia platform to <<boilerplate-wsi-header-table, Window System
Extensions and Headers>> table (public pull request 933).
* Change the type of
slink:VkBufferDeviceAddressCreateInfoEXT::pname:deviceAddress from
basetype:VkDeviceSize to basetype:VkDeviceAddress. These are both
typedefs of code:uint64_t, so it is an ABI-compatible change (public
issue 934).
Internal Issues:
* Remove generated header files and update the CI tests to build a copy of
the headers for use by the hpp-generate / hpp-compile CI stages. Targets
to generate the headers will not be removed, but keeping these generated
files in the repository increased the frequency of conflicts between
branches when merging to master (internal issue 745).
* Reword "`undefined: behavior if *action*" to "`must: not do *action*`"
in the places the old terminology was used, and add a new
<<writing-undefined, Describing Undefined Behavior>> section of the
style guide to explain how to write such language in the future
(internal issue 1579).
* Move almost all Python scripts into the toplevel `scripts/` directory.
Apply extensive internal edits to clean up and simplify the scripts, and
try to follow PEP8 guidelines. Generalize the scripts with the use of a
Conventions object controlling many aspects of output generation, to
enable their use in other Khronos projects with similar requirements.
Autogenerate extension interface refpages (these are experimental and
may be retired going forward).
New Extensions:
* `VK_AMD_display_native_hdr`
* `VK_EXT_full_screen_exclusive` (internal issue 1439)
* `VK_EXT_host_query_reset`
* `VK_EXT_pipeline_creation_feedback` (internal issue 1560)
* `VK_KHR_surface_protected_capabilities` (internal issue 1520)
-----------------------------------------------------
Change log for March 11, 2019 Vulkan 1.1.103 spec update:
* Update release number to 103.

View File

@ -85,6 +85,9 @@ CP = cp
ECHO = echo
GS_EXISTS := $(shell command -v gs 2> /dev/null)
# Path to Python scripts used in generation
SCRIPTS = scripts
# Target directories for output files
# HTMLDIR - 'html' target
# PDFDIR - 'pdf' target
@ -115,7 +118,7 @@ VERBOSE =
# ADOCOPTS options for asciidoc->HTML5 output
NOTEOPTS = -a editing-notes -a implementation-guide
PATCHVERSION = 103
PATCHVERSION = 104
ifneq (,$(findstring VK_VERSION_1_1,$(VERSIONS)))
SPECREVISION = 1.1.$(PATCHVERSION)
else
@ -264,7 +267,7 @@ $(OUTDIR)/registry.html: $(REGSRC)
# Reflow text in spec sources
REFLOW = reflow.py
REFLOW = $(SCRIPTS)/reflow.py
REFLOWOPTS = -overwrite
reflow:
@ -290,8 +293,9 @@ clean_checks:
$(QUIET)$(RMRF) $(CHECKDIR)
clean_generated:
$(QUIET)$(RMRF) api/* hostsynctable/* validity/* $(METADIR)/* vkapi.py
$(QUIET)$(RM) config/extDependency.stamp config/extDependency.pyc config/extDependency.sh config/extDependency.py
$(QUIET)$(RMRF) api/* hostsynctable/* validity/* $(METADIR)/*
$(QUIET)$(RMRF) include/vulkan/vulkan_*.h $(SCRIPTS)/vkapi.py
$(QUIET)$(RM) config/extDependency.*
$(QUIET)$(RM) man/apispec.txt $(LOGFILE) man/[Vv][Kk]*.txt man/PFN*.txt
$(QUIET)$(RMRF) $(PDFMATHDIR)
@ -327,9 +331,10 @@ MANCOPYRIGHT = $(MANDIR)/copyright-ccby.txt $(MANDIR)/footer.txt
#
# Should pass in $(EXTOPTIONS) to determine which pages to generate.
# For now, all core and extension ref pages are extracted by genRef.py.
GENREF = $(SCRIPTS)/genRef.py
LOGFILE = man/logfile
man/apispec.txt: $(SPECFILES) genRef.py reflib.py vkapi.py
$(PYTHON) genRef.py -log $(LOGFILE) $(SPECFILES)
man/apispec.txt: $(SPECFILES) $(GENREF) $(SCRIPTS)/reflib.py $(SCRIPTS)/vkapi.py
$(PYTHON) $(GENREF) -log $(LOGFILE) $(SPECFILES)
# These targets are HTML5 ref pages
#
@ -377,53 +382,8 @@ $(OUTDIR)/apispec.html: $(SPECVERSION) man/apispec.txt $(MANCOPYRIGHT) $(SVGFILE
$(QUIET)$(MKDIR) $(OUTDIR)
$(QUIET)$(ASCIIDOC) -b html5 -a html_spec_relative='html/vkspec.html' $(ADOCOPTS) $(ADOCHTMLOPTS) -o $@ man/apispec.txt
# Automated (though heuristic) checks of consistency in the spec and
# ref page sources.
# These are way out of date WRT current spec markup, and probably won't
# work properly.
# Validate includes in spec source vs. includes actually in the tree
# Generates file in $(CHECKDIR)
# $(NOTINSPEC) notInSpec.txt - include files only found in XML, not in spec
# Intermediate files removed after the run
# $(ACTUAL) - include files generated from vk.xml
# $(INSPEC) - include files referenced from the spec (not ref page) source
# Other files which could be generated but are basically useless
# include files only found in the spec source - comm -13 $(ACTUAL) $(INSPEC)
# include files both existing and referenced by the spec - comm -12 $(ACTUAL) $(INSPEC)
INCFILES = $(CHECKDIR)/incfiles
ACTUAL = $(CHECKDIR)/actual
INSPEC = $(CHECKDIR)/inspec
NOTINSPEC = $(CHECKDIR)/notInSpec.txt
checkinc:
$(QUIET)if test ! -d $(CHECKDIR) ; then $(MKDIR) $(CHECKDIR) ; fi
$(QUIET)find api validity hostsynctable -name '*.txt' | sort > $(ACTUAL)
$(QUIET)cat $(SPECFILES) | \
egrep '^include::\.\./' | tr -d '[]' | \
sed -e 's#^include::\.\./##g' | sort > $(INCFILES)
$(QUIET)echo "List of API include files repeatedly included in the API specification" > $(NOTINSPEC)
$(QUIET)echo "----------------------------------------------------------------------" >> $(NOTINSPEC)
$(QUIET)uniq -d $(INCFILES) >> $(NOTINSPEC)
$(QUIET)(echo ; echo "List of API include files not referenced in the API specification") >> $(NOTINSPEC)
$(QUIET)echo "-----------------------------------------------------------------" >> $(NOTINSPEC)
$(QUIET)comm -23 $(ACTUAL) $(INCFILES) >> $(NOTINSPEC)
$(QUIET)echo "Include files not found in the spec source are in $(CHECKDIR)/notInSpec.txt"
$(QUIET)$(RM) $(INCFILES) $(ACTUAL) $(INSPEC)
# Validate link tags in spec and ref page sources against vk.xml
# (represented in vkapi.py, which is autogenerated along with the
# headers and ref page includes).
# Generates files in $(CHECKDIR):
# specErrs.txt - errors & warnings in API spec
# manErrs.txt - errors & warnings in man pages
checklinks: man/apispec.txt generated
$(QUIET)if test ! -d $(CHECKDIR) ; then $(MKDIR) $(CHECKDIR) ; fi
$(QUIET)echo "Generating link checks for spec (specErrs.txt) and man pages (manErrs.txt)"
$(QUIET)$(PYTHON) checkLinks.py -follow $(SPECFILES) > $(CHECKDIR)/specErrs.txt
$(QUIET)$(PYTHON) checkLinks.py -follow man/[Vv][Kk]*.txt > $(CHECKDIR)/manErrs.txt
# Targets generated from the XML and registry processing scripts
# vkapi.py - Python encoding of the registry
# $(SCRIPTS)/vkapi.py - Python encoding of the registry
# api/timeMarker - proxy for 'apiincludes' - API include files under api/*/*.txt
# hostsynctable/timeMarker - proxy for host sync table include files under hostsynctable/*.txt
# validity/timeMarker - proxy for API validity include files under validity/*/*.txt
@ -440,12 +400,12 @@ checklinks: man/apispec.txt generated
REGISTRY = xml
VKXML = $(REGISTRY)/vk.xml
GENVK = $(REGISTRY)/genvk.py
GENVK = $(SCRIPTS)/genvk.py
GENVKOPTS = $(VERSIONOPTIONS) $(EXTOPTIONS) $(GENVKEXTRA) -registry $(VKXML)
GENVKEXTRA =
vkapi.py: $(VKXML) $(GENVK)
$(PYTHON) $(GENVK) $(GENVKOPTS) -o . vkapi.py
$(SCRIPTS)/vkapi.py: $(VKXML) $(GENVK)
$(PYTHON) $(GENVK) $(GENVKOPTS) -o scripts vkapi.py
apiinc: api/timeMarker
@ -475,7 +435,7 @@ $(METADIR)/timeMarker: $(VKXML) $(GENVK)
# This leaves out config/extDependency.sh intentionally as it only
# needs to be updated when the extension dependencies in vk.xml change.
generated: vkapi.py $(GENDEPENDS)
generated: $(SCRIPTS)/vkapi.py $(GENDEPENDS)
# Extension dependencies derived from vk.xml
# Both Bash and Python versions are generated
@ -483,7 +443,7 @@ generated: vkapi.py $(GENDEPENDS)
config/extDependency.sh: config/extDependency.stamp
config/extDependency.py: config/extDependency.stamp
DEPSCRIPT = $(REGISTRY)/extDependency.py
DEPSCRIPT = $(SCRIPTS)/extDependency.py
config/extDependency.stamp: $(VKXML) $(DEPSCRIPT)
$(QUIET)$(PYTHON) $(DEPSCRIPT) -registry $(VKXML) \
-outscript config/extDependency.sh \

View File

@ -8,21 +8,22 @@ This repository contains sources for the formal documentation of the Vulkan
API. This includes:
[options="compact"]
* the Vulkan API Specification
* specification of Vulkan Extensions
* the reference ("`man`") pages
* the XML API Registry (also mirrored at
* The Vulkan API Specification
* Specification of Vulkan extensions
* API reference ("`man`") pages
* The XML API Registry (also mirrored at
https://github.com/KhronosGroup/Vulkan-Headers)
* Vulkan header files (also mirrored at
https://github.com/KhronosGroup/Vulkan-Headers)
* related tools and scripts.
* Related tools and scripts.
The authoritative public repository is located at
https://github.com/KhronosGroup/Vulkan-Docs/.
It hosts public Issue tracker, and accepts patches (Pull Requests) from the
general public.
It hosts a public Issue tracker, and outside developers can file proposed
patches (Pull Requests) against the Specification, subject to approval
by Khronos.
If in doubt where to submit your Issue consult the
If in doubt where to submit your Issue, consult the
https://github.com/KhronosGroup/Vulkan-Ecosystem repo.
@ -32,14 +33,6 @@ Everything is now maintained in the `master` branch of the repository.
From this branch it is possible to generate both Vulkan 1.1 and Vulkan 1.0
Specifications, as well as specifications for any set of Extensions.
[NOTE]
====
Old revisions of the repository maintained the Vulkan 1.0 Specification in
the `1.0` branch, and extensions in the `1.0-VK_EXTENSION_NAME`.
These branches are now **obsolete**, and contain only very old versions of
the Specification (and extensions).
====
== Directory Structure
@ -59,16 +52,12 @@ images/ Images (figures, diagrams, icons)
include/vulkan/ Vulkan headers, generated from the Registry
man/ Reference (man) pages for the API; mostly extracted from the spec source
out/ Default directory for the generated documents
scripts/ Related scripts (but many scripts are still in the root or xml/ directory)
src/ext_loader/ Extension loader library (deprecated)
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) and related scripts
xml/ XML API Registry (vk.xml)
registry.txt Sources for documentation of the vk.xml format
```
This structure was adopted following 1.1.70 spec update.
There may be additional cleanup and simplification in the future.
== Building the Specification and Reference Pages

View File

@ -0,0 +1,62 @@
include::meta/VK_AMD_display_native_hdr.txt[]
*Last Modified Date*::
2018-12-18
*IP Status*::
No known IP claims.
*Contributors*::
- Matthaeus G. Chajdas, AMD
- Aaron Hagan, AMD
- Aric Cyr, AMD
- Timothy Lottes, AMD
- Derrick Owens, AMD
- Daniel Rakos, AMD
This extension introduces the following display native HDR features to
Vulkan:
* A new elink:VkColorSpaceKHR enum for setting the native display
colorspace.
For example, this color space would be set by the swapchain to use the
native color space in Freesync2 displays.
* Local dimming control
=== New Object Types
None.
=== New Enum Constants
* Extending elink:VkStructureType:
** ename:VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD
** ename:VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD
* Extending elink:VkColorSpaceKHR:
** ename:VK_COLOR_SPACE_DISPLAY_NATIVE_AMD
=== New Enums
None.
=== New Structures
* slink:VkDisplayNativeHdrSurfaceCapabilitiesAMD
* slink:VkSwapchainDisplayNativeHdrCreateInfoAMD
=== New Functions
* flink:vkSetLocalDimmingAMD
=== Issues
None.
=== Examples
None.
=== Version History
* Revision 1, 2018-12-18 (Daniel Rakos)
- Initial revision

View File

@ -0,0 +1,139 @@
// Copyright (c) 2018 Khronos Group. This work is licensed under a
// Creative Commons Attribution 4.0 International License; see
// http://creativecommons.org/licenses/by/4.0/
include::meta/VK_EXT_full_screen_exclusive.txt[]
*Last Modified Date*::
2019-03-12
*IP Status*::
No known IP claims.
*Interactions and External Dependencies*::
- Interacts with VK_KHR_device_group, VK_KHR_win32_surface, and Vulkan 1.1
*Contributors*::
- Hans-Kristian Arntzen, ARM
- Slawomir Grajewski, Intel
- Tobias Hector, AMD
- James Jones, NVIDIA
- Daniel Rakos, AMD
- Jeff Juliano, NVIDIA
- Joshua Schnarr, NVIDIA
- Aaron Hagan, AMD
This extension allows applications to set the policy for swapchain creation
and presentation mechanisms relating to full-screen access.
Implementations may be able to acquire exclusive access to a particular
display for an application window that covers the whole screen.
This can increase performance on some systems by bypassing composition,
however it can also result in disruptive or expensive transitions in the
underlying windowing system when a change occurs.
Applications can choose between explicitly disallowing or allowing this
behavior, letting the implementation decide, or managing this mode of
operation directly using the new flink:vkAcquireFullScreenExclusiveModeEXT
and flink:vkReleaseFullScreenExclusiveModeEXT commands.
=== New Enum Constants
* Extending elink:VkResult
** ename:VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT
* Extending elink:VkStructureType
** ename:VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT
** ename:VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT
ifdef::VK_KHR_win32_surface[]
** ename:VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT
endif::VK_KHR_win32_surface[]
=== New Enums
* elink:VkFullScreenExclusiveEXT
=== New Structures
* slink:VkSurfaceFullScreenExclusiveInfoEXT
* slink:VkSurfaceCapabilitiesFullScreenExclusiveEXT
ifdef::VK_KHR_win32_surface[]
* slink:VkSurfaceFullScreenExclusiveWin32InfoEXT
endif::VK_KHR_win32_surface[]
=== New Functions
* flink:vkGetPhysicalDeviceSurfacePresentModes2EXT
* flink:vkGetDeviceGroupSurfacePresentModes2EXT
* flink:vkAcquireFullScreenExclusiveModeEXT
* flink:vkReleaseFullScreenExclusiveModeEXT
=== Issues
1) What should the extension & flag be called?
RESOLVED: VK_EXT_full_screen_exclusive.
Other options considered (prior to the app-controlled mode) were:
* VK_EXT_smooth_fullscreen_transition
* VK_EXT_fullscreen_behavior
* VK_EXT_fullscreen_preference
* VK_EXT_fullscreen_hint
* VK_EXT_fast_fullscreen_transition
* VK_EXT_avoid_fullscreen_exclusive
2) Do we need more than a boolean toggle?
RESOLVED: Yes.
Using an enum with default/allowed/disallowed/app-controlled enables
applications to accept driver default behavior, specifically override it in
either direction without implying the driver is ever required to use
full-screen exclusive mechanisms, or manage this mode explicitly.
3) Should this be a KHR or EXT extension?
RESOLVED: EXT, in order to allow it to be shipped faster.
4) Can the fullscreen hint affect the surface capabilities, and if so,
should the hint also be specified as input when querying the surface
capabilities?
RESOLVED: Yes on both accounts.
While the hint does not guarantee a particular fullscreen mode will be used
when the swapchain is created, it can sometimes imply particular modes will
NOT be used.
If the driver determines that it will opt-out of using a particular mode
based on the policy, and knows it can only support certain capabilities if
that mode is used, it would be confusing at best to the application to
report those capabilities in such cases.
Not allowing implementations to report this state to applications could
result in situations where applications are unable to determine why
swapchain creation fails when they specify certain hint values, which could
result in never- terminating surface creation loops.
5) Should full-screen be one word or two?
RESOLVED: Two words.
"Fullscreen" is not in my dictionary, and web searches did not turn up
definitive proof that it is a colloquially accepted compound word.
Documentation for the corresponding Windows API mechanisms dithers.
The text consistently uses a hyphen, but none-the-less, there is a
SetFullscreenState method in the DXGI swapchain object.
Given this inconclusive external guidance, it is best to adhere to the
Vulkan style guidelines and avoid inventing new compound words.
=== Version History
* Revision 4, 2019-03-12 (Tobias Hector)
- Added application-controlled mode, and related functions
- Tidied up appendix
* Revision 3, 2019-01-03 (James Jones)
- Renamed to VK_EXT_full_screen_exclusive
- Made related adjustments to the tri-state enumerant names.
* Revision 2, 2018-11-27 (James Jones)
- Renamed to VK_KHR_fullscreen_behavior
- Switched from boolean flag to tri-state enum
* Revision 1, 2018-11-06 (James Jones)
- Internal revision

View File

@ -0,0 +1,38 @@
include::meta/VK_EXT_host_query_reset.txt[]
*Last Modified Date*::
2019-03-06
*IP Status*::
No known IP claims.
*Interactions and External Dependencies*::
*Contributors*::
- Bas Nieuwenhuizen, Google
- Jason Ekstrand, Intel
- Jeff Bolz, NVIDIA
- Piers Daniell, NVIDIA
This extension adds a new function to reset queries from the host.
=== New Enum Constants
* Extending elink:VkStructureType:
** ename:VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT
=== New Enums
None.
=== New Structures
* slink:VkPhysicalDeviceHostQueryResetFeaturesEXT
=== New Functions
* flink:vkResetQueryPoolEXT
=== Issues
=== Version History
* Revision 1, 2019-03-12 (Bas Nieuwenhuizen)
- Initial draft

View File

@ -0,0 +1,57 @@
include::meta/VK_EXT_pipeline_creation_feedback.txt[]
*Last Modified Date*::
2019-03-12
*IP Status*::
No known IP claims.
*Contributors*::
- Jean-Francois Roy, Google
- Hai Nguyen, Google
- Andrew Ellem, Google
- Bob Fraser, Google
- Sujeevan Rajayogam, Google
- Jan-Harald Fredriksen, ARM
- Jeff Leger, Qualcomm Technologies, Inc.
- Jeff Bolz, NVIDIA
- Daniel Koch, NVIDIA
- Neil Henning, AMD
This extension adds a mechanism to provide feedback to an application about
pipeline creation, with the specific goal of allowing a feedback loop
between build systems and in-the-field application executions to ensure
effective pipeline caches are shipped to customers.
=== New Object Types
None.
=== New Enum Constants
* Extending elink:VkStructureType:
** ename:VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT
=== New Enums
* elink:VkPipelineCreationFeedbackFlagBitsEXT
=== New Structures
* slink:VkPipelineCreationFeedbackCreateInfoEXT
* slink:VkPipelineCreationFeedbackEXT
=== New Functions
None.
=== Issues
None.
=== Examples
None.
=== Version History
* Revision 1, 2019-03-12 (Jean-Francois Roy)
- Initial revision

View File

@ -0,0 +1,59 @@
include::meta/VK_KHR_surface_protected_capabilities.txt[]
*Last Modified Date*::
2018-12-18
*IP Status*::
No known IP claims.
*Contributors*::
- Sandeep Shinde, NVIDIA
- James Jones, NVIDIA
- Daniel Koch, NVIDIA
This extension extends slink:VkSurfaceCapabilities2KHR, providing
applications a way to query whether swapchains can: be created with the
ename:VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR flag set.
Vulkan 1.1 added (optional) support for protect memory and protected
resources including buffers (ename:VK_BUFFER_CREATE_PROTECTED_BIT), images
(ename:VK_IMAGE_CREATE_PROTECTED_BIT), and swapchains
(ename:VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR).
However, on implementations which support multiple windowing systems, not
all window systems may: be able to provide a protected display path.
This extension provides a way to query if a protected swapchain created for
a surface (and thus a specific windowing system) can: be displayed on
screen.
It extends the existing slink:VkSurfaceCapabilities2KHR structure with a new
slink:VkSurfaceProtectedCapabilitiesKHR structure from which the application
can: obtain information about support for protected swapchain creation
through flink:vkGetPhysicalDeviceSurfaceCapabilities2KHR.
=== New Object Types
None.
=== New Enum Constants
* Extending elink:VkStructureType:
** ename:VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR
=== New Enums
None.
=== New Structures
* slink:VkSurfaceProtectedCapabilitiesKHR
=== New Functions
None.
=== Issues
None.
=== Version History
* Revision 1, 2018-12-18 (Sandeep Shinde, Daniel Koch)
- Internal revisions.

View File

@ -198,11 +198,8 @@ If dname:VK_DEFINE_NON_DISPATCHABLE_HANDLE is already defined when
This allows the application to define a binary-compatible custom handle
which may: provide more type-safety or other features needed by the
application.
Behavior is undefined: if the application defines a non-binary-compatible
handle and may: result in memory corruption or application termination.
Binary compatibility is platform dependent so the application must: be
careful if it overrides the default dname:VK_DEFINE_NON_DISPATCHABLE_HANDLE
definition.
Applications must: not define handles in a way that is not binary compatible
- where binary compatibility is platform dependent.
====
--

View File

@ -87,8 +87,8 @@ which cause a debug report, are:
include::../api/enums/VkDebugReportFlagBitsEXT.txt[]
* ename:VK_DEBUG_REPORT_ERROR_BIT_EXT specifies that an error that may
cause undefined: results, including an application crash.
* ename:VK_DEBUG_REPORT_ERROR_BIT_EXT specifies that the application has
violated a valid usage condition of the specification.
* ename:VK_DEBUG_REPORT_WARNING_BIT_EXT specifies use of Vulkan that may:
expose an app bug.
Such cases may not be immediately harmful, such as a fragment shader

View File

@ -479,8 +479,8 @@ include::../api/enums/VkDebugUtilsMessageSeverityFlagBitsEXT.txt[]
unintended such as using an image whose memory has not been filled.
In general if you see a warning but you know that the behavior is
intended/desired, then simply ignore the warning.
* ename:VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT specifies that an
error that may cause undefined: results, including an application crash.
* ename:VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT specifies that the
application has violated a valid usage condition of the specification.
--

View File

@ -0,0 +1,172 @@
// Copyright (c) 2014-2019 Khronos Group. This work is licensed under a
// Creative Commons Attribution 4.0 International License; see
// http://creativecommons.org/licenses/by/4.0/
// This section is included inside the Pipelines chapter (pipelines.txt)
[[pipelines-creation-feedback]]
== Pipeline Creation Feedback
[open,refpage='VkPipelineCreationFeedbackCreateInfoEXT',desc='Request for feedback about the creation of a pipeline',type='structs',xrefs='VkGraphicsPipelineCreateInfo VkComputePipelineCreateInfo VkRayTracingPipelineCreateInfoNV VkPipelineCreationFeedbackEXT']
--
Feedback about the creation of a particular pipeline object can: be obtained
by including a sname:VkPipelineCreationFeedbackCreateInfoEXT structure in
the pNext chain of slink:VkGraphicsPipelineCreateInfo,
ifdef::VK_NV_ray_tracing[]
slink:VkRayTracingPipelineCreateInfoNV,
endif::VK_NV_ray_tracing[]
or slink:VkComputePipelineCreateInfo.
The sname:VkPipelineCreationFeedbackCreateInfoEXT structure is defined as:
include::../../api/structs/VkPipelineCreationFeedbackCreateInfoEXT.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:pPipelineCreationFeedback is a pointer to a
slink:VkPipelineCreationFeedbackEXT structure.
* pname:pipelineStageCreationFeedbackCount is the number of elements in
pname:pPipelineStageCreationFeedbacks.
* pname:pPipelineStageCreationFeedbacks is an array of size
pname:pipelineStageCreationFeedbackCount of
slink:VkPipelineCreationFeedbackEXT structures.
An implementation should: write pipeline creation feedback to
pname:pPipelineCreationFeedback and may: write pipeline stage creation
feedback to pname:pPipelineStageCreationFeedbacks.
An implementation must: set or clear the
ename:VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT in
slink:VkPipelineCreationFeedbackEXT::pname:flags for
pname:pPipelineCreationFeedback and every element of
pname:pPipelineStageCreationFeedbacks.
[NOTE]
.Note
====
One common scenario for an implementation to skip per-stage feedback is when
ename:VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT
is set in pname:pPipelineCreationFeedback.
====
When chained to
ifdef::VK_NV_ray_tracing[]
slink:VkRayTracingPipelineCreateInfoNV or
endif::VK_NV_ray_tracing[]
slink:VkGraphicsPipelineCreateInfo, the `i` element of
pname:pPipelineStageCreationFeedbacks corresponds to the `i` element of
ifdef::VK_NV_ray_tracing[]
slink:VkRayTracingPipelineCreateInfoNV::pname:pStages or
endif::VK_NV_ray_tracing[]
slink:VkGraphicsPipelineCreateInfo::pname:pStages.
When chained to slink:VkComputePipelineCreateInfo, the first element of
pname:pPipelineStageCreationFeedbacks corresponds to
slink:VkComputePipelineCreateInfo::pname:stage.
.Valid Usage
****
* [[VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02668]]
When chained to slink:VkGraphicsPipelineCreateInfo,
slink:VkPipelineCreationFeedbackEXT::pname:pipelineStageCreationFeedbackCount
must: equal slink:VkGraphicsPipelineCreateInfo::pname:stageCount
* [[VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02669]]
When chained to slink:VkComputePipelineCreateInfo,
slink:VkPipelineCreationFeedbackEXT::pname:pipelineStageCreationFeedbackCount
must: equal 1
ifdef::VK_NV_ray_tracing[]
* [[VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02670]]
When chained to slink:VkRayTracingPipelineCreateInfoNV,
slink:VkPipelineCreationFeedbackEXT::pname:pipelineStageCreationFeedbackCount
must: equal slink:VkRayTracingPipelineCreateInfoNV::pname:stageCount
endif::VK_NV_ray_tracing[]
****
include::../../validity/structs/VkPipelineCreationFeedbackCreateInfoEXT.txt[]
--
[open,refpage='VkPipelineCreationFeedbackEXT',desc='Feedback about the creation of a pipeline or pipeline stage',type='structs',xrefs='VkPipelineCreationFeedbackCreateInfoEXT VkPipelineCreationFeedbackFlagBitsEXT']
--
The sname:VkPipelineCreationFeedbackEXT structure is defined as:
include::../../api/structs/VkPipelineCreationFeedbackEXT.txt[]
* pname:flags is a bitmask of elink:VkPipelineCreationFeedbackFlagBitsEXT
providing feedback about the creation of a pipeline or of a pipeline
stage.
* pname:duration is the duration spent creating a pipeline or pipeline
stage in nanoseconds.
If the ename:VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT is not set in
pname:flags, an implementation must: not set any other bits in pname:flags,
and all other sname:VkPipelineCreationFeedbackEXT data members are
undefined.
include::../../validity/structs/VkPipelineCreationFeedbackEXT.txt[]
--
[open,refpage='VkPipelineCreationFeedbackFlagBitsEXT',desc='Bitmask specifying pipeline or pipeline stage creation feedback',type='enums',xrefs='VkPipelineCreationFeedbackCreateInfoEXT VkPipelineCreationFeedbackEXT']
--
Possible values of the pname:flags member of
slink:VkPipelineCreationFeedbackEXT are:
include::../../api/enums/VkPipelineCreationFeedbackFlagBitsEXT.txt[]
* ename:VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT indicates that the
feedback information is valid.
* ename:VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT
indicates that a readily usable pipeline or pipeline stage was found in
the pname:pipelineCache specified by the application in the pipeline
creation command.
+
An implementation should: set the
ename:VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT
bit if it was able to avoid the large majority of pipeline or pipeline stage
creation work by using the pname:pipelineCache parameter of
flink:vkCreateGraphicsPipelines,
ifdef::VK_NV_ray_tracing[]
flink:vkCreateRayTracingPipelinesNV,
endif::VK_NV_ray_tracing[]
or flink:vkCreateComputePipelines.
When an implementation sets this bit for the entire pipeline, it may: leave
it unset for any stage.
+
[NOTE]
.Note
====
Implementations are encouraged to provide a meaningful signal to
applications using this bit.
The intention is to communicate to the application that the pipeline or
pipeline stage was created "as fast as it gets" using the pipeline cache
provided by the application.
If an implementation uses an internal cache, it is discouraged from setting
this bit as the feedback would be unactionable.
====
* ename:VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT
indicates that the base pipeline specified by the
pname:basePipelineHandle or pname:basePipelineIndex member of the
stext:Vk*PipelineCreateInfo structure was used to accelerate the
creation of the pipeline.
+
An implementation should: set the
ename:VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT bit
if it was able to avoid a significant amount of work by using the base
pipeline.
+
[NOTE]
.Note
====
While "significant amount of work" is subjective, implementations are
encouraged to provide a meaningful signal to applications using this bit.
For example, a 1% reduction in duration may not warrant setting this bit,
while a 50% reduction would.
====
--
[open,refpage='VkPipelineCreationFeedbackFlagsEXT',desc='Bitmask of VkPipelineCreationFeedbackFlagBitsEXT',type='flags',xrefs='VkPipelineCreationFeedbackEXT VkPipelineCreationFeedbackFlagBitsEXT']
--
include::../../api/flags/VkPipelineCreationFeedbackFlagsEXT.txt[]
tname:VkPipelineCreationFeedbackFlagsEXT is a bitmask type for providing
zero or more elink:VkPipelineCreationFeedbackFlagBitsEXT.
--

View File

@ -404,6 +404,17 @@ flink:vkGetPhysicalDeviceSurfaceCapabilitiesKHR, with the ability to specify
extended inputs via chained input structures, and to return extended
information via chained output structures.
ifdef::VK_EXT_full_screen_exclusive,VK_KHR_win32_surface[]
.Valid Usage
****
* [[VUID-vkGetPhysicalDeviceSurfaceCapabilities2KHR-pNext-02671]]
If an instance of slink:VkSurfaceCapabilitiesFullScreenExclusiveEXT is
included in the pname:pNext chain of pname:pSurfaceCapabilities, an
instance of slink:VkSurfaceFullScreenExclusiveWin32InfoEXT must: be
included in the pname:pNext chain of pname:pSurfaceInfo.
****
endif::VK_EXT_full_screen_exclusive,VK_KHR_win32_surface[]
include::../../validity/protos/vkGetPhysicalDeviceSurfaceCapabilities2KHR.txt[]
--
@ -422,9 +433,134 @@ The members of sname:VkPhysicalDeviceSurfaceInfo2KHR correspond to the
arguments to flink:vkGetPhysicalDeviceSurfaceCapabilitiesKHR, with
pname:sType and pname:pNext added for extensibility.
ifdef::VK_EXT_full_screen_exclusive[]
Additional capabilities of a surface may: be available to swapchains created
with different full-screen exclusive settings - particularly if exclusive
full-screen access is application controlled.
These additional capabilities can: be queried by including the
slink:VkSurfaceFullScreenExclusiveInfoEXT structure in the pname:pNext chain
of this structure when used to query surface properties.
ifdef::VK_KHR_win32_surface[]
Additionally, for Win32 surfaces with application controlled exclusive
full-screen access, chaining a valid instance of the
slink:VkSurfaceFullScreenExclusiveWin32InfoEXT structure may: also report
additional surface capabilities.
endif::VK_KHR_win32_surface[]
These additional capabilities only apply to swapchains created with the same
parameters passed into the pname:pNext chain of
slink:VkSwapchainCreateInfoKHR.
endif::VK_EXT_full_screen_exclusive[]
ifdef::VK_KHR_win32_surface,VK_EXT_full_screen_exclusive[]
.Valid Usage
****
* [[VUID-VkPhysicalDeviceSurfaceInfo2KHR-pNext-02672]]
If the pname:pNext chain includes an instance of
slink:VkSurfaceFullScreenExclusiveInfoEXT with its
pname:fullScreenExclusive member set to
ename:VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT, and
pname:surface was created using flink:vkCreateWin32SurfaceKHR, an
instance of slink:VkSurfaceFullScreenExclusiveWin32InfoEXT must: be
present in the pname:pNext chain
****
endif::VK_KHR_win32_surface,VK_EXT_full_screen_exclusive[]
include::../../validity/structs/VkPhysicalDeviceSurfaceInfo2KHR.txt[]
--
ifdef::VK_EXT_full_screen_exclusive[]
[open,refpage='VkSurfaceFullScreenExclusiveInfoEXT',desc='Structure specifying the preferred full-screen transition behavior',type='structs']
--
If the pname:pNext chain of slink:VkSwapchainCreateInfoKHR includes a
sname:VkSurfaceFullScreenExclusiveInfoEXT structure, then that structure
specifies the application's preferred full-screen transition behavior.
The sname:VkSurfaceFullScreenExclusiveInfoEXT structure is defined as:
include::../../api/structs/VkSurfaceFullScreenExclusiveInfoEXT.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:fullScreenExclusive is a elink:VkFullScreenExclusiveEXT value
specifying the preferred full-screen transition behavior.
If this structure is not present, pname:fullScreenExclusive is considered to
be ename:VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT.
include::../../validity/structs/VkSurfaceFullScreenExclusiveInfoEXT.txt[]
--
[open,refpage='VkFullScreenExclusiveEXT',desc='Hint values an application can specify affecting full-screen transition behavior',type='enums']
--
Possible values of
sname:VkSurfaceFullScreenExclusiveInfoEXT::pname:fullScreenExclusive are:
include::../../api/enums/VkFullScreenExclusiveEXT.txt[]
* ename:VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT indicates the implementation
should: determine the appropriate full-screen method by whatever means
it deems appropriate.
* ename:VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT indicates the implementation
may: use full-screen exclusive mechanisms when available.
Such mechanisms may: result in better performance and/or the
availability of different presentation capabilities, but may: require a
more disruptive transition during swapchain initialization, first
presentation and/or destruction.
* ename:VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT indicates the
implementation should: avoid using full-screen mechanisms which rely on
disruptive transitions.
* ename:VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT indicates the
application will manage full-screen exclusive mode by using the
flink:vkAcquireFullScreenExclusiveModeEXT and
flink:vkReleaseFullScreenExclusiveModeEXT commands.
--
ifdef::VK_KHR_win32_surface[]
[open,refpage='VkSurfaceFullScreenExclusiveWin32InfoEXT',desc='Structure specifying additional creation parameters specific to Win32 fullscreen exclusive mode',type='structs']
--
The sname:VkSurfaceFullScreenExclusiveWin32InfoEXT structure is defined as:
include::../../api/structs/VkSurfaceFullScreenExclusiveWin32InfoEXT.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:hmonitor is the Win32 code:HMONITOR handle identifying the display
to create the surface with.
[NOTE]
.Note
====
If pname:hmonitor is invalidated (e.g. the monitor is unplugged) during the
lifetime of a swapchain created with this structure, operations on that
swapchain will return ename:VK_ERROR_OUT_OF_DATE_KHR.
====
[NOTE]
.Note
====
It's the responsibility of the application to change the display settings of
the targeted Win32 display using the appropriate platform APIs.
Such changes may: alter the surface capabilities reported for the created
surface.
====
.Valid Usage
****
* [[VUID-VkSurfaceFullScreenExclusiveWin32InfoEXT-hmonitor-02673]]
pname:hmonitor must: be a valid code:HMONITOR
****
include::../../validity/structs/VkSurfaceFullScreenExclusiveWin32InfoEXT.txt[]
--
endif::VK_KHR_win32_surface[]
endif::VK_EXT_full_screen_exclusive[]
[open,refpage='VkSurfaceCapabilities2KHR',desc='Structure describing capabilities of a surface',type='structs']
--
@ -441,6 +577,34 @@ include::../../api/structs/VkSurfaceCapabilities2KHR.txt[]
include::../../validity/structs/VkSurfaceCapabilities2KHR.txt[]
--
ifdef::VK_KHR_surface_protected_capabilities[]
[open,refpage='VkSurfaceProtectedCapabilitiesKHR',desc='Structure describing capability of a surface to be protected',type='structs']
--
An application queries if a protected VkSurface is displayable on a specific
windowing system using sname:VkSurfaceProtectedCapabilitiesKHR, which can:
be passed in pname:pNext parameter of sname:VkSurfaceCapabilities2KHR.
The sname:VkSurfaceProtectedCapabilitiesKHR structure is defined as:
include::../../api/structs/VkSurfaceProtectedCapabilitiesKHR.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:supportsProtected specifies whether a protected swapchain created
from slink:VkPhysicalDeviceSurfaceInfo2KHR::pname:surface for a
particular windowing system can: be displayed on screen or not.
If pname:supportsProtected is ename:VK_TRUE, then creation of swapchains
with the ename:VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR flag set must: be
supported for pname:surface.
include::../../validity/structs/VkSurfaceProtectedCapabilitiesKHR.txt[]
--
endif::VK_KHR_surface_protected_capabilities[]
ifdef::VK_KHR_shared_presentable_image[]
[open,refpage='VkSharedPresentSurfaceCapabilitiesKHR',desc='structure describing capabilities of a surface for shared presentation',type='structs']
--
@ -465,6 +629,58 @@ include::../../validity/structs/VkSharedPresentSurfaceCapabilitiesKHR.txt[]
--
endif::VK_KHR_shared_presentable_image[]
ifdef::VK_AMD_display_native_hdr[]
[open,refpage='VkDisplayNativeHdrSurfaceCapabilitiesAMD',desc='Structure describing display native HDR specific capabilities of a surface',type='structs']
--
The sname:VkDisplayNativeHdrSurfaceCapabilitiesAMD structure is defined as:
include::../../api/structs/VkDisplayNativeHdrSurfaceCapabilitiesAMD.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:localDimmingSupport specifies whether the surface supports local
dimming.
If this is ename:VK_TRUE, slink:VkSwapchainDisplayNativeHdrCreateInfoAMD
can: be used to explicitly enable or disable local dimming for the
surface.
Local dimming may also be overriden by flink:vkSetLocalDimmingAMD during
the lifetime of the swapchain.
include::../../validity/structs/VkDisplayNativeHdrSurfaceCapabilitiesAMD.txt[]
--
endif::VK_AMD_display_native_hdr[]
ifdef::VK_EXT_full_screen_exclusive[]
[open,refpage='VkSurfaceCapabilitiesFullScreenExclusiveEXT',desc='Structure describing full screen exclusive capabilities of a surface',type='structs']
--
The sname:VkSurfaceCapabilitiesFullScreenExclusiveEXT structure is defined
as:
include::../../api/structs/VkSurfaceCapabilitiesFullScreenExclusiveEXT.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:fullScreenExclusiveControlSupported is a boolean describing
whether the surface is able to make use of exclusive full-screen access.
This structure can: be included in the pname:pNext chain of
slink:VkSurfaceCapabilities2KHR to determine support for exclusive
full-screen access.
If pname:fullScreenExclusiveSupported is ename:VK_FALSE, it indicates that
exclusive full-screen access is not obtainable for this surface.
Applications must: not attempt to create swapchains with
ename:VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT set if
pname:fullScreenExclusiveSupported is ename:VK_FALSE.
include::../../validity/structs/VkSurfaceCapabilitiesFullScreenExclusiveEXT.txt[]
--
endif::VK_EXT_full_screen_exclusive[]
endif::VK_KHR_get_surface_capabilities2[]
ifdef::VK_EXT_display_surface_counter[]
@ -720,6 +936,12 @@ ifdef::VK_EXT_swapchain_colorspace[]
are used "`as is`".
This is intended to allow applications to supply data for color spaces
not described here.
ifdef::VK_AMD_display_native_hdr[]
* ename:VK_COLOR_SPACE_DISPLAY_NATIVE_AMD specifies support for the
display's native color space.
This matches the color space expectations of AMD's FreeSync2 standard,
for displays supporting it.
endif::VK_AMD_display_native_hdr[]
The color components of Non-linear color space swap chain images have had
the appropriate transfer function applied.
@ -984,6 +1206,36 @@ were returned.
include::../../validity/protos/vkGetPhysicalDeviceSurfacePresentModesKHR.txt[]
--
ifdef::VK_EXT_full_screen_exclusive[]
[open,refpage='vkGetPhysicalDeviceSurfacePresentModes2EXT',desc='Query supported presentation modes',type='protos']
--
Alternatively, to query the supported presentation modes for a surface
combined with select other fixed swapchain creation parameters, call:
include::../../api/protos/vkGetPhysicalDeviceSurfacePresentModes2EXT.txt[]
* pname:physicalDevice is the physical device that will be associated with
the swapchain to be created, as described for
flink:vkCreateSwapchainKHR.
* pname:pSurfaceInfo points to an instance of the
slink:VkPhysicalDeviceSurfaceInfo2KHR structure, describing the surface
and other fixed parameters that would be consumed by
flink:vkCreateSwapchainKHR.
* pname:pPresentModeCount is a pointer to an integer related to the number
of presentation modes available or queried, as described below.
* pname:pPresentModes is either `NULL` or a pointer to an array of
elink:VkPresentModeKHR values, indicating the supported presentation
modes.
fname:vkGetPhysicalDeviceSurfacePresentModes2EXT behaves similarly to
flink:vkGetPhysicalDeviceSurfacePresentModesKHR, with the ability to specify
extended inputs via chained input structures.
include::../../validity/protos/vkGetPhysicalDeviceSurfacePresentModes2EXT.txt[]
--
endif::VK_EXT_full_screen_exclusive[]
[open,refpage='VkPresentModeKHR',desc='presentation mode supported for a surface',type='enums']
--
@ -1085,6 +1337,92 @@ equivalent to the behavior of {wgl|glX}SwapBuffers with a swap interval of
--
ifdef::VK_EXT_full_screen_exclusive[]
== Full Screen Exclusive Control
Swapchains created with pname:fullScreenExclusive set to
ename:VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT must: acquire and
release exclusive full-screen access explicitly, using the following
commands.
[open,refpage='vkAcquireFullScreenExclusiveModeEXT',desc='Acquire full-screen exclusive mode for a swapchain',type='protos']
--
To acquire exclusive full-screen access for a swapchain, call:
include::../../api/protos/vkAcquireFullScreenExclusiveModeEXT.txt[]
* pname:device is the device associated with pname:swapchain.
* pname:swapchain is the swapchain to acquire exclusive full-screen access
for.
.Valid Usage
****
* [[VUID-vkAcquireFullScreenExclusiveModeEXT-swapchain-02674]]
pname:swapchain must: not be in the retired state
* [[VUID-vkAcquireFullScreenExclusiveModeEXT-swapchain-02675]]
pname:swapchain must: be a swapchain created with an instance of
slink:VkSurfaceFullScreenExclusiveInfoEXT, with
pname:fullScreenExclusive set to
ename:VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT
* [[VUID-vkAcquireFullScreenExclusiveModeEXT-swapchain-02676]]
pname:swapchain must: not currently have exclusive full-screen access
****
A return value of ename:VK_SUCCESS indicates that the pname:swapchain
successfully acquired exclusive full-screen access.
The swapchain will retain this exclusivity until either the application
releases exclusive full-screen access with
flink:vkReleaseFullScreenExclusiveModeEXT, destroys the swapchain, or if any
of the swapchain commands return
ename:VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT indicating that the mode
was lost because of platform-specific changes.
If the swapchain was unable to acquire exclusive full-screen access to the
display then ename:VK_ERROR_INITIALIZATION_FAILED is returned.
An application can: attempt to acquire exclusive full-screen access again
for the same swapchain even if this command fails, or if
ename:VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT has been returned by a
swapchain command.
include::../../validity/protos/vkAcquireFullScreenExclusiveModeEXT.txt[]
--
[open,refpage='vkReleaseFullScreenExclusiveModeEXT',desc='Release full-screen exclusive mode from a swapchain',type='protos']
--
To release exclusive full-screen access from a swapchain, call:
include::../../api/protos/vkReleaseFullScreenExclusiveModeEXT.txt[]
* pname:device is the device associated with pname:swapchain.
* pname:swapchain is the swapchain to release exclusive full-screen access
from.
[NOTE]
.Note
====
Applications will not be able to present to pname:swapchain after this call
until exclusive full-screen access is reacquired.
This is usually useful to handle when an application is minimised or
otherwise intends to stop presenting for a time.
====
.Valid Usage
****
* [[VUID-vkReleaseFullScreenExclusiveModeEXT-swapchain-02677]]
pname:swapchain must: not be in the retired state
* [[VUID-vkReleaseFullScreenExclusiveModeEXT-swapchain-02678]]
pname:swapchain must: be a swapchain created with an instance of
slink:VkSurfaceFullScreenExclusiveInfoEXT, with
pname:fullScreenExclusive set to
ename:VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT
****
--
endif::VK_EXT_full_screen_exclusive[]
ifdef::VK_KHR_swapchain[]
ifdef::VK_VERSION_1_1,VK_KHR_device_group[]
@ -1198,6 +1536,32 @@ include::../../validity/protos/vkGetDeviceGroupSurfacePresentModesKHR.txt[]
--
ifdef::VK_EXT_full_screen_exclusive[]
[open,refpage='vkGetDeviceGroupSurfacePresentModes2EXT',desc='Query device group present capabilities for a surface',type='protos']
--
Alternatively, to query the supported device group presentation modes for a
surface combined with select other fixed swapchain creation parameters,
call:
include::../../api/protos/vkGetDeviceGroupSurfacePresentModes2EXT.txt[]
* pname:device is the logical device.
* pname:pSurfaceInfo points to an instance of the
VkPhysicalDeviceSurfaceInfo2KHR structure, describing the surface and
other fixed parameters that would be consumed by vkCreateSwapchainKHR.
* pname:pModes is a pointer to a value of type
tlink:VkDeviceGroupPresentModeFlagsKHR that is filled with the supported
device group present modes for the surface.
fname:vkGetDeviceGroupSurfacePresentModes2EXT behaves similarly to
flink:vkGetDeviceGroupSurfacePresentModesKHR, with the ability to specify
extended inputs via chained input structures.
include::../../validity/protos/vkGetDeviceGroupSurfacePresentModes2EXT.txt[]
--
endif::VK_EXT_full_screen_exclusive[]
[open,refpage='vkGetPhysicalDevicePresentRectanglesKHR',desc='Query present rectangles for a surface on a physical device',type='protos']
--

View File

@ -97,6 +97,41 @@ include::../../api/protos/vkCreateSwapchainKHR.txt[]
* pname:pSwapchain is a pointer to a slink:VkSwapchainKHR handle in which
the created swapchain object will be returned.
ifdef::VK_EXT_full_screen_exclusive[]
If the pname:oldSwapchain parameter of pname:pCreateInfo is a valid
swapchain, which has exclusive full-screen access, that access is released
from pname:oldSwapchain.
If the command succeeds in this case, the newly created swapchain will
automatically acquire exclusive full-screen access from pname:oldSwapchain.
[NOTE]
.Note
====
This implicit transfer is intended to avoid exiting and entering full-screen
exclusive mode, which may otherwise cause unwanted visual updates to the
display.
====
In some cases, swapchain creation may: fail if exclusive full-screen mode is
requested for application control, but for some implementation-specific
reason exclusive full-screen access is unavailable for the particular
combination of parameters provided.
If this occurs, ename:VK_ERROR_INITIALIZATION_FAILED will be returned.
[NOTE]
.Note
====
In particular, it will fail if the pname:imageExtent member of
pname:pCreateInfo does not match the extents of the monitor.
ifdef::VK_KHR_win32_surface[]
Other reasons for failure may include the app not being set as high-dpi
aware, or if the physical device and monitor are not compatible in this
mode.
====
endif::VK_KHR_win32_surface[]
endif::VK_EXT_full_screen_exclusive[]
include::../../validity/protos/vkCreateSwapchainKHR.txt[]
--
@ -233,11 +268,11 @@ endif::VK_KHR_shared_presentable_image[]
****
* [[VUID-VkSwapchainCreateInfoKHR-surface-01270]]
pname:surface must: be a surface that is supported by the device as
determined using fname:vkGetPhysicalDeviceSurfaceSupportKHR
determined using flink:vkGetPhysicalDeviceSurfaceSupportKHR
* [[VUID-VkSwapchainCreateInfoKHR-minImageCount-01271]]
pname:minImageCount must: be greater than or equal to the value returned
in the pname:minImageCount member of the sname:VkSurfaceCapabilitiesKHR
structure returned by fname:vkGetPhysicalDeviceSurfaceCapabilitiesKHR
structure returned by flink:vkGetPhysicalDeviceSurfaceCapabilitiesKHR
for the surface
* [[VUID-VkSwapchainCreateInfoKHR-minImageCount-01272]]
pname:minImageCount must: be less than or equal to the value returned in
@ -354,6 +389,24 @@ ifdef::VK_KHR_swapchain_mutable_format[]
greater than zero and pname:pViewFormats must: have an element equal to
pname:imageFormat
endif::VK_KHR_swapchain_mutable_format[]
ifdef::VK_KHR_surface_protected_capabilities[]
* [[VUID-VkSwapchainCreateInfoKHR-flags-03187]]
If pname:flags contains ename:VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR,
then sname:VkSurfaceProtectedCapabilitiesKHR::pname:supportsProtected
must: be ename:VK_TRUE in the slink:VkSurfaceProtectedCapabilitiesKHR
structure returned by flink:vkGetPhysicalDeviceSurfaceCapabilities2KHR
for pname:surface
endif::VK_KHR_surface_protected_capabilities[]
ifdef::VK_EXT_full_screen_exclusive,VK_KHR_win32_surface[]
* [[VUID-VkSwapchainCreateInfoKHR-pNext-02679]]
If the pname:pNext chain includes an instance of
slink:VkSurfaceFullScreenExclusiveInfoEXT with its
pname:fullScreenExclusive member set to
ename:VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT, and
pname:surface was created using flink:vkCreateWin32SurfaceKHR, an
instance of slink:VkSurfaceFullScreenExclusiveWin32InfoEXT must: be
present in the pname:pNext chain
endif::VK_EXT_full_screen_exclusive,VK_KHR_win32_surface[]
****
include::../../validity/structs/VkSwapchainCreateInfoKHR.txt[]
@ -426,6 +479,75 @@ include::../../validity/structs/VkDeviceGroupSwapchainCreateInfoKHR.txt[]
endif::VK_VERSION_1_1,VK_KHR_device_group[]
ifdef::VK_AMD_display_native_hdr[]
[open,refpage='VkSwapchainDisplayNativeHdrCreateInfoAMD',desc='Structure specifying display native HDR parameters of a newly created swapchain object',type='structs']
--
If the pname:pNext chain of slink:VkSwapchainCreateInfoKHR includes a
sname:VkSwapchainDisplayNativeHdrCreateInfoAMD structure, then that
structure includes additional swapchain creation parameters specific to
display native HDR support.
The sname:VkSwapchainDisplayNativeHdrCreateInfoAMD structure is defined as:
include::../../api/structs/VkSwapchainDisplayNativeHdrCreateInfoAMD.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:localDimmingEnable specifies whether local dimming is enabled for
the swapchain.
If the pname:pNext chain of slink:VkSwapchainCreateInfoKHR does not contain
this structure, the default value for pname:localDimmingEnable is
ename:VK_TRUE, meaning local dimming is initially enabled for the swapchain.
include::../../validity/structs/VkSwapchainDisplayNativeHdrCreateInfoAMD.txt[]
.Valid Usage
****
* [[VUID-VkSwapchainDisplayNativeHdrCreateInfoAMD-localDimmingEnable-XXXXX]]
It is only valid to set pname:localDimmingEnable to ename:VK_TRUE if
slink:VkDisplayNativeHdrSurfaceCapabilitiesAMD::pname:localDimmingSupport
is supported.
****
--
[open,refpage='vkSetLocalDimmingAMD',desc='Set Local Dimming',type='protos']
--
The local dimming HDR setting may also be changed over the life of a
swapchain by calling:
include::../../api/protos/vkSetLocalDimmingAMD.txt[]
* pname:swapChain handle to enable local dimming.
* pname:localDimmingEnable specifies whether local dimming is enabled for
the swapchain.
include::../../validity/protos/vkSetLocalDimmingAMD.txt[]
.Valid Usage
****
* [[VUID-vkSetLocalDimmingAMD-XXXXX]]
It is only valid to call flink:vkSetLocalDimmingAMD if
slink:VkDisplayNativeHdrSurfaceCapabilitiesAMD::pname:localDimmingSupport
is supported.
****
--
endif::VK_AMD_display_native_hdr[]
ifdef::VK_EXT_full_screen_exclusive[]
--
If the pname:pNext chain of slink:VkSwapchainCreateInfoKHR includes a
slink:VkSurfaceFullScreenExclusiveInfoEXT structure, then that structure
specifies the application's preferred full-screen presentation behavior.
If this structure is not present, pname:fullScreenExclusive is considered to
be ename:VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT.
--
endif::VK_EXT_full_screen_exclusive[]
ifdef::VK_EXT_display_control[]
include::../VK_EXT_display_control/swapchain_counters.txt[]
endif::VK_EXT_display_control[]
@ -548,6 +670,11 @@ ifdef::VK_KHR_display_swapchain[]
include::../VK_KHR_display_swapchain/destroy_swapchain_interactions.txt[]
endif::VK_KHR_display_swapchain[]
ifdef::VK_EXT_full_screen_exclusive[]
If pname:swapchain has exclusive full-screen access, it is released before
the swapchain is destroyed.
endif::VK_EXT_full_screen_exclusive[]
.Valid Usage
****
* [[VUID-vkDestroySwapchainKHR-swapchain-01282]]
@ -607,19 +734,14 @@ can: create command buffers that reference these images prior to entering
its main rendering loop.
====
The implementation will have already allocated and bound the memory backing
the sname:VkImage objects returned by fname:vkGetSwapchainImagesKHR.
The memory for each image will not alias with the memory for other images or
with any sname:VkDeviceMemory object.
As such, performing any operation affecting the binding of memory to a
presentable image results in undefined: behavior.
Images returned by flink:vkGetSwapchainImagesKHR are fully backed by memory
before they are passed to the application.
All presentable images are initially in the ename:VK_IMAGE_LAYOUT_UNDEFINED
layout, thus before using presentable images, the application must:
transition them to a valid layout for the intended use.
Further, the lifetime of presentable images is controlled by the
implementation so destroying a presentable image with flink:vkDestroyImage
results in undefined: behavior.
implementation, so applications must: not destroy a presentable image.
See flink:vkDestroySwapchainKHR for further details on the lifetime of
presentable images.
@ -1027,6 +1149,14 @@ ename:VK_ERROR_SURFACE_LOST_KHR, the set of queue operations are still
considered to be enqueued and thus any semaphore to be waited on gets
unsignaled when the corresponding queue operation is complete.
ifdef::VK_EXT_full_screen_exclusive[]
If any pname:swapchain member of pname:pPresentInfo was created with
ename:VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT,
ename:VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT will be returned if that
swapchain does not have exclusive full-screen access, possibly for
implementation-specific reasons outside of the application's control.
endif::VK_EXT_full_screen_exclusive[]
include::../../validity/protos/vkQueuePresentKHR.txt[]
--
@ -1255,6 +1385,11 @@ the following rules in order:
* If any of the presents would have a result of
ename:VK_ERROR_OUT_OF_DATE_KHR if issued separately then
ename:VK_ERROR_OUT_OF_DATE_KHR is returned.
ifdef::VK_EXT_full_screen_exclusive[]
* If any of the presents would have a result of
ename:VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT if issued separately
then ename:VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT is returned.
endif::VK_EXT_full_screen_exclusive[]
* If any of the presents would have a result of ename:VK_SUBOPTIMAL_KHR if
issued separately then ename:VK_SUBOPTIMAL_KHR is returned.
* Otherwise ename:VK_SUCCESS is returned.

View File

@ -22,10 +22,10 @@ include::../../api/protos/vkCreateViSurfaceNN.txt[]
created surface object is returned.
During the lifetime of a surface created using a particular
code:nn::code:vi::code:NativeWindowHandle any attempts to create another
surface for the same code:nn::code:vi::code:Layer and any attempts to
connect to the same code:nn::code:vi::code:Layer through other platform
mechanisms will have undefined: results.
code:nn::code:vi::code:NativeWindowHandle, applications must: not attempt to
create another surface for the same code:nn::code:vi::code:Layer or attempt
to connect to the same code:nn::code:vi::code:Layer through other platform
mechanisms.
If the native window is created with a specified size, pname:currentExtent
will reflect that size.

View File

@ -40,10 +40,8 @@ undefined: after an execute secondary command buffer command is recorded.
There is one exception to this rule - if the primary command buffer is
inside a render pass instance, then the render pass and subpass state is not
disturbed by executing secondary command buffers.
Whenever the state of a command buffer is undefined:, the application must:
set all relevant state on the command buffer before any state dependent
commands such as draws and dispatches are recorded, otherwise the behavior
of executing that command buffer is undefined:.
For state dependent commands (such as draws and dispatches), any state
consumed by those commands must: not be undefined:.
Unless otherwise specified, and without explicit synchronization, the
various commands submitted to a queue via command buffers may: execute in
@ -1347,10 +1345,14 @@ in the queue.
Such events must: be signaled by the application using flink:vkSetEvent, and
the fname:vkCmdWaitEvents commands that wait upon them must: not be inside a
render pass instance.
Implementations may: have limits on how long the command buffer will wait,
in order to avoid interfering with progress of other clients of the device.
If the event is not signaled within these limits, results are undefined: and
may: include device loss.
The event must: be set before the flink:vkCmdWaitEvents command is executed.
[NOTE]
.Note
====
Implementations may have some tolerance for waiting on events to be set, but
this is defined outside of the scope of Vulkan.
====
[[commandbuffers-secondary]]

View File

@ -2130,33 +2130,35 @@ The allocated descriptor sets are returned in pname:pDescriptorSets.
When a descriptor set is allocated, the initial state is largely
uninitialized and all descriptors are undefined:.
However, the descriptor set can: be bound in a command buffer without
causing errors or exceptions.
Descriptors also become undefined: if the underlying resource is destroyed.
Descriptor sets containing undefined: descriptors can: still be bound and
used, subject to the following conditions:
ifdef::VK_EXT_descriptor_indexing[]
For descriptor set bindings created with the
ename:VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT bit set, all descriptors
in that binding that are dynamically used must: have been populated before
the descriptor set is <<descriptorsets-binding,consumed>>.
For descriptor set bindings created without the
ename:VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT bit set, all descriptors
in that binding that are statically used must: have been populated before
the descriptor set is <<descriptorsets-binding,consumed>>.
* For descriptor set bindings created with the
ename:VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT bit set, all
descriptors in that binding that are dynamically used must: have been
populated before the descriptor set is
<<descriptorsets-binding,consumed>>.
* For descriptor set bindings created without the
ename:VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT bit set, all
descriptors in that binding that are statically used must: have been
populated before the descriptor set is
<<descriptorsets-binding,consumed>>.
endif::VK_EXT_descriptor_indexing[]
ifndef::VK_EXT_descriptor_indexing[]
All descriptors that are statically used must: have been populated before
the descriptor set is consumed.
* Descriptors that are <<shaders-staticuse,statically used>> must: have
been populated before the descriptor set is
<<descriptorsets-binding,consumed>>.
endif::VK_EXT_descriptor_indexing[]
ifdef::VK_EXT_inline_uniform_block[]
Descriptor bindings with descriptor type of
ename:VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT need not be populated
before the descriptor set is consumed.
* Descriptor bindings with descriptor type of
ename:VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT can: be undefined:
when the descriptor set is <<descriptorsets-binding,consumed>>; though
values in that block will be undefined:.
endif::VK_EXT_inline_uniform_block[]
Entries that are not used by a pipeline can: have uninitialized descriptors
or descriptors of resources that have been destroyed, and executing a draw
or dispatch with such a descriptor set bound does not cause undefined:
behavior.
This means applications need not populate unused entries with dummy
descriptors.
* Entries that are not used by a pipeline can: have undefined:
descriptors.
ifdef::VK_VERSION_1_1,VK_KHR_maintenance1[]
If a call to fname:vkAllocateDescriptorSets would cause the total number of
@ -3749,24 +3751,21 @@ descriptor set and later bound to a command buffer.
Push descriptors allow for incremental updates of descriptors without
managing the lifetime of descriptor sets.
When a command buffer begins recording, all push descriptors have undefined:
contents.
When a command buffer begins recording, all push descriptors are undefined:.
Push descriptors can: be updated incrementally and cause shaders to use the
updated descriptors for subsequent rendering commands (either compute or
graphics, according to the pname:pipelineBindPoint) until the descriptor is
overwritten, or else until the set is disturbed as described in
<<descriptorsets-compatibility, Pipeline Layout Compatibility>>.
When the set is disturbed or push descriptors with a different descriptor
set layout are set, all push descriptors become invalid.
set layout are set, all push descriptors are undefined:.
Valid descriptors must: be pushed for all bindings that any shaders in a
pipeline access, at the time that a draw or dispatch command is recorded to
execute using that pipeline.
Push descriptors that are <<shaders-staticuse,statically used>> by a
pipeline must: not be undefined: at the time that a draw or dispatch command
is recorded to execute using that pipeline.
This includes immutable sampler descriptors, which must: be pushed before
they are accessed by a pipeline.
However, if none of the shaders in a pipeline statically use certain
bindings in the push descriptor set, then those descriptors need not be
valid.
Push descriptors that are not statically used can: remain undefined:.
Push descriptors do not use dynamic offsets.
Instead, the corresponding non-dynamic descriptor types can: be used and the

View File

@ -1113,14 +1113,19 @@ references on where to find more information:
A logical device may: become _lost_ for a number of implementation-specific
reasons, indicating that pending and future command execution may: fail and
cause resources and backing memory to become undefined.
cause resources and backing memory to become undefined:.
[NOTE]
.Note
====
Typical reasons for device loss will include things like execution timing
out (to prevent denial of service), power management events, platform
resource management, or implementation errors.
resource management, implementation errors.
Applications not adhering to <<fundamentals-errors, valid usage>> may also
result in device loss being reported, however this is not guaranteed.
Even if device loss is reported, the system may be in an unrecoverable
state, and further usage of the API is still considered invalid.
====
When this happens, certain commands will return ename:VK_ERROR_DEVICE_LOST
@ -1154,17 +1159,6 @@ such as the operating system crashing; in which case it may: not be reported
via the Vulkan API.
====
[NOTE]
.Note
====
Undefined behavior caused by an application error may: cause a device to
become lost.
However, such undefined: behavior may: also cause unrecoverable damage to
the process, and it is then not guaranteed that the API objects, including
the sname:VkPhysicalDevice or the sname:VkInstance are still valid or that
the error is recoverable.
====
When a device is lost, its child objects are not implicitly destroyed and
their handles are still valid.
Those objects must: still be destroyed before their parents or the device

View File

@ -45,10 +45,8 @@ include::../validity/protos/vkGetPhysicalDeviceFeatures.txt[]
Fine-grained features used by a logical device must: be enabled at
sname:VkDevice creation time.
If a feature is enabled that the physical device does not support,
sname:VkDevice creation will fail.
If an application uses a feature without enabling it at sname:VkDevice
creation time, the device behavior is undefined:.
The validation layer will warn if features are used without being enabled.
sname:VkDevice creation will fail and return
ename:VK_ERROR_FEATURE_NOT_PRESENT.
The fine-grained features are enabled by passing a pointer to the
sname:VkPhysicalDeviceFeatures structure via the pname:pEnabledFeatures
@ -236,9 +234,8 @@ binding for that vertex shader invocation are considered out of bounds.
**** Zero values, format converted according to the format of the
attribute.
**** Zero values, or [eq]#(0,0,0,x)# vectors, as described above.
** If pname:robustBufferAccess is not enabled, out of bounds accesses may:
corrupt any memory within the process and cause undefined: behavior up
to and including application termination.
** If pname:robustBufferAccess is not enabled, applications must: not
perform out of bounds accesses.
* [[features-fullDrawIndexUint32]] pname:fullDrawIndexUint32 specifies the
full 32-bit range of indices is supported for indexed draw calls when
using a elink:VkIndexType of ename:VK_INDEX_TYPE_UINT32.
@ -1071,7 +1068,8 @@ The sname:VkPhysicalDeviceProtectedMemoryFeatures structure is defined as:
include::../api/structs/VkPhysicalDeviceProtectedMemoryFeatures.txt[]
* pname:protectedMemory specifies whether protected memory is supported.
* [[features-features-protectedMemory]] pname:protectedMemory specifies
whether protected memory is supported.
If the sname:VkPhysicalDeviceProtectedMemoryFeatures structure is included
in the pname:pNext chain of slink:VkPhysicalDeviceFeatures2, it is filled
@ -2025,6 +2023,32 @@ include::../validity/structs/VkPhysicalDeviceYcbcrImageArraysFeaturesEXT.txt[]
endif::VK_EXT_ycbcr_image_arrays[]
ifdef::VK_EXT_host_query_reset[]
[open,refpage='VkPhysicalDeviceHostQueryResetFeaturesEXT',desc='Structure describing whether queries can be reset from the host',type='structs']
--
The sname:VkPhysicalDeviceHostQueryResetFeaturesEXT structure is defined as:
include::../api/structs/VkPhysicalDeviceHostQueryResetFeaturesEXT.txt[]
The members of the sname:VkPhysicalDeviceHostQueryResetFeaturesEXT structure
describe the following features:
* [[features-hostQueryReset]] pname:hostQueryReset indicates that the
implementation supports resetting queries from the host with
flink:vkResetQueryPoolEXT.
If the sname:VkPhysicalDeviceHostQueryResetFeaturesEXT structure is included
in the pname:pNext chain of slink:VkPhysicalDeviceFeatures2, it is filled
with values indicating whether the feature is supported.
sname:VkPhysicalDeviceHostQueryResetFeaturesEXT can: also be used in the
pname:pNext chain of slink:VkDeviceCreateInfo to enable features.
include::../validity/structs/VkPhysicalDeviceHostQueryResetFeaturesEXT.txt[]
--
endif::VK_EXT_host_query_reset[]
[[features-requirements]]
== Feature Requirements

View File

@ -705,8 +705,7 @@ memory from one process can: be visible to another process or not must: not
be violated by a Vulkan implementation for *any memory allocation*.
Vulkan implementations are not required: to make additional security or
integrity guarantees beyond those provided by the OS unless explicitly
directed by the application's use of a particular feature or extension (e.g.
via <<features-robustBufferAccess, robust buffer access>>).
directed by the application's use of a particular feature or extension.
[NOTE]
.Note
@ -715,10 +714,20 @@ For instance, if an operating system guarantees that data in all its memory
allocations are set to zero when newly allocated, the Vulkan implementation
must: make the same guarantees for any allocations it controls (e.g.
slink:VkDeviceMemory).
Similarly, if an operating system guarantees that use-after-free of host
allocations will not result in values written by another process becoming
visible, the same guarantees must: be made by the Vulkan implementation for
device memory.
====
Applications can: request stronger robustness guarantees by enabling the
pname:robustBufferAccess feature as described in <<features>>.
ifdef::VK_VERSION_1_1[]
If the <<features-features-protectedMemory, protected memory>> feature is
supported, the implementation provides additional guarantees when invalid
usage occurs to prevent values in protected memory from being accessed or
inferred outside of protected operations, as described in
<<memory-protected-access-rules>>.
endif::VK_VERSION_1_1[]
Validation of correct API usage is left to validation layers.
Applications should: be developed with validation layers enabled, to help
@ -1164,6 +1173,14 @@ ifdef::VK_EXT_buffer_device_address[]
* ename:VK_ERROR_INVALID_DEVICE_ADDRESS_EXT A buffer creation failed
because the requested address is not available.
endif::VK_EXT_buffer_device_address[]
ifdef::VK_KHR_win32_surface,VK_EXT_full_screen_exclusive[]
* ename:VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT An operation on a
swapchain created with
ename:VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT failed as it
did not have exlusive full-screen access.
This may: occur due to implementation-dependent reasons, outside of the
application's control.
endif::VK_KHR_win32_surface,VK_EXT_full_screen_exclusive[]
If a command returns a run time error, unless otherwise specified any output
parameters will have undefined: contents, except that if the output

View File

@ -163,15 +163,11 @@ To obtain a function pointer for a physical-device-level command from a
device extension, an application can: use flink:vkGetInstanceProcAddr.
This function pointer may: point to dispatch code, which calls a different
real implementation for different sname:VkPhysicalDevice objects.
Behavior is undefined: if an extension physical-device command is called on
a physical device that does not support the extension.
Applications must: not use a slink:VkPhysicalDevice in any command added by
an extension or core version that is not supported by that physical device.
Device extensions may: define structures that can: be added to the
ptext:pNext chain of physical-device-level commands.
Behavior is undefined: if such an extension structure is passed to a
physical-device-level command for a physical device that does not support
the extension.
endif::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]

View File

@ -2404,7 +2404,6 @@ generates a primitive.
+
All index values must: be in the range [eq]#[0, N-1]#, where [eq]#N# is the
value specified by the code:OutputVertices execution mode.
Out-of-bounds index values result in undefined behavior.
+
The code:PrimitiveIndicesNV decoration must: only be used in mesh shaders.
+

View File

@ -86,7 +86,7 @@ in this Specification.
accomplish through the API, while *must not* means something that the
application is capable of expressing through the API, but that the
consequences of doing so are undefined: and potentially unrecoverable for
the implementation.
the implementation (see <<fundamentals-errors>>).
==================
Unless otherwise noted in the section heading, all sections and appendices

View File

@ -1392,12 +1392,11 @@ include::../api/structs/VkPhysicalDeviceProtectedMemoryProperties.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:protectedNoFault specifies whether the undefined: behavior may:
include process termination or device loss.
If pname:protectedNoFault is ename:VK_FALSE, undefined: behavior may:
include process termination or device loss.
If pname:protectedNoFault is ename:VK_TRUE, undefined: behavior will not
include process termination or device loss.
* pname:protectedNoFault specifies the behavior of the implementation when
<<memory-protected-access-rules, protected memory access rules>> are
broken.
If pname:protectedNoFault is ename:VK_TRUE, breaking those rules will
not result in process termination or device loss.
If the sname:VkPhysicalDeviceProtectedMemoryProperties structure is included
in the pname:pNext chain of slink:VkPhysicalDeviceProperties2, it is filled

View File

@ -2407,10 +2407,8 @@ include::../api/protos/vkFreeMemory.txt[]
Before freeing a memory object, an application must: ensure the memory
object is no longer in use by the device--for example by command buffers in
the _pending state_.
The memory can: remain bound to images or buffers at the time the memory
object is freed, but any further use of them (on host or device) for
anything other than destroying those objects will result in undefined:
behavior.
Memory can: be freed whilst still bound to resources, but those resources
must: not be used afterwards.
If there are still any bound images or buffers, the memory may: not be
immediately released by the implementation, but must: be released by the
time all bound images and buffers have been destroyed.
@ -2835,40 +2833,33 @@ Protected memory adds the following concepts:
can: be submitted
* Queue operations
** Unprotected queue operations
*** Any read from or write to protected memory during unprotected queue
operations results in undefined: behavior but is subject to the
inviolable rules below.
** Protected queue operations
[[memory-protected-access-rules]]
==== Protected Memory Access Rules
*** Any write to unprotected memory during protected queue operations
results in undefined: behavior but is subject to the inviolable rules
below.
*** Except for framebuffer-space pipeline stages, compute shader stage,
and transfer stage, any read from or write to protected memory during
protected queue operations results in undefined: behavior but is
subject to the inviolable rules below.
*** Any query during protected queue operations results in undefined:
behavior, but is subject to the inviolable rules below.
*** Any indirect command during protected queue operations results in
undefined: behavior but is subject to the inviolable rules below.
If slink:VkPhysicalDeviceProtectedMemoryProperties::pname:protectedNoFault
is ename:VK_FALSE, applications must: not perform any of the following
operations:
* Write to unprotected memory within protected queue operations.
* Access protected memory within protected queue operations other than in
framebuffer-space pipeline stages, the compute shader stage, or the
transfer stage.
* Perform a query within protected queue operations.
* Execute an indirect command within protected queue operations.
If slink:VkPhysicalDeviceProtectedMemoryProperties::pname:protectedNoFault
is ename:VK_TRUE, these operations are valid, but reads will return
undefined: values, and writes will either be dropped or store undefined:
values.
[[memory-protected-memory-undefined]]
==== Protected memory inviolable rules
Whether these operations are valid or not, or if any other invalid usage is
performed, the implementation must: guarantee that:
Implementations must: ensure that correct usage or incorrect usage by an
application does not affect the integrity of the memory protection system.
The implementation must: guarantee that:
* Protected device memory must: not be visible to the host.
* Protected device memory must: never be visible to the host.
* Values written to unprotected device memory must: not be a function of
data from protected memory.
Incorrect usage by an application of the memory protection system results in
undefined: behavior which may: include process termination or device loss.
values from protected memory.
endif::VK_VERSION_1_1[]
ifdef::VK_KHR_external_memory_capabilities+VK_ANDROID_external_memory_android_hardware_buffer[]

View File

@ -1986,3 +1986,7 @@ endif::VK_AMD_shader_info[]
ifdef::VK_NV_ray_tracing[]
include::VK_NV_ray_tracing/raytracing-pipelines.txt[]
endif::VK_NV_ray_tracing[]
ifdef::VK_EXT_pipeline_creation_feedback[]
include::VK_EXT_pipeline_creation_feedback/pipelines.txt[]
endif::VK_EXT_pipeline_creation_feedback[]

View File

@ -182,10 +182,8 @@ flink:vkCmdCopyQueryPoolResults does not include
ename:VK_QUERY_RESULT_WAIT_BIT, execution of flink:vkCmdCopyQueryPoolResults
may: happen-before the results of flink:vkCmdEndQuery are available.
After query pool creation, each query is in an undefined: state and must: be
reset prior to use.
After query pool creation, each query must: be reset before it is used.
Queries must: also be reset between uses.
Using a query that has not been reset will result in undefined: behavior.
ifdef::VK_VERSION_1_1,VK_KHR_device_group[]
@ -199,7 +197,7 @@ endif::VK_VERSION_1_1,VK_KHR_device_group[]
[open,refpage='vkCmdResetQueryPool',desc='Reset queries in a query pool',type='protos']
--
To reset a range of queries in a query pool, call:
To reset a range of queries in a query pool on a queue, call:
include::../api/protos/vkCmdResetQueryPool.txt[]
@ -227,6 +225,40 @@ unavailable.
include::../validity/protos/vkCmdResetQueryPool.txt[]
--
ifdef::VK_EXT_host_query_reset[]
[open,refpage='vkResetQueryPoolEXT',desc='Reset queries in a query pool',type='protos']
--
To reset a range of queries in a query pool on the host, call:
include::../api/protos/vkResetQueryPoolEXT.txt[]
* pname:queryPool is the handle of the query pool managing the queries
being reset.
* pname:firstQuery is the initial query index to reset.
* pname:queryCount is the number of queries to reset.
This command sets the status of query indices [eq]#[pname:firstQuery,
pname:firstQuery {plus} pname:queryCount - 1]# to unavailable.
.Valid Usage
****
* [[VUID-vkResetQueryPoolEXT-None-02665]]
The <<features-hostQueryReset,hostQueryReset>> feature must: be enabled
* [[VUID-vkResetQueryPoolEXT-firstQuery-02666]]
pname:firstQuery must: be less than the number of queries in
pname:queryPool
* [[VUID-vkResetQueryPoolEXT-firstQuery-02667]]
The sum of pname:firstQuery and pname:queryCount must: be less than or
equal to the number of queries in pname:queryPool
****
include::../validity/protos/vkResetQueryPoolEXT.txt[]
--
endif::VK_EXT_host_query_reset[]
Once queries are reset and ready for use, query commands can: be issued to a
command buffer.
Occlusion queries and pipeline statistics queries count events - drawn

View File

@ -2075,8 +2075,8 @@ image.
ifdef::VK_ANDROID_external_memory_android_hardware_buffer[]
However, the subresource layout of images in Android hardware buffer
external memory is not known until the image has been bound to memory, so
calling fname:vkGetImageSubresourceLayout for such an image before it has
been bound will result in undefined: behavior.
applications must: not call flink:vkGetImageSubresourceLayout for such an
image before it has been bound.
endif::VK_ANDROID_external_memory_android_hardware_buffer[]
.Valid Usage
@ -3548,7 +3548,7 @@ image array layer [eq]#(pname:baseArrayLayer {plus} i)# is face index
[eq]#(i mod 6)# of cube _i / 6_.
If the number of layers in the view, whether set explicitly in
pname:layerCount or implied by ename:VK_REMAINING_ARRAY_LAYERS, is not a
multiple of 6, behavior when indexing the last cube is undefined:.
multiple of 6, the last cube map in the array must: not be accessed.
pname:aspectMask must: be only ename:VK_IMAGE_ASPECT_COLOR_BIT,
ename:VK_IMAGE_ASPECT_DEPTH_BIT or ename:VK_IMAGE_ASPECT_STENCIL_BIT if
@ -4050,8 +4050,8 @@ include::../validity/structs/VkMemoryRequirements.txt[]
ifdef::VK_ANDROID_external_memory_android_hardware_buffer[]
The precise size of images that will be bound to external Android hardware
buffer memory is unknown until the memory has been imported or allocated, so
calling flink:vkGetImageMemoryRequirements with such an image before it has
been bound to memory will result in undefined: behavior.
applications must: not call flink:vkGetImageMemoryRequirements with such an
image before it has been bound to memory.
When importing Android hardware buffer memory, the pname:allocationSize can:
be determined by calling flink:vkGetAndroidHardwareBufferPropertiesANDROID.
When allocating new memory for an image that can: be exported to an Android

View File

@ -841,7 +841,7 @@ ifdef::VK_NV_compute_shader_derivatives[]
A derivative group for a compute shader is a single local workgroup.
endif::VK_NV_compute_shader_derivatives[]
Derivatives are undefined: for a sampled image instruction if the
Derivative values are undefined: for a sampled image instruction if the
instruction is in flow control that is not uniform across the derivative
group.

View File

@ -1240,15 +1240,7 @@ and these bindings can: be altered during the lifetime of the resource.
It is important to note that freeing a sname:VkDeviceMemory object with
fname:vkFreeMemory will not cause resources (or resource regions) bound to
the memory object to become unbound.
Access to resources that are bound to memory objects that have been freed
will result in undefined: behavior, potentially including application
termination.
Implementations must: ensure that no access to physical memory owned by the
system or another process will occur in this scenario.
In other words, accessing resources bound to freed memory may: result in
application termination, but must: not result in system termination or in
reading non-process-accessible memory.
Applications must: not access resources bound to memory that has been freed.
====
Sparse memory bindings execute on a queue that includes the
@ -1256,9 +1248,7 @@ ename:VK_QUEUE_SPARSE_BINDING_BIT bit.
Applications must: use <<synchronization,synchronization primitives>> to
guarantee that other queues do not access ranges of memory concurrently with
a binding change.
Accessing memory in a range while it is being rebound results in undefined:
behavior.
It is valid to access other ranges of the same resource while a bind
Applications can: access other ranges of the same resource while a bind
operation is executing.
[NOTE]

View File

@ -2593,12 +2593,9 @@ in the execution dependency.
====
Unlike fences or events, the act of waiting for a semaphore also unsignals
that semaphore.
If two operations are separately specified to wait for the same semaphore,
and there are no other execution dependencies between those operations,
behavior is undefined:.
An execution dependency must: be present that guarantees that the semaphore
unsignal operation for the first of those waits, happens-before the
semaphore is signalled again, and before the second unsignal operation.
Applications must: ensure that between two such wait operations, the
semaphore is signaled again, with execution dependencies used to ensure
these occur in order.
Semaphore waits and signals should thus occur in discrete 1:1 pairs.
====

View File

@ -594,9 +594,8 @@ ifdef::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
==== Layout Validation
If all planes of a _disjoint_ _multi-planar_ image are not in the same
<<resources-image-layouts,image layout>>, sampling the image with
<<samplers-YCbCr-conversion,sampler Y'C~B~C~R~ conversion>>, will result in
undefined: behavior.
<<resources-image-layouts,image layout>>, the image must: not be sampled
with <<samplers-YCbCr-conversion,sampler Y'C~B~C~R~ conversion>> enabled.
endif::VK_VERSION_1_1,VK_KHR_sampler_ycbcr_conversion[]
@ -1290,9 +1289,8 @@ There are a series of validations that the texel undergoes.
==== Texel Format Validation
If the image format of the code:OpTypeImage is not compatible with the
sname:VkImageView's pname:format, the effect of the write on the image
view's memory is undefined, but the write must: not access memory outside of
the image view.
sname:VkImageView's pname:format, the write causes the contents of the
image's memory to become undefined:.
[[textures-output-coordinate-validation]]
@ -1361,8 +1359,8 @@ These neighboring fragments are used to compute derivatives with the
assumption that the values of P in the neighborhood are piecewise linear.
It is further assumed that the values of P in the neighborhood are locally
continuous.
Therefore, computation of derivatives in non-uniform control flow has
undefined: behavior.
Applications must: not use derivative instructions in non-uniform control
flow.
[latexmath]
+++++++++++++++++++

View File

@ -116,11 +116,10 @@ For matrix types, outputs are written as an array of column vectors.
If any component of an output with an assigned transform feedback offset was
not written to by its shader, the value recorded for that component is
undefined.
The results of writing an output variable to a transform feedback buffer are
undefined if any component of that variable would be written at an offset
not aligned to the size of the component, or the component is less than 4
bytes in size.
undefined:.
All components of an output variable must: be written at an offset aligned
to the size of the component.
The size of each component of an output variable must: be at least 32-bits.
When capturing a vertex, any portion of the reserved storage not associated
with an output variable with an assigned transform feedback offset will be
unmodified.

View File

@ -83,13 +83,13 @@ def makeSubmit(submitName, required, target='html'):
# # Reorganize and rename them, and generate the diff spec
print('')
print('cd scripts')
print('cd scripts/htmldiff')
print('./htmldiff',
enQuote('../' + baseSpec),
enQuote('../' + newSpec),
enQuote('../../' + baseSpec),
enQuote('../../' + newSpec),
'>',
enQuote('../submit/html/diff-' + submitName + '.html'))
print('cd ..')
enQuote('../../submit/html/diff-' + submitName + '.html'))
print('cd ../../')
if __name__ == '__main__':
parser = argparse.ArgumentParser()

View File

@ -23,7 +23,7 @@ or otherwise, arising from or in connection with these materials.
This Specification has been created under the Khronos Intellectual Property
Rights Policy, which is Attachment A of the Khronos Group Membership
Agreement available at www.khronos.org/files/member_agreement.pdf, and which
Agreement available at https://www.khronos.org/files/member_agreement.pdf, and which
defines the terms 'Scope', 'Compliant Portion', and 'Necessary Patent Claims'.
Parties desiring to implement the Specification and make use of Khronos trademarks
in relation to that implementation, and receive reciprocal patent license protection

View File

@ -15,7 +15,7 @@
version="1.1"
id="svg8"
sodipodi:docname="commandbuffer_lifecycle.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)">
inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
<defs
id="defs2">
<marker
@ -33,21 +33,6 @@
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="marker5653"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path5651"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
@ -211,9 +196,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2"
inkscape:cx="274.30175"
inkscape:cy="131.46613"
inkscape:zoom="1.4142136"
inkscape:cx="405.79858"
inkscape:cy="139.11401"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
@ -226,10 +211,10 @@
fit-margin-top="1"
fit-margin-right="1"
fit-margin-bottom="1"
inkscape:window-width="1680"
inkscape:window-height="987"
inkscape:window-x="1672"
inkscape:window-y="-8"
inkscape:window-width="1920"
inkscape:window-height="1001"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
@ -501,12 +486,6 @@
id="path5559"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:0.39687499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.5875, 1.5875;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker5653)"
d="M 106.49479,15.744128 C 99.21875,45.645838 88.635415,41.541003 60.854164,41.541003"
id="path5561"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.39687496"

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -1,126 +0,0 @@
#ifndef VULKAN_ANDROID_H_
#define VULKAN_ANDROID_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_KHR_android_surface 1
struct ANativeWindow;
#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6
#define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface"
typedef VkFlags VkAndroidSurfaceCreateFlagsKHR;
typedef struct VkAndroidSurfaceCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkAndroidSurfaceCreateFlagsKHR flags;
struct ANativeWindow* window;
} VkAndroidSurfaceCreateInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkCreateAndroidSurfaceKHR)(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
VkInstance instance,
const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
#endif
#define VK_ANDROID_external_memory_android_hardware_buffer 1
struct AHardwareBuffer;
#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION 3
#define VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME "VK_ANDROID_external_memory_android_hardware_buffer"
typedef struct VkAndroidHardwareBufferUsageANDROID {
VkStructureType sType;
void* pNext;
uint64_t androidHardwareBufferUsage;
} VkAndroidHardwareBufferUsageANDROID;
typedef struct VkAndroidHardwareBufferPropertiesANDROID {
VkStructureType sType;
void* pNext;
VkDeviceSize allocationSize;
uint32_t memoryTypeBits;
} VkAndroidHardwareBufferPropertiesANDROID;
typedef struct VkAndroidHardwareBufferFormatPropertiesANDROID {
VkStructureType sType;
void* pNext;
VkFormat format;
uint64_t externalFormat;
VkFormatFeatureFlags formatFeatures;
VkComponentMapping samplerYcbcrConversionComponents;
VkSamplerYcbcrModelConversion suggestedYcbcrModel;
VkSamplerYcbcrRange suggestedYcbcrRange;
VkChromaLocation suggestedXChromaOffset;
VkChromaLocation suggestedYChromaOffset;
} VkAndroidHardwareBufferFormatPropertiesANDROID;
typedef struct VkImportAndroidHardwareBufferInfoANDROID {
VkStructureType sType;
const void* pNext;
struct AHardwareBuffer* buffer;
} VkImportAndroidHardwareBufferInfoANDROID;
typedef struct VkMemoryGetAndroidHardwareBufferInfoANDROID {
VkStructureType sType;
const void* pNext;
VkDeviceMemory memory;
} VkMemoryGetAndroidHardwareBufferInfoANDROID;
typedef struct VkExternalFormatANDROID {
VkStructureType sType;
void* pNext;
uint64_t externalFormat;
} VkExternalFormatANDROID;
typedef VkResult (VKAPI_PTR *PFN_vkGetAndroidHardwareBufferPropertiesANDROID)(VkDevice device, const struct AHardwareBuffer* buffer, VkAndroidHardwareBufferPropertiesANDROID* pProperties);
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryAndroidHardwareBufferANDROID)(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo, struct AHardwareBuffer** pBuffer);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkGetAndroidHardwareBufferPropertiesANDROID(
VkDevice device,
const struct AHardwareBuffer* buffer,
VkAndroidHardwareBufferPropertiesANDROID* pProperties);
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryAndroidHardwareBufferANDROID(
VkDevice device,
const VkMemoryGetAndroidHardwareBufferInfoANDROID* pInfo,
struct AHardwareBuffer** pBuffer);
#endif
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,58 +0,0 @@
#ifndef VULKAN_FUCHSIA_H_
#define VULKAN_FUCHSIA_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_FUCHSIA_imagepipe_surface 1
#define VK_FUCHSIA_IMAGEPIPE_SURFACE_SPEC_VERSION 1
#define VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME "VK_FUCHSIA_imagepipe_surface"
typedef VkFlags VkImagePipeSurfaceCreateFlagsFUCHSIA;
typedef struct VkImagePipeSurfaceCreateInfoFUCHSIA {
VkStructureType sType;
const void* pNext;
VkImagePipeSurfaceCreateFlagsFUCHSIA flags;
zx_handle_t imagePipeHandle;
} VkImagePipeSurfaceCreateInfoFUCHSIA;
typedef VkResult (VKAPI_PTR *PFN_vkCreateImagePipeSurfaceFUCHSIA)(VkInstance instance, const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateImagePipeSurfaceFUCHSIA(
VkInstance instance,
const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,58 +0,0 @@
#ifndef VULKAN_IOS_H_
#define VULKAN_IOS_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_MVK_ios_surface 1
#define VK_MVK_IOS_SURFACE_SPEC_VERSION 2
#define VK_MVK_IOS_SURFACE_EXTENSION_NAME "VK_MVK_ios_surface"
typedef VkFlags VkIOSSurfaceCreateFlagsMVK;
typedef struct VkIOSSurfaceCreateInfoMVK {
VkStructureType sType;
const void* pNext;
VkIOSSurfaceCreateFlagsMVK flags;
const void* pView;
} VkIOSSurfaceCreateInfoMVK;
typedef VkResult (VKAPI_PTR *PFN_vkCreateIOSSurfaceMVK)(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateIOSSurfaceMVK(
VkInstance instance,
const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,58 +0,0 @@
#ifndef VULKAN_MACOS_H_
#define VULKAN_MACOS_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_MVK_macos_surface 1
#define VK_MVK_MACOS_SURFACE_SPEC_VERSION 2
#define VK_MVK_MACOS_SURFACE_EXTENSION_NAME "VK_MVK_macos_surface"
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
typedef struct VkMacOSSurfaceCreateInfoMVK {
VkStructureType sType;
const void* pNext;
VkMacOSSurfaceCreateFlagsMVK flags;
const void* pView;
} VkMacOSSurfaceCreateInfoMVK;
typedef VkResult (VKAPI_PTR *PFN_vkCreateMacOSSurfaceMVK)(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateMacOSSurfaceMVK(
VkInstance instance,
const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,66 +0,0 @@
#ifndef VULKAN_METAL_H_
#define VULKAN_METAL_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_EXT_metal_surface 1
#ifdef __OBJC__
@class CAMetalLayer;
#else
typedef void CAMetalLayer;
#endif
#define VK_EXT_METAL_SURFACE_SPEC_VERSION 1
#define VK_EXT_METAL_SURFACE_EXTENSION_NAME "VK_EXT_metal_surface"
typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
typedef struct VkMetalSurfaceCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkMetalSurfaceCreateFlagsEXT flags;
const CAMetalLayer* pLayer;
} VkMetalSurfaceCreateInfoEXT;
typedef VkResult (VKAPI_PTR *PFN_vkCreateMetalSurfaceEXT)(VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT(
VkInstance instance,
const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,58 +0,0 @@
#ifndef VULKAN_VI_H_
#define VULKAN_VI_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_NN_vi_surface 1
#define VK_NN_VI_SURFACE_SPEC_VERSION 1
#define VK_NN_VI_SURFACE_EXTENSION_NAME "VK_NN_vi_surface"
typedef VkFlags VkViSurfaceCreateFlagsNN;
typedef struct VkViSurfaceCreateInfoNN {
VkStructureType sType;
const void* pNext;
VkViSurfaceCreateFlagsNN flags;
void* window;
} VkViSurfaceCreateInfoNN;
typedef VkResult (VKAPI_PTR *PFN_vkCreateViSurfaceNN)(VkInstance instance, const VkViSurfaceCreateInfoNN* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateViSurfaceNN(
VkInstance instance,
const VkViSurfaceCreateInfoNN* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,65 +0,0 @@
#ifndef VULKAN_WAYLAND_H_
#define VULKAN_WAYLAND_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_KHR_wayland_surface 1
#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 6
#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface"
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
typedef struct VkWaylandSurfaceCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkWaylandSurfaceCreateFlagsKHR flags;
struct wl_display* display;
struct wl_surface* surface;
} VkWaylandSurfaceCreateInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkCreateWaylandSurfaceKHR)(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
VkInstance instance,
const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR(
VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
struct wl_display* display);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,276 +0,0 @@
#ifndef VULKAN_WIN32_H_
#define VULKAN_WIN32_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_KHR_win32_surface 1
#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6
#define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface"
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
typedef struct VkWin32SurfaceCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkWin32SurfaceCreateFlagsKHR flags;
HINSTANCE hinstance;
HWND hwnd;
} VkWin32SurfaceCreateInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
VkInstance instance,
const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(
VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex);
#endif
#define VK_KHR_external_memory_win32 1
#define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32"
typedef struct VkImportMemoryWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkExternalMemoryHandleTypeFlagBits handleType;
HANDLE handle;
LPCWSTR name;
} VkImportMemoryWin32HandleInfoKHR;
typedef struct VkExportMemoryWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
const SECURITY_ATTRIBUTES* pAttributes;
DWORD dwAccess;
LPCWSTR name;
} VkExportMemoryWin32HandleInfoKHR;
typedef struct VkMemoryWin32HandlePropertiesKHR {
VkStructureType sType;
void* pNext;
uint32_t memoryTypeBits;
} VkMemoryWin32HandlePropertiesKHR;
typedef struct VkMemoryGetWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkDeviceMemory memory;
VkExternalMemoryHandleTypeFlagBits handleType;
} VkMemoryGetWin32HandleInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR(
VkDevice device,
const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo,
HANDLE* pHandle);
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR(
VkDevice device,
VkExternalMemoryHandleTypeFlagBits handleType,
HANDLE handle,
VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);
#endif
#define VK_KHR_win32_keyed_mutex 1
#define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1
#define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex"
typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR {
VkStructureType sType;
const void* pNext;
uint32_t acquireCount;
const VkDeviceMemory* pAcquireSyncs;
const uint64_t* pAcquireKeys;
const uint32_t* pAcquireTimeouts;
uint32_t releaseCount;
const VkDeviceMemory* pReleaseSyncs;
const uint64_t* pReleaseKeys;
} VkWin32KeyedMutexAcquireReleaseInfoKHR;
#define VK_KHR_external_semaphore_win32 1
#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32"
typedef struct VkImportSemaphoreWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkSemaphoreImportFlags flags;
VkExternalSemaphoreHandleTypeFlagBits handleType;
HANDLE handle;
LPCWSTR name;
} VkImportSemaphoreWin32HandleInfoKHR;
typedef struct VkExportSemaphoreWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
const SECURITY_ATTRIBUTES* pAttributes;
DWORD dwAccess;
LPCWSTR name;
} VkExportSemaphoreWin32HandleInfoKHR;
typedef struct VkD3D12FenceSubmitInfoKHR {
VkStructureType sType;
const void* pNext;
uint32_t waitSemaphoreValuesCount;
const uint64_t* pWaitSemaphoreValues;
uint32_t signalSemaphoreValuesCount;
const uint64_t* pSignalSemaphoreValues;
} VkD3D12FenceSubmitInfoKHR;
typedef struct VkSemaphoreGetWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkExternalSemaphoreHandleTypeFlagBits handleType;
} VkSemaphoreGetWin32HandleInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo);
typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHR(
VkDevice device,
const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo);
VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR(
VkDevice device,
const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo,
HANDLE* pHandle);
#endif
#define VK_KHR_external_fence_win32 1
#define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32"
typedef struct VkImportFenceWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkFence fence;
VkFenceImportFlags flags;
VkExternalFenceHandleTypeFlagBits handleType;
HANDLE handle;
LPCWSTR name;
} VkImportFenceWin32HandleInfoKHR;
typedef struct VkExportFenceWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
const SECURITY_ATTRIBUTES* pAttributes;
DWORD dwAccess;
LPCWSTR name;
} VkExportFenceWin32HandleInfoKHR;
typedef struct VkFenceGetWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkFence fence;
VkExternalFenceHandleTypeFlagBits handleType;
} VkFenceGetWin32HandleInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo);
typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceWin32HandleKHR(
VkDevice device,
const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo);
VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR(
VkDevice device,
const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo,
HANDLE* pHandle);
#endif
#define VK_NV_external_memory_win32 1
#define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
#define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32"
typedef struct VkImportMemoryWin32HandleInfoNV {
VkStructureType sType;
const void* pNext;
VkExternalMemoryHandleTypeFlagsNV handleType;
HANDLE handle;
} VkImportMemoryWin32HandleInfoNV;
typedef struct VkExportMemoryWin32HandleInfoNV {
VkStructureType sType;
const void* pNext;
const SECURITY_ATTRIBUTES* pAttributes;
DWORD dwAccess;
} VkExportMemoryWin32HandleInfoNV;
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV(
VkDevice device,
VkDeviceMemory memory,
VkExternalMemoryHandleTypeFlagsNV handleType,
HANDLE* pHandle);
#endif
#define VK_NV_win32_keyed_mutex 1
#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 1
#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex"
typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV {
VkStructureType sType;
const void* pNext;
uint32_t acquireCount;
const VkDeviceMemory* pAcquireSyncs;
const uint64_t* pAcquireKeys;
const uint32_t* pAcquireTimeoutMilliseconds;
uint32_t releaseCount;
const VkDeviceMemory* pReleaseSyncs;
const uint64_t* pReleaseKeys;
} VkWin32KeyedMutexAcquireReleaseInfoNV;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,66 +0,0 @@
#ifndef VULKAN_XCB_H_
#define VULKAN_XCB_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_KHR_xcb_surface 1
#define VK_KHR_XCB_SURFACE_SPEC_VERSION 6
#define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface"
typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
typedef struct VkXcbSurfaceCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkXcbSurfaceCreateFlagsKHR flags;
xcb_connection_t* connection;
xcb_window_t window;
} VkXcbSurfaceCreateInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
VkInstance instance,
const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(
VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
xcb_connection_t* connection,
xcb_visualid_t visual_id);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,66 +0,0 @@
#ifndef VULKAN_XLIB_H_
#define VULKAN_XLIB_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_KHR_xlib_surface 1
#define VK_KHR_XLIB_SURFACE_SPEC_VERSION 6
#define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface"
typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
typedef struct VkXlibSurfaceCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkXlibSurfaceCreateFlagsKHR flags;
Display* dpy;
Window window;
} VkXlibSurfaceCreateInfoKHR;
typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
VkInstance instance,
const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSurfaceKHR* pSurface);
VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(
VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
Display* dpy,
VisualID visualID);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,54 +0,0 @@
#ifndef VULKAN_XLIB_XRANDR_H_
#define VULKAN_XLIB_XRANDR_H_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2015-2019 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/
#define VK_EXT_acquire_xlib_display 1
#define VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION 1
#define VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME "VK_EXT_acquire_xlib_display"
typedef VkResult (VKAPI_PTR *PFN_vkAcquireXlibDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display);
typedef VkResult (VKAPI_PTR *PFN_vkGetRandROutputDisplayEXT)(VkPhysicalDevice physicalDevice, Display* dpy, RROutput rrOutput, VkDisplayKHR* pDisplay);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkAcquireXlibDisplayEXT(
VkPhysicalDevice physicalDevice,
Display* dpy,
VkDisplayKHR display);
VKAPI_ATTR VkResult VKAPI_CALL vkGetRandROutputDisplayEXT(
VkPhysicalDevice physicalDevice,
Display* dpy,
RROutput rrOutput,
VkDisplayKHR* pDisplay);
#endif
#ifdef __cplusplus
}
#endif
#endif

75
scripts/README.adoc Normal file
View File

@ -0,0 +1,75 @@
= Vulkan^(R)^ Specification Repository Scripts
This directory contains scripts used in building the Vulkan API
specification and related artifacts. For the most part, these scripts are
invoked from the top-level directory or from the API Registry in
../xml to build generated components of the specification.
Scripts in this directory include:
* genvk.py - Python script to generate Vulkan headers and some other
targets, using the generators described below.
* reg.py - Python tools to read a registry XML file and call into
generators to create headers and other types of output.
* conventions.py, vkconventions.py - API-specific parameters and
formatting / style conventions used by generators.
* generator.py - output generator base class.
** cgenerator.py - C header output generator.
** docgenerator.py - Asciidoc interface language include generator.
** extensionmetadocgenerator.py - Generator for Asciidoc extension
descriptions in spec appendices.
** hostsyncgenerator.py - Asciidoc host sync table generator.
** pygenerator.py - Generates python encoding of the API description.
** validitygenerator.py - Asciidoc validity language generator.
* checkXrefs - shell script to look for broken internal links in a
generated HTML specification.
* check_spec_links.py - validates a variety of markup and content in the
Asciidoctor specification source.
* extDependency.py - generate extension dependencies in Bash and Python
form for use when building the specification.
* genRelease, genspec.py - build HTML and PDF Specifications with a
variety of options to control target directories, extensions included
while building, etc.
* genRef.py, reflib.py - extract API reference pages from specification
source into single-page source documents.
* indexExt.py - generate HTML index of all extensions for inclusion into
the Vulkan registry index page.
* reflow.py, reflow_count.py - reflow specification source text to follow
style guidelines, and insert Valid Usage statements where they're
needed.
* test_check_spec_links.py, test_check_spec_links_api_specific.py,
test_entity_db.py - these are from another Khronos WG repository and are
unused by Vulkan at present.
* htmldiff/htmldiff - HTML diff script (see below).
* Retired/ - contains obsolete, unused, or single-purpose scripts. Not
maintained.
HTML Diff Script for Vulkan
===========================
This is a first cut at a script to compare Vulkan HTML specifications. Usage
is simply 'htmldiff file1.html file2.html > diff.html'. The script does not
copy CSS and images required by the input specs, so it's best to generate
the output in the same directory as one of the inputs. However, the script
must be invoked from the directory it is located within.
The scripts used require Python and Perl. Additionally, the python
'utidylib' module and the underlying libtidy C library are required,
which may make it challenging to run the scripts on non-Linux platforms
- I haven't checked and those requirements cannot be easily removed. On
Debian Linux, it may be necessary to install the 'python-utidylib' and
'libtidy' packages if they are not already present. I haven't checked
dependencies for other Linux distributions but they are probably
similar.
The scripts are taken from the code backing the
http://services.w3.org/htmldiff
website. 'htmldiff' is the Python driver script. 'htmldiff.pl' is the
Perl script which generates the diff after preprocessing of the input
HTML by 'htmldiff'. 'htmldiff.orig' is the original Python script from
the website, modified to run at the command line instead of as a CGI
script.

View File

@ -1,26 +0,0 @@
HTML Diff Script for Vulkan
===========================
This is a first cut at a script to compare Vulkan HTML specifications. Usage
is simply 'htmldiff file1.html file2.html > diff.html'. The script does not
copy CSS and images requires by the input specs, so it's best to generate
the output in the same directory as one of the inputs.
The scripts used require Python and Perl. Additionally, the python
'utidylib' module and the underlying libtidy C library are required,
which may make it challenging to run the scripts on non-Linux platforms
- I haven't checked and those requirements cannot be easily removed. On
Debian Linux, it may be necessary to install the 'python-utidylib' and
'libtidy' packages if they are not already present. I haven't checked
dependencies for other Linux distributions but they are probably
similar.
The scripts are taken from the code backing the
http://services.w3.org/htmldiff
website. 'htmldiff' is the Python driver script. 'htmldiff.pl' is the
Perl script which generates the diff after preprocessing of the input
HTML by 'htmldiff'. 'htmldiff.orig' is the original Python script from
the website, modified to run at the command line instead of as a CGI
script.

View File

@ -23,9 +23,9 @@ import copy, sys, string, re
def realignXML(fp):
patterns = [
[ '(^ *\<type .*)(category=[\'"]bitmask[\'"].*)', 58 ],
[ '(^ *\<enum [bv].*)(name=.*)', 28 ],
[ '(^ *\<enum [bv].*)(comment=.*)', 85 ]
[ r'(^ *\<type .*)(category=[\'"]bitmask[\'"].*)', 58 ],
[ r'(^ *\<enum [bv].*)(name=.*)', 28 ],
[ r'(^ *\<enum [bv].*)(comment=.*)', 85 ]
]
# Assemble compiled expressions to match and alignment columns

View File

@ -14,8 +14,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os,re,sys,pdb
from generator import *
import os
import re
import sys
from generator import (GeneratorOptions, OutputGenerator, noneStr,
regSortFeatures, write)
# CGeneratorOptions - subclass of GeneratorOptions.
#
@ -51,9 +54,16 @@ from generator import *
# parameter on a separate line
# alignFuncParam - if nonzero and parameters are being put on a
# separate line, align parameter names at the specified column
# genEnumBeginEndRange - True if BEGIN_RANGE / END_RANGE macros should
# be generated for enumerated types
# genAliasMacro - True if the OpenXR alias macro should be generated
# for aliased types (unclear what other circumstances this is useful)
# aliasMacro - alias macro to inject when genAliasMacro is True
class CGeneratorOptions(GeneratorOptions):
"""Represents options during C interface generation for headers"""
def __init__(self,
conventions = None,
filename = None,
directory = '.',
apiname = None,
@ -76,8 +86,12 @@ class CGeneratorOptions(GeneratorOptions):
apientryp = '',
indentFuncProto = True,
indentFuncPointer = False,
alignFuncParam = 0):
GeneratorOptions.__init__(self, filename, directory, apiname, profile,
alignFuncParam = 0,
genEnumBeginEndRange = False,
genAliasMacro = False,
aliasMacro = ''
):
GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
versions, emitversions, defaultExtensions,
addExtensions, removeExtensions,
emitExtensions, sortProcedure)
@ -93,6 +107,9 @@ class CGeneratorOptions(GeneratorOptions):
self.indentFuncProto = indentFuncProto
self.indentFuncPointer = indentFuncPointer
self.alignFuncParam = alignFuncParam
self.genEnumBeginEndRange = genEnumBeginEndRange
self.genAliasMacro = genAliasMacro
self.aliasMacro = aliasMacro
# COutputGenerator - subclass of OutputGenerator.
# Generates C-language API interfaces.
@ -116,21 +133,25 @@ class COutputGenerator(OutputGenerator):
TYPE_SECTIONS = ['include', 'define', 'basetype', 'handle', 'enum',
'group', 'bitmask', 'funcpointer', 'struct']
ALL_SECTIONS = TYPE_SECTIONS + ['commandPointer', 'command']
def __init__(self,
errFile = sys.stderr,
warnFile = sys.stderr,
diagFile = sys.stdout):
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
# Internal state - accumulators for different inner block text
self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
#
self.sections = {section: [] for section in self.ALL_SECTIONS}
self.feature_not_empty = False
self.need_platform_include = False
self.may_alias = None
def beginFile(self, genOpts):
OutputGenerator.beginFile(self, genOpts)
# C-specific
#
# Multiple inclusion protection & C++ wrappers.
if (genOpts.protectFile and self.genOpts.filename):
headerSym = re.sub('\.h', '_h_',
if genOpts.protectFile and self.genOpts.filename:
headerSym = re.sub(r'\.h', '_h_',
os.path.basename(self.genOpts.filename)).upper()
write('#ifndef', headerSym, file=self.outFile)
write('#define', headerSym, '1', file=self.outFile)
@ -139,26 +160,12 @@ class COutputGenerator(OutputGenerator):
write('extern "C" {', file=self.outFile)
write('#endif', file=self.outFile)
self.newline()
#
# User-supplied prefix text, if any (list of strings)
if (genOpts.prefixText):
if genOpts.prefixText:
for s in genOpts.prefixText:
write(s, file=self.outFile)
#
# Some boilerplate describing what was generated - this
# will probably be removed later since the extensions
# pattern may be very long.
# write('/* Generated C header for:', file=self.outFile)
# write(' * API:', genOpts.apiname, file=self.outFile)
# if (genOpts.profile):
# write(' * Profile:', genOpts.profile, file=self.outFile)
# write(' * Versions considered:', genOpts.versions, file=self.outFile)
# write(' * Versions emitted:', genOpts.emitversions, file=self.outFile)
# write(' * Default extensions included:', genOpts.defaultExtensions, file=self.outFile)
# write(' * Additional extensions included:', genOpts.addExtensions, file=self.outFile)
# write(' * Extensions removed:', genOpts.removeExtensions, file=self.outFile)
# write(' * Extensions emitted:', genOpts.emitExtensions, file=self.outFile)
# write(' */', file=self.outFile)
def endFile(self):
# C-specific
# Finish C++ wrapper and multiple inclusion protection
@ -166,11 +173,12 @@ class COutputGenerator(OutputGenerator):
write('#ifdef __cplusplus', file=self.outFile)
write('}', file=self.outFile)
write('#endif', file=self.outFile)
if (self.genOpts.protectFile and self.genOpts.filename):
if self.genOpts.protectFile and self.genOpts.filename:
self.newline()
write('#endif', file=self.outFile)
# Finish processing in superclass
OutputGenerator.endFile(self)
def beginFeature(self, interface, emit):
# Start processing in superclass
OutputGenerator.beginFeature(self, interface, emit)
@ -178,55 +186,68 @@ class COutputGenerator(OutputGenerator):
# Accumulate includes, defines, types, enums, function pointer typedefs,
# end function prototypes separately for this feature. They're only
# printed in endFeature().
self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
self.sections = {section: [] for section in self.ALL_SECTIONS}
self.feature_not_empty = False
def endFeature(self):
# C-specific
# Actually write the interface to the output file.
if (self.emit):
self.newline()
if (self.genOpts.protectFeature):
write('#ifndef', self.featureName, file=self.outFile)
# If type declarations are needed by other features based on
# this one, it may be necessary to suppress the ExtraProtect,
# or move it below the 'for section...' loop.
if (self.featureExtraProtect != None):
write('#ifdef', self.featureExtraProtect, file=self.outFile)
write('#define', self.featureName, '1', file=self.outFile)
for section in self.TYPE_SECTIONS:
contents = self.sections[section]
if contents:
write('\n'.join(contents), file=self.outFile)
if self.emit:
if self.feature_not_empty:
if self.genOpts.conventions.writeFeature(self.featureExtraProtect, self.genOpts.filename):
self.newline()
if (self.genOpts.genFuncPointers and self.sections['commandPointer']):
write('\n'.join(self.sections['commandPointer']), file=self.outFile)
self.newline()
if (self.sections['command']):
if (self.genOpts.protectProto):
write(self.genOpts.protectProto,
self.genOpts.protectProtoStr, file=self.outFile)
write('\n'.join(self.sections['command']), end='', file=self.outFile)
if (self.genOpts.protectProto):
write('#endif', file=self.outFile)
else:
if self.genOpts.protectFeature:
write('#ifndef', self.featureName, file=self.outFile)
# If type declarations are needed by other features based on
# this one, it may be necessary to suppress the ExtraProtect,
# or move it below the 'for section...' loop.
if self.featureExtraProtect is not None:
write('#ifdef', self.featureExtraProtect, file=self.outFile)
self.newline()
if (self.featureExtraProtect != None):
write('#endif /*', self.featureExtraProtect, '*/', file=self.outFile)
if (self.genOpts.protectFeature):
write('#endif /*', self.featureName, '*/', file=self.outFile)
write('#define', self.featureName, '1', file=self.outFile)
for section in self.TYPE_SECTIONS:
# OpenXR:
# If we need the explicit include of the external platform header,
# put it right before the function pointer definitions
if section == "funcpointer" and self.need_platform_include:
write('// Include for OpenXR Platform-Specific Types', file=self.outFile)
write('#include "openxr_platform.h"', file=self.outFile)
self.newline()
self.need_platform_include = False
contents = self.sections[section]
if contents:
write('\n'.join(contents), file=self.outFile)
if self.genOpts.genFuncPointers and self.sections['commandPointer']:
write('\n'.join(self.sections['commandPointer']), file=self.outFile)
self.newline()
if self.sections['command']:
if self.genOpts.protectProto:
write(self.genOpts.protectProto,
self.genOpts.protectProtoStr, file=self.outFile)
write('\n'.join(self.sections['command']), end='', file=self.outFile)
if self.genOpts.protectProto:
write('#endif', file=self.outFile)
else:
self.newline()
if self.featureExtraProtect is not None:
write('#endif /*', self.featureExtraProtect, '*/', file=self.outFile)
if self.genOpts.protectFeature:
write('#endif /*', self.featureName, '*/', file=self.outFile)
# Finish processing in superclass
OutputGenerator.endFeature(self)
#
# Append a definition to the specified section
def appendSection(self, section, text):
# self.sections[section].append('SECTION: ' + section + '\n')
self.sections[section].append(text)
# self.logMsg('diag', 'appendSection(section =', section, 'text =', text)
#
self.feature_not_empty = True
# Type generation
def genType(self, typeinfo, name, alias):
OutputGenerator.genType(self, typeinfo, name, alias)
typeElem = typeinfo.elem
# Vulkan:
# Determine the category of the type, and the type section to add
# its definition to.
# 'funcpointer' is added to the 'struct' section as a workaround for
@ -238,11 +259,12 @@ class COutputGenerator(OutputGenerator):
else:
section = category
if category == 'struct' or category == 'union':
if category in ('struct', 'union'):
# If the type is a struct type, generate it using the
# special-purpose generator.
self.genStruct(typeinfo, name, alias)
else:
# OpenXR: this section was not under 'else:' previously, just fell through
if alias:
# If the type is an alias, just emit a typedef declaration
body = 'typedef ' + alias + ' ' + name + ';\n'
@ -252,17 +274,65 @@ class COutputGenerator(OutputGenerator):
# If the resulting text is an empty string, don't emit it.
body = noneStr(typeElem.text)
for elem in typeElem:
if (elem.tag == 'apientry'):
if elem.tag == 'apientry':
body += self.genOpts.apientry + noneStr(elem.tail)
else:
body += noneStr(elem.text) + noneStr(elem.tail)
if body:
# Add extra newline after multi-line entries.
if '\n' in body[0:-1]:
body += '\n'
self.appendSection(section, body)
#
# Protection string generation
# Protection strings are the strings defining the OS/Platform/Graphics
# requirements for a given OpenXR command. When generating the
# language header files, we need to make sure the items specific to a
# graphics API or OS platform are properly wrapped in #ifs.
def genProtectString(self, protect_str):
protect_if_str = ''
protect_end_str = ''
protect_list = []
if protect_str:
if ',' in protect_str:
protect_list.extend(protect_str.split(","))
protect_def_str = ''
count = 0
for protect_define in protect_list:
if count > 0:
protect_def_str += ' &&'
protect_def_str += ' defined(%s)' % protect_define
count = count + 1
count = count + 1
protect_if_str = '#if'
protect_if_str += protect_def_str
protect_if_str += '\n'
protect_end_str = '#endif //'
protect_end_str += protect_def_str
protect_end_str += '\n'
else:
protect_if_str += '#ifdef %s\n' % protect_str
protect_end_str += '#endif // %s\n' % protect_str
return (protect_if_str, protect_end_str)
def typeMayAlias(self, typeName):
if not self.may_alias:
# First time we've asked if a type may alias.
# So, let's populate the set of all names of types that may.
# Everyone with an explicit mayalias="true"
self.may_alias = set(typeName
for typeName, data in self.registry.typedict.items()
if data.elem.get('mayalias') == 'true')
# Every type mentioned in some other type's parentstruct attribute.
self.may_alias.update(set(x for x in
[otherType.elem.get('parentstruct')
for _, otherType in self.registry.typedict.items()]
if x is not None
))
return typeName in self.may_alias
# Struct (e.g. C "struct" type) generation.
# This is a special case of the <type> tag where the contents are
# interpreted as a set of <member> tags instead of freeform C
@ -270,7 +340,7 @@ class COutputGenerator(OutputGenerator):
# tags - they are a declaration of a struct or union member.
# Only simple member declarations are supported (no nested
# structs etc.)
# If alias != None, then this struct aliases another; just
# If alias is not None, then this struct aliases another; just
# generate a typedef of that alias.
def genStruct(self, typeinfo, typeName, alias):
OutputGenerator.genStruct(self, typeinfo, typeName, alias)
@ -280,127 +350,65 @@ class COutputGenerator(OutputGenerator):
if alias:
body = 'typedef ' + alias + ' ' + typeName + ';\n'
else:
body = 'typedef ' + typeElem.get('category') + ' ' + typeName + ' {\n'
body = ''
(protect_begin, protect_end) = self.genProtectString(typeElem.get('protect'))
if protect_begin:
body += protect_begin
body += 'typedef ' + typeElem.get('category')
targetLen = 0;
# This is an OpenXR-specific alternative where aliasing refers
# to an inheritance hierarchy of types rather than C-level type
# aliases.
if self.genOpts.genAliasMacro and self.typeMayAlias(typeName):
body += ' ' + self.genOpts.aliasMacro
body += ' ' + typeName + ' {\n'
targetLen = 0
for member in typeElem.findall('.//member'):
targetLen = max(targetLen, self.getCParamTypeLength(member))
for member in typeElem.findall('.//member'):
body += self.makeCParamDecl(member, targetLen + 4)
body += ';\n'
body += '} ' + typeName + ';\n'
if protect_end:
body += protect_end
self.appendSection('struct', body)
#
# Group (e.g. C "enum" type) generation.
# These are concatenated together with other types.
# If alias != None, it is the name of another group type
# If alias is not None, it is the name of another group type
# which aliases this type; just generate that alias.
def genGroup(self, groupinfo, groupName, alias = None):
OutputGenerator.genGroup(self, groupinfo, groupName, alias)
groupElem = groupinfo.elem
if alias:
# If the group name is aliased, just emit a typedef declaration
# for the alias.
body = 'typedef ' + alias + ' ' + groupName + ';\n'
else:
self.logMsg('diag', 'CGenerator.genGroup group =', groupName, 'alias =', alias)
# Otherwise, emit an actual enumerated type declaration
expandName = re.sub(r'([0-9a-z_])([A-Z0-9])',r'\1_\2',groupName).upper()
expandPrefix = expandName
expandSuffix = ''
expandSuffixMatch = re.search(r'[A-Z][A-Z]+$',groupName)
if expandSuffixMatch:
expandSuffix = '_' + expandSuffixMatch.group()
# Strip off the suffix from the prefix
expandPrefix = expandName.rsplit(expandSuffix, 1)[0]
# Prefix
body = "\ntypedef enum " + groupName + " {\n"
# @@ Should use the type="bitmask" attribute instead
isEnum = ('FLAG_BITS' not in expandPrefix)
# Get a list of nested 'enum' tags.
enums = groupElem.findall('enum')
# Check for and report duplicates, and return a list with them
# removed.
enums = self.checkDuplicateEnums(enums)
# Loop over the nested 'enum' tags. Keep track of the minimum and
# maximum numeric values, if they can be determined; but only for
# core API enumerants, not extension enumerants. This is inferred
# by looking for 'extends' attributes.
minName = None
# Accumulate non-numeric enumerant values separately and append
# them following the numeric values, to allow for aliases.
# NOTE: this doesn't do a topological sort yet, so aliases of
# aliases can still get in the wrong order.
aliasText = ""
for elem in enums:
# Convert the value to an integer and use that to track min/max.
(numVal,strVal) = self.enumToValue(elem, True)
name = elem.get('name')
# Extension enumerants are only included if they are required
if self.isEnumRequired(elem):
decl = " " + name + " = " + strVal + ",\n"
if numVal != None:
body += decl
else:
aliasText += decl
# Don't track min/max for non-numbers (numVal == None)
if isEnum and numVal != None and elem.get('extends') is None:
if minName == None:
minName = maxName = name
minValue = maxValue = numVal
elif numVal < minValue:
minName = name
minValue = numVal
elif numVal > maxValue:
maxName = name
maxValue = numVal
# Now append the non-numeric enumerant values
body += aliasText
# Generate min/max value tokens and a range-padding enum. Need some
# additional padding to generate correct names...
if isEnum:
body += " " + expandPrefix + "_BEGIN_RANGE" + expandSuffix + " = " + minName + ",\n"
body += " " + expandPrefix + "_END_RANGE" + expandSuffix + " = " + maxName + ",\n"
body += " " + expandPrefix + "_RANGE_SIZE" + expandSuffix + " = (" + maxName + " - " + minName + " + 1),\n"
body += " " + expandPrefix + "_MAX_ENUM" + expandSuffix + " = 0x7FFFFFFF\n"
# Postfix
body += "} " + groupName + ";"
# After either enumerated type or alias paths, add the declaration
# to the appropriate section for the group being defined.
if groupElem.get('type') == 'bitmask':
section = 'bitmask'
else:
section = 'group'
self.appendSection(section, body)
if alias:
# If the group name is aliased, just emit a typedef declaration
# for the alias.
body = 'typedef ' + alias + ' ' + groupName + ';\n'
self.appendSection(section, body)
else:
(section, body) = self.buildEnumCDecl(self.genOpts.genEnumBeginEndRange, groupinfo, groupName)
self.appendSection(section, "\n" + body)
# Enumerant generation
# <enum> tags may specify their values in several ways, but are usually
# just integers.
def genEnum(self, enuminfo, name, alias):
OutputGenerator.genEnum(self, enuminfo, name, alias)
(numVal,strVal) = self.enumToValue(enuminfo.elem, False)
(_, strVal) = self.enumToValue(enuminfo.elem, False)
body = '#define ' + name.ljust(33) + ' ' + strVal
self.appendSection('enum', body)
#
# Command generation
def genCmd(self, cmdinfo, name, alias):
OutputGenerator.genCmd(self, cmdinfo, name, alias)
@ -413,5 +421,5 @@ class COutputGenerator(OutputGenerator):
prefix = ''
decls = self.makeCDecls(cmdinfo.elem)
self.appendSection('command', prefix + decls[0] + '\n')
if (self.genOpts.genFuncPointers):
if self.genOpts.genFuncPointers:
self.appendSection('commandPointer', decls[1])

132
scripts/conventions.py Normal file
View File

@ -0,0 +1,132 @@
#!/usr/bin/python3 -i
#
# Copyright (c) 2013-2019 The Khronos Group Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Base class for working-group-specific style conventions,
# used in generation.
from abc import ABC, abstractmethod
class ConventionsBase(ABC):
"""WG-specific conventions."""
@abstractmethod
def formatExtension(self, name):
"""Mark up a name as an extension for the spec."""
raise NotImplementedError
@property
@abstractmethod
def null(self):
"""Preferred spelling of NULL."""
raise NotImplementedError
def makeProseList(self, elements, connective='and'):
"""Make a (comma-separated) list for use in prose.
Adds a connective (by default, 'and')
before the last element if there are more than 1.
Override with a different method or different call to
_implMakeProseList if you want to add a comma for two elements,
or not use a serial comma.
"""
return self._implMakeProseList(elements, connective)
@property
def struct_macro(self):
"""Get the appropriate format macro for a structure.
May override.
"""
return 'sname:'
def makeStructName(self, name):
"""Prepend the appropriate format macro for a structure to a structure type name.
Uses struct_macro, so just override that if you want to change behavior.
"""
return self.struct_macro + name
@property
def external_macro(self):
"""Get the appropriate format macro for an external type like uint32_t.
May override.
"""
return 'basetype:'
def makeExternalTypeName(self, name):
"""Prepend the appropriate format macro for an external type like uint32_t to a type name.
Uses external_macro, so just override that if you want to change behavior.
"""
return self.external_macro + name
def _implMakeProseList(self, elements, connective, comma_for_two_elts=False, serial_comma=True):
"""Internal-use implementation to make a (comma-separated) list for use in prose.
Adds a connective (by default, 'and')
before the last element if there are more than 1,
and only includes commas if there are more than 2
(if comma_for_two_elts is False).
Don't edit these defaults, override self.makeProseList().
"""
assert(serial_comma) # didn't implement what we didn't need
my_elts = list(elements)
if len(my_elts) > 1:
my_elts[-1] = '{} {}'.format(connective, my_elts[-1])
if not comma_for_two_elts and len(my_elts) <= 2:
return ' '.join(my_elts)
return ', '.join(my_elts)
@property
@abstractmethod
def file_suffix(self):
"""Return suffix of generated Asciidoctor files"""
raise NotImplementedError
@property
@abstractmethod
def api_name(self):
"""Return API name"""
raise NotImplementedError
@property
@abstractmethod
def api_prefix(self):
"""Return API token prefix"""
raise NotImplementedError
@property
@abstractmethod
def api_version_prefix(self):
"""Return API core version token prefix"""
raise NotImplementedError
@property
@abstractmethod
def KHR_prefix(self):
"""Return extension name prefix for KHR extensions"""
raise NotImplementedError
@property
@abstractmethod
def EXT_prefix(self):
"""Return extension name prefix for EXT extensions"""
raise NotImplementedError

View File

@ -14,37 +14,42 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os,re,sys
from generator import *
import sys
from generator import GeneratorOptions, OutputGenerator, regSortFeatures, noneStr, write
# DocGeneratorOptions - subclass of GeneratorOptions.
#
# Shares many members with CGeneratorOptions, since
# both are writing C-style declarations:
#
# prefixText - list of strings to prefix generated header with
# (usually a copyright statement + calling convention macros).
# apicall - string to use for the function declaration prefix,
# such as APICALL on Windows.
# apientry - string to use for the calling convention macro,
# in typedefs, such as APIENTRY.
# apientryp - string to use for the calling convention macro
# in function pointer typedefs, such as APIENTRYP.
# directory - directory into which to generate include files
# indentFuncProto - True if prototype declarations should put each
# parameter on a separate line
# indentFuncPointer - True if typedefed function pointers should put each
# parameter on a separate line
# alignFuncParam - if nonzero and parameters are being put on a
# separate line, align parameter names at the specified column
#
# Additional members:
# expandEnumerants - if True, add BEGIN/END_RANGE macros in enumerated
# type declarations
#
class DocGeneratorOptions(GeneratorOptions):
"""Represents options during C interface generation for Asciidoc"""
"""DocGeneratorOptions - subclass of GeneratorOptions.
Shares many members with CGeneratorOptions, since
both are writing C-style declarations:
prefixText - list of strings to prefix generated header with
(usually a copyright statement + calling convention macros).
apicall - string to use for the function declaration prefix,
such as APICALL on Windows.
apientry - string to use for the calling convention macro,
in typedefs, such as APIENTRY.
apientryp - string to use for the calling convention macro
in function pointer typedefs, such as APIENTRYP.
directory - directory into which to generate include files
indentFuncProto - True if prototype declarations should put each
parameter on a separate line
indentFuncPointer - True if typedefed function pointers should put each
parameter on a separate line
alignFuncParam - if nonzero and parameters are being put on a
separate line, align parameter names at the specified column
Additional members:
expandEnumerants - if True, add BEGIN/END_RANGE macros in enumerated
type declarations
secondaryInclude - if True, add secondary (no xref anchor) versions
of generated files
"""
def __init__(self,
conventions = None,
filename = None,
directory = '.',
apiname = None,
@ -63,8 +68,9 @@ class DocGeneratorOptions(GeneratorOptions):
indentFuncProto = True,
indentFuncPointer = False,
alignFuncParam = 0,
secondaryInclude = False,
expandEnumerants = True):
GeneratorOptions.__init__(self, filename, directory, apiname, profile,
GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
versions, emitversions, defaultExtensions,
addExtensions, removeExtensions,
emitExtensions, sortProcedure)
@ -75,12 +81,13 @@ class DocGeneratorOptions(GeneratorOptions):
self.indentFuncProto = indentFuncProto
self.indentFuncPointer = indentFuncPointer
self.alignFuncParam = alignFuncParam
self.secondaryInclude = secondaryInclude
self.expandEnumerants = expandEnumerants
# DocOutputGenerator - subclass of OutputGenerator.
# Generates AsciiDoc includes with C-language API interfaces, for reference
# pages and the Vulkan specification. Similar to COutputGenerator, but
# each interface is written into a different file as determined by the
# pages and the corresponding specification. Similar to COutputGenerator,
# but each interface is written into a different file as determined by the
# options, only actual C types are emitted, and none of the boilerplate
# preprocessor code is emitted.
#
@ -99,23 +106,37 @@ class DocGeneratorOptions(GeneratorOptions):
# genCmd(cmdinfo)
class DocOutputGenerator(OutputGenerator):
"""Generate specified API interfaces in a specific style, such as a C header"""
def __init__(self,
errFile = sys.stderr,
warnFile = sys.stderr,
diagFile = sys.stdout):
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
#
# Keep track of all extension numbers
self.extension_numbers = set()
def beginFile(self, genOpts):
OutputGenerator.beginFile(self, genOpts)
def endFile(self):
OutputGenerator.endFile(self)
def beginFeature(self, interface, emit):
# Start processing in superclass
OutputGenerator.beginFeature(self, interface, emit)
# Verify that each extension has a unique number during doc generation
extension_number = interface.get('number')
if extension_number is not None and extension_number != "0":
if extension_number in self.extension_numbers:
self.logMsg('error', 'Duplicate extension number ', extension_number, ' detected in feature ', interface.get('name'), '\n')
exit(1)
else:
self.extension_numbers.add(extension_number)
def endFeature(self):
# Finish processing in superclass
OutputGenerator.endFeature(self)
#
# Generate an include file
#
# directory - subdirectory to put file in
@ -132,24 +153,40 @@ class DocOutputGenerator(OutputGenerator):
fp = open(filename, 'w', encoding='utf-8')
# Asciidoc anchor
write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
write(self.genOpts.conventions.warning_comment, file=fp)
write('[[{0},{0}]]'.format(basename), file=fp)
write('[source,c++]', file=fp)
write('----', file=fp)
write(contents, file=fp)
write('----', file=fp)
fp.close()
if self.genOpts.secondaryInclude:
# Create secondary no cross-reference include file
filename = directory + '/' + basename + '.no-xref.txt'
self.logMsg('diag', '# Generating include file:', filename)
fp = open(filename, 'w', encoding='utf-8')
# Asciidoc anchor
write(self.genOpts.conventions.warning_comment, file=fp)
write('// Include this no-xref version without cross reference id for multiple includes of same file', file=fp)
write('[source,c++]', file=fp)
write('----', file=fp)
write(contents, file=fp)
write('----', file=fp)
fp.close()
#
# Type generation
def genType(self, typeinfo, name, alias):
OutputGenerator.genType(self, typeinfo, name, alias)
typeElem = typeinfo.elem
# If the type is a struct type, traverse the imbedded <member> tags
# If the type is a struct type, traverse the embedded <member> tags
# generating a structure. Otherwise, emit the tag text.
category = typeElem.get('category')
body = ''
if category == 'struct' or category == 'union':
if category in ('struct', 'union'):
# If the type is a struct type, generate it using the
# special-purpose generator.
self.genStruct(typeinfo, name, alias)
@ -165,13 +202,13 @@ class DocOutputGenerator(OutputGenerator):
# If the resulting text is an empty string, don't emit it.
body = noneStr(typeElem.text)
for elem in typeElem:
if (elem.tag == 'apientry'):
if elem.tag == 'apientry':
body += self.genOpts.apientry + noneStr(elem.tail)
else:
body += noneStr(elem.text) + noneStr(elem.tail)
if body:
if (category in OutputGenerator.categoryToPath.keys()):
if category in OutputGenerator.categoryToPath:
self.writeInclude(OutputGenerator.categoryToPath[category],
name, body + '\n')
else:
@ -179,7 +216,7 @@ class DocOutputGenerator(OutputGenerator):
name, '- bad category: ', category)
else:
self.logMsg('diag', '# NOT writing empty include file for type', name)
#
# Struct (e.g. C "struct" type) generation.
# This is a special case of the <type> tag where the contents are
# interpreted as a set of <member> tags instead of freeform C
@ -187,7 +224,7 @@ class DocOutputGenerator(OutputGenerator):
# tags - they are a declaration of a struct or union member.
# Only simple member declarations are supported (no nested
# structs etc.)
# If alias != None, then this struct aliases another; just
# If alias is not None, then this struct aliases another; just
# generate a typedef of that alias.
def genStruct(self, typeinfo, typeName, alias):
OutputGenerator.genStruct(self, typeinfo, typeName, alias)
@ -199,8 +236,8 @@ class DocOutputGenerator(OutputGenerator):
else:
body = 'typedef ' + typeElem.get('category') + ' ' + typeName + ' {\n'
targetLen = 0;
for member in typeinfo.elem.findall('.//member'):
targetLen = 0
for member in typeElem.findall('.//member'):
targetLen = max(targetLen, self.getCParamTypeLength(member))
for member in typeElem.findall('.//member'):
body += self.makeCParamDecl(member, targetLen + 4)
@ -208,117 +245,48 @@ class DocOutputGenerator(OutputGenerator):
body += '} ' + typeName + ';'
self.writeInclude('structs', typeName, body)
#
# Group (e.g. C "enum" type) generation.
# These are concatenated together with other types.
# If alias != None, it is the name of another group type
# If alias is not None, it is the name of another group type
# which aliases this type; just generate that alias.
def genGroup(self, groupinfo, groupName, alias):
OutputGenerator.genGroup(self, groupinfo, groupName, alias)
groupElem = groupinfo.elem
if alias:
filename = groupName
# If the group name is aliased, just emit a typedef declaration
# for the alias.
body = 'typedef ' + alias + ' ' + groupName + ';\n'
else:
filename = groupName
# See if we need min/max/num/padding at end
expand = self.genOpts.expandEnumerants
(_, body) = self.buildEnumCDecl(expand, groupinfo, groupName)
if expand:
expandName = re.sub(r'([0-9a-z_])([A-Z0-9][^A-Z0-9]?)',r'\1_\2',groupName).upper()
isEnum = ('FLAG_BITS' not in expandName)
expandPrefix = expandName
expandSuffix = ''
# Look for a suffix
expandSuffixMatch = re.search(r'[A-Z][A-Z]+$',groupName)
if expandSuffixMatch:
expandSuffix = '_' + expandSuffixMatch.group()
# Strip off the suffix from the prefix
expandPrefix = expandName.rsplit(expandSuffix, 1)[0]
# Prefix
body = "typedef enum " + groupName + " {\n"
# Get a list of nested 'enum' tags.
enums = groupElem.findall('enum')
# Check for and report duplicates, and return a list with them
# removed.
enums = self.checkDuplicateEnums(enums)
# Loop over the nested 'enum' tags. Keep track of the minimum and
# maximum numeric values, if they can be determined.
minName = None
# Accumulate non-numeric enumerant values separately and append
# them following the numeric values, to allow for aliases.
# NOTE: this doesn't do a topological sort yet, so aliases of
# aliases can still get in the wrong order.
aliasText = ""
for elem in enums:
# Convert the value to an integer and use that to track min/max.
(numVal,strVal) = self.enumToValue(elem, True)
name = elem.get('name')
# Extension enumerants are only included if they are required
if self.isEnumRequired(elem):
decl = " " + name + " = " + strVal + ",\n"
if numVal != None:
body += decl
else:
aliasText += decl
# Don't track min/max for non-numbers (numVal == None)
if expand and isEnum and numVal != None and elem.get('extends') is None:
if (minName == None):
minName = maxName = name
minValue = maxValue = numVal
elif (numVal < minValue):
minName = name
minValue = numVal
elif (numVal > maxValue):
maxName = name
maxValue = numVal
# Now append the non-numeric enumerant values
body += aliasText
# Generate min/max value tokens and a range-padding enum. Need some
# additional padding to generate correct names...
if expand:
#@ body += "\n"
if isEnum:
body += " " + expandPrefix + "_BEGIN_RANGE" + expandSuffix + " = " + minName + ",\n"
body += " " + expandPrefix + "_END_RANGE" + expandSuffix + " = " + maxName + ",\n"
body += " " + expandPrefix + "_RANGE_SIZE" + expandSuffix + " = (" + maxName + " - " + minName + " + 1),\n"
body += " " + expandPrefix + "_MAX_ENUM" + expandSuffix + " = 0x7FFFFFFF\n"
# Postfix
body += "} " + groupName + ";"
self.writeInclude('enums', filename, body)
self.writeInclude('enums', groupName, body)
# Enumerant generation
# <enum> tags may specify their values in several ways, but are usually
# just integers.
def genEnum(self, enuminfo, name, alias):
OutputGenerator.genEnum(self, enuminfo, name, alias)
(numVal,strVal) = self.enumToValue(enuminfo.elem, False)
body = '#define ' + name.ljust(33) + ' ' + strVal
self.logMsg('diag', '# NOT writing compile-time constant', name)
# (_, strVal) = self.enumToValue(enuminfo.elem, False)
# body = '#define ' + name.ljust(33) + ' ' + strVal
# self.writeInclude('consts', name, body)
#
# Command generation
def genCmd(self, cmdinfo, name, alias):
OutputGenerator.genCmd(self, cmdinfo, name, alias)
#
return_type = cmdinfo.elem.find('proto/type')
if self.genOpts.conventions.requires_error_validation(return_type):
# This command returns an API result code, so check that it
# returns at least the required errors.
required_errors = self.genOpts.conventions.required_errors
errorcodes = cmdinfo.elem.get('errorcodes').split(',')
if not required_errors.issubset(set(errorcodes)):
self.logMsg('error', 'Missing required error code for command: ', name, '\n')
exit(1)
decls = self.makeCDecls(cmdinfo.elem)
self.writeInclude('protos', name, decls[0])

View File

@ -16,13 +16,23 @@
# extDependency - generate a mapping of extension name -> all required
# extension names for that extension.
# This script generates a list of all extensions, and of just KHR
# extensions, that are placed into a Bash script and/or Python script. This
# script can then be sources or executed to set a variable (e.g., khrExts),
# Frontend scripts such as 'makeAllExts' and 'makeKHR' use this information
# to set the EXTENSIONS Makefile variable when building the spec.
#
# This updates config/extDependency.sh from the spec Makefile.
# It also defines lists of KHR extensions and all extensions for use in
# make frontend scripts such as 'makeAllExts'.
# Sample Usage:
#
# python3 scripts/extDependency.py -outscript=temp.sh
# source temp.sh
# make EXTENSIONS="$khrExts" html
# rm temp.sh
import argparse
import xml.etree.ElementTree as etree
from vkconventions import VulkanConventions as APIConventions
def enQuote(key):
return "'" + str(key) + "'"
@ -32,13 +42,13 @@ def enQuote(key):
def shList(names):
s = ('"' +
' '.join([str(key) for key in sorted(names)]) +
' '.join(str(key) for key in sorted(names)) +
'"')
return s
def pyList(names):
s = ('[ ' +
', '.join([enQuote(key) for key in sorted(names)]) +
', '.join(enQuote(key) for key in sorted(names)) +
' ]')
return s
@ -91,7 +101,7 @@ class DiGraph:
# The stack of nodes that need visiting.
visit_me = []
# Boostrap the traversal.
# Bootstrap the traversal.
seen.add(node)
for x in self.__nodes[node].adj:
if x not in seen:
@ -114,14 +124,17 @@ class DiGraphNode:
# Set of adjacent of nodes.
self.adj = set()
# API conventions object
conventions = APIConventions()
# -extension name - may be a single extension name, a space-separated list
# of names, or a regular expression.
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-registry', action='store',
default='vk.xml',
help='Use specified registry file instead of vk.xml')
default=conventions.registry_path,
help='Use specified registry file instead of ' + conventions.registry_path)
parser.add_argument('-outscript', action='store',
default=None,
help='Shell script to create')
@ -151,14 +164,15 @@ if __name__ == '__main__':
name = elem.get('name')
supported = elem.get('supported')
if (supported == 'vulkan'):
if supported == conventions.xml_api_name:
allExts.add(name)
if ('KHR' in name):
if 'KHR' in name:
khrExts.add(name)
if ('requires' in elem.attrib):
deps = elem.get('requires').split(',')
deps = elem.get('requires')
if deps:
deps = deps.split(',')
for dep in deps:
g.add_edge(name, dep)
@ -166,25 +180,25 @@ if __name__ == '__main__':
g.add_node(name)
else:
# Skip unsupported extensions
True
pass
if args.outscript:
fp = open(args.outscript, 'w', encoding='utf-8')
print('#!/bin/bash', file=fp)
print('# Generated from xml/extDependency.py', file=fp)
print('# Generated from extDependency.py', file=fp)
print('# Specify maps of all extensions required by an enabled extension', file=fp)
print('', file=fp)
print('declare -A extensions', file=fp)
# When printing lists of extensions, sort them sort the output script
# remains as stable as possible as extensions are added to vk.xml.
# When printing lists of extensions, sort them so that the output script
# remains as stable as possible as extensions are added to the API XML.
for ext in sorted(g.nodes()):
children = list(g.descendants(ext))
# Only emit an ifdef block if an extension has dependencies
if len(children) > 0:
if children:
print('extensions[' + ext + ']=' + shList(children), file=fp)
print('', file=fp)
@ -198,19 +212,19 @@ if __name__ == '__main__':
fp = open(args.outpy, 'w', encoding='utf-8')
print('#!/usr/bin/env python', file=fp)
print('# Generated from xml/extDependency.py', file=fp)
print('# Generated from extDependency.py', file=fp)
print('# Specify maps of all extensions required by an enabled extension', file=fp)
print('', file=fp)
print('extensions = {}', file=fp)
# When printing lists of extensions, sort them sort the output script
# remains as stable as possible as extensions are added to vk.xml.
# When printing lists of extensions, sort them so that the output script
# remains as stable as possible as extensions are added to the API XML.
for ext in sorted(g.nodes()):
children = list(g.descendants(ext))
# Only emit an ifdef block if an extension has dependencies
if len(children) > 0:
if children:
print("extensions['" + ext + "'] = " + pyList(children), file=fp)
print('', file=fp)

View File

@ -14,14 +14,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os,re,sys,functools
from generator import *
import re
import sys
from functools import total_ordering
from generator import GeneratorOptions, OutputGenerator, regSortFeatures, write
# ExtensionMetaDocGeneratorOptions - subclass of GeneratorOptions.
class ExtensionMetaDocGeneratorOptions(GeneratorOptions):
"""Represents options during extension metainformation generation for Asciidoc"""
def __init__(self,
conventions = None,
filename = None,
directory = '.',
apiname = None,
@ -33,7 +35,7 @@ class ExtensionMetaDocGeneratorOptions(GeneratorOptions):
removeExtensions = None,
emitExtensions = None,
sortProcedure = regSortFeatures):
GeneratorOptions.__init__(self, filename, directory, apiname, profile,
GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
versions, emitversions, defaultExtensions,
addExtensions, removeExtensions,
emitExtensions, sortProcedure)
@ -41,11 +43,11 @@ class ExtensionMetaDocGeneratorOptions(GeneratorOptions):
@total_ordering
class Extension:
def __init__(self,
generator, # needed for logging
generator, # needed for logging and API conventions
filename,
name,
number,
type,
ext_type,
requires,
requiresCore,
contact,
@ -55,10 +57,11 @@ class Extension:
provisional,
revision ):
self.generator = generator
self.conventions = generator.genOpts.conventions
self.filename = filename
self.name = name
self.number = number
self.type = type
self.ext_type = ext_type
self.requires = requires
self.requiresCore = requiresCore
self.contact = contact
@ -69,7 +72,7 @@ class Extension:
self.revision = revision
self.deprecationType = None
self.supercedingVkVersion = None
self.supercedingAPIVersion = None
self.supercedingExtension = None
if self.promotedTo is not None and self.deprecatedBy is not None and self.obsoletedBy is not None:
@ -81,73 +84,78 @@ class Extension:
elif self.deprecatedBy is not None and self.obsoletedBy is not None:
self.generator.logMsg('warn', 'Both \'deprecatedby\' and \'obsoletedby\' attributes used on extension ' + self.name + '! Ignoring \'deprecatedby\'.')
superceededBy = None
supercededBy = None
if self.promotedTo is not None:
self.deprecationType = 'promotion'
superceededBy = promotedTo
supercededBy = promotedTo
elif self.deprecatedBy is not None:
self.deprecationType = 'deprecation'
superceededBy = deprecatedBy
supercededBy = deprecatedBy
elif self.obsoletedBy is not None:
self.deprecationType = 'obsoletion'
superceededBy = obsoletedBy
supercededBy = obsoletedBy
if superceededBy is not None:
if superceededBy == '' and not self.deprecationType == 'promotion':
pass # supercedingVkVersion, supercedingExtension == None
elif superceededBy.startswith('VK_VERSION_'):
self.supercedingVkVersion = superceededBy
elif superceededBy.startswith('VK_'):
self.supercedingExtension = superceededBy
if supercededBy is not None:
if supercededBy == '' and not self.deprecationType == 'promotion':
pass # supercedingAPIVersion, supercedingExtension is None
elif supercededBy.startswith(self.conventions.api_version_prefix):
self.supercedingAPIVersion = supercededBy
elif supercededBy.startswith(self.conventions.api_prefix):
self.supercedingExtension = supercededBy
else:
self.generator.logMsg('error', 'Unrecognized ' + self.deprecationType + ' attribute value \'' + superceededBy + '\'!')
self.generator.logMsg('error', 'Unrecognized ' + self.deprecationType + ' attribute value \'' + supercededBy + '\'!')
def __str__(self): return self.name
def __str__(self):
return self.name
def __eq__(self, other):
return self.name == other.name
def __ne__(self, other):
return self.name != other.name
def __eq__(self, other): return self.name == other.name
def __ne__(self, other): return self.name != other.name
def __lt__(self, other):
me_is_KHR = self.name.startswith( 'VK_KHR' )
me_is_EXT = self.name.startswith( 'VK_EXT' )
he_is_KHR = other.name.startswith( 'VK_KHR' )
he_is_EXT = other.name.startswith( 'VK_EXT' )
self_is_KHR = self.name.startswith(self.conventions.KHR_prefix)
self_is_EXT = self.name.startswith(self.conventions.EXT_prefix)
other_is_KHR = other.name.startswith(self.conventions.KHR_prefix)
other_is_EXT = other.name.startswith(self.conventions.EXT_prefix)
swap = False
if me_is_KHR and not he_is_KHR:
if self_is_KHR and not other_is_KHR:
return not swap
elif he_is_KHR and not me_is_KHR:
if other_is_KHR and not self_is_KHR:
return swap
elif me_is_EXT and not he_is_EXT:
if self_is_EXT and not other_is_EXT:
return not swap
elif he_is_EXT and not me_is_EXT:
if other_is_EXT and not self_is_EXT:
return swap
else:
return self.name < other.name
return self.name < other.name
def typeToStr(self):
if self.type == 'instance':
if self.ext_type == 'instance':
return 'Instance extension'
elif self.type == 'device':
if self.ext_type == 'device':
return 'Device extension'
elif self.type != None:
if self.ext_type is not None:
self.generator.logMsg('warn', 'The type attribute of ' + self.name + ' extension is neither \'instance\' nor \'device\'. That is invalid (at the time this script was written).')
write(' ' + type.capitalize(), file=fp)
else: # should be unreachable
self.generator.logMsg('error', 'Logic error in typeToStr(): Missing type attribute!')
return None
def conditionalLinkCoreVk(self, vulkanVersion, linkSuffix):
versionMatch = re.match(r'VK_VERSION_(\d+)_(\d+)', vulkanVersion)
def conditionalLinkCoreAPI(self, apiVersion, linkSuffix):
versionMatch = re.match(self.conventions.api_version_prefix + r'(\d+)_(\d+)', apiVersion)
major = versionMatch.group(1)
minor = versionMatch.group(2)
dottedVersion = major + '.' + minor
doc = 'ifdef::' + vulkanVersion + '[]\n'
doc += ' <<versions-' + dottedVersion + linkSuffix + ', Vulkan ' + dottedVersion + '>>\n'
doc += 'endif::' + vulkanVersion + '[]\n'
doc += 'ifndef::' + vulkanVersion + '[]\n'
doc += ' Vulkan ' + dottedVersion + '\n'
doc += 'endif::' + vulkanVersion + '[]\n'
doc = 'ifdef::' + apiVersion + '[]\n'
doc += ' <<versions-' + dottedVersion + linkSuffix + ', ' + self.conventions.api_name + ' ' + dottedVersion + '>>\n'
doc += 'endif::' + apiVersion + '[]\n'
doc += 'ifndef::' + apiVersion + '[]\n'
doc += ' ' + self.conventions.api_name + ' ' + dottedVersion + '\n'
doc += 'endif::' + apiVersion + '[]\n'
return doc
@ -166,22 +174,22 @@ class Extension:
if ext.deprecationType:
if ext.deprecationType == 'promotion':
if ext.supercedingVkVersion:
write(' ** Which in turn was _promoted_ to\n' + ext.conditionalLinkCoreVk(ext.supercedingVkVersion, '-promotions'), file=file)
if ext.supercedingAPIVersion:
write(' ** Which in turn was _promoted_ to\n' + ext.conditionalLinkCoreAPI(ext.supercedingAPIVersion, '-promotions'), file=file)
else: # ext.supercedingExtension
write(' ** Which in turn was _promoted_ to extension\n' + ext.conditionalLinkExt(ext.supercedingExtension), file=file)
ext.resolveDeprecationChain(extensionsList, ext.supercedingExtension, file)
elif ext.deprecationType == 'deprecation':
if ext.supercedingVkVersion:
write(' ** Which in turn was _deprecated_ by\n' + ext.conditionalLinkCoreVk(ext.supercedingVkVersion, '-new-feature'), file=file)
if ext.supercedingAPIVersion:
write(' ** Which in turn was _deprecated_ by\n' + ext.conditionalLinkCoreAPI(ext.supercedingAPIVersion, '-new-feature'), file=file)
elif ext.supercedingExtension:
write(' ** Which in turn was _deprecated_ by\n' + ext.conditionalLinkExt(ext.supercedingExtension) + ' extension', file=file)
ext.resolveDeprecationChain(extensionsList, ext.supercedingExtension, file)
else:
write(' ** Which in turn was _deprecated_ without replacement', file=file)
elif ext.deprecationType == 'obsoletion':
if ext.supercedingVkVersion:
write(' ** Which in turn was _obsoleted_ by\n' + ext.conditionalLinkCoreVk(ext.supercedingVkVersion, '-new-feature'), file=file)
if ext.supercedingAPIVersion:
write(' ** Which in turn was _obsoleted_ by\n' + ext.conditionalLinkCoreAPI(ext.supercedingAPIVersion, '-new-feature'), file=file)
elif ext.supercedingExtension:
write(' ** Which in turn was _obsoleted_ by\n' + ext.conditionalLinkExt(ext.supercedingExtension) + ' extension', file=file)
ext.resolveDeprecationChain(extensionsList, ext.supercedingExtension, file)
@ -210,9 +218,9 @@ class Extension:
write('*Revision*::', file=fp)
write(' ' + self.revision, file=fp)
# Only Vulkan extension dependencies are coded in XML, others are explicit
# Only API extension dependencies are coded in XML, others are explicit
write('*Extension and Version Dependencies*::', file=fp)
write(' * Requires Vulkan ' + self.requiresCore, file=fp)
write(' * Requires ' + self.conventions.api_name + ' ' + self.requiresCore, file=fp)
if self.requires:
for dep in self.requires.split(','):
write(' * Requires `<<' + dep + '>>`', file=fp)
@ -221,22 +229,22 @@ class Extension:
write('*Deprecation state*::', file=fp)
if self.deprecationType == 'promotion':
if self.supercedingVkVersion:
write(' * _Promoted_ to\n' + self.conditionalLinkCoreVk(self.supercedingVkVersion, '-promotions'), file=fp)
if self.supercedingAPIVersion:
write(' * _Promoted_ to\n' + self.conditionalLinkCoreAPI(self.supercedingAPIVersion, '-promotions'), file=fp)
else: # ext.supercedingExtension
write(' * _Promoted_ to\n' + self.conditionalLinkExt(self.supercedingExtension) + ' extension', file=fp)
self.resolveDeprecationChain(extensionsList, self.supercedingExtension, fp)
elif self.deprecationType == 'deprecation':
if self.supercedingVkVersion:
write(' * _Deprecated_ by\n' + self.conditionalLinkCoreVk(self.supercedingVkVersion, '-new-features'), file=fp)
if self.supercedingAPIVersion:
write(' * _Deprecated_ by\n' + self.conditionalLinkCoreAPI(self.supercedingAPIVersion, '-new-features'), file=fp)
elif self.supercedingExtension:
write(' * _Deprecated_ by\n' + self.conditionalLinkExt(self.supercedingExtension) + ' extension' , file=fp)
self.resolveDeprecationChain(extensionsList, self.supercedingExtension, fp)
else:
write(' * _Deprecated_ without replacement' , file=fp)
elif self.deprecationType == 'obsoletion':
if self.supercedingVkVersion:
write(' * _Obsoleted_ by\n' + self.conditionalLinkCoreVk(self.supercedingVkVersion, '-new-features'), file=fp)
if self.supercedingAPIVersion:
write(' * _Obsoleted_ by\n' + self.conditionalLinkCoreAPI(self.supercedingAPIVersion, '-new-features'), file=fp)
elif self.supercedingExtension:
write(' * _Obsoleted_ by\n' + self.conditionalLinkExt(self.supercedingExtension) + ' extension' , file=fp)
self.resolveDeprecationChain(extensionsList, self.supercedingExtension, fp)
@ -247,40 +255,94 @@ class Extension:
else: # should be unreachable
self.generator.logMsg('error', 'Logic error in makeMetafile(): deprecationType is neither \'promotion\', \'deprecation\' nor \'obsoletion\'!')
write('*Contact*::', file=fp)
contacts = self.contact.split(',')
for contact in contacts:
contactWords = contact.strip().split()
name = ' '.join(contactWords[:-1])
handle = contactWords[-1]
if handle.startswith('gitlab:'):
prettyHandle = 'icon:gitlab[alt=GitLab, role="red"]' + handle.replace('gitlab:@', '')
elif handle.startswith('@'):
trackerLink = 'link:++https://github.com/KhronosGroup/Vulkan-Docs/issues/new?title=' + self.name + ':%20&body=' + handle + '%20++'
prettyHandle = trackerLink + '[icon:github[alt=GitHub, role="black"]' + handle[1:] + ']'
else:
prettyHandle = handle
if self.conventions.write_contacts:
write('*Contact*::', file=fp)
contacts = self.contact.split(',')
for contact in contacts:
contactWords = contact.strip().split()
name = ' '.join(contactWords[:-1])
handle = contactWords[-1]
if handle.startswith('gitlab:'):
prettyHandle = 'icon:gitlab[alt=GitLab, role="red"]' + handle.replace('gitlab:@', '')
elif handle.startswith('@'):
trackerLink = 'link:++https://github.com/KhronosGroup/Vulkan-Docs/issues/new?title=' + self.name + ':%20&body=' + handle + '%20++'
prettyHandle = trackerLink + '[icon:github[alt=GitHub, role="black"]' + handle[1:] + ']'
else:
prettyHandle = handle
write(' * ' + name + ' ' + prettyHandle, file=fp)
write(' * ' + name + ' ' + prettyHandle, file=fp)
fp.close()
fp.close()
if self.conventions.write_refpage_include:
# Now make the refpage include
fp = self.generator.newFile(self.filename.replace('meta/', 'meta/refpage.'))
write('== Registered Extension Number', file=fp)
write(self.number, file=fp)
write('', file=fp)
write('== Revision', file=fp)
write(self.revision, file=fp)
write('', file=fp)
# Only API extension dependencies are coded in XML, others are explicit
write('== Extension and Version Dependencies', file=fp)
write(' * Requires ' + self.conventions.api_name + ' ' + self.requiresCore, file=fp)
if self.requires:
for dep in self.requires.split(','):
write(' * Requires `<<' + dep + '>>`', file=fp)
write('', file=fp)
if self.deprecationType:
write('== Deprecation state', file=fp)
if self.deprecationType == 'promotion':
if self.supercedingAPIVersion:
write(' * _Promoted_ to\n' + self.conditionalLinkCoreAPI(self.supercedingAPIVersion, '-promotions'), file=fp)
else: # ext.supercedingExtension
write(' * _Promoted_ to\n' + self.conditionalLinkExt(self.supercedingExtension) + ' extension', file=fp)
self.resolveDeprecationChain(extensionsList, self.supercedingExtension, fp)
elif self.deprecationType == 'deprecation':
if self.supercedingAPIVersion:
write(' * _Deprecated_ by\n' + self.conditionalLinkCoreAPI(self.supercedingAPIVersion, '-new-features'), file=fp)
elif self.supercedingExtension:
write(' * _Deprecated_ by\n' + self.conditionalLinkExt(self.supercedingExtension) + ' extension' , file=fp)
self.resolveDeprecationChain(extensionsList, self.supercedingExtension, fp)
else:
write(' * _Deprecated_ without replacement' , file=fp)
elif self.deprecationType == 'obsoletion':
if self.supercedingAPIVersion:
write(' * _Obsoleted_ by\n' + self.conditionalLinkCoreAPI(self.supercedingAPIVersion, '-new-features'), file=fp)
elif self.supercedingExtension:
write(' * _Obsoleted_ by\n' + self.conditionalLinkExt(self.supercedingExtension) + ' extension' , file=fp)
self.resolveDeprecationChain(extensionsList, self.supercedingExtension, fp)
else:
# TODO: Does not make sense to retroactively ban use of extensions from 1.0.
# Needs some tweaks to the semantics and this message, when such extension(s) occur.
write(' * _Obsoleted_ without replacement' , file=fp)
else: # should be unreachable
self.generator.logMsg('error', 'Logic error in makeMetafile(): deprecationType is neither \'promotion\', \'deprecation\' nor \'obsoletion\'!')
write('', file=fp)
fp.close()
# ExtensionMetaDocOutputGenerator - subclass of OutputGenerator.
# Generates AsciiDoc includes with metainformation for the Vulkan extension
# appendices. The fields used from <extension> tags in vk.xml are:
# Generates AsciiDoc includes with metainformation for the API extension
# appendices. The fields used from <extension> tags in the API XML are:
#
# name extension name string
# number extension number (optional)
# contact name and github login or email address (optional)
# type 'instance' | 'device' (optional)
# requires list of comma-separate requires Vulkan extensions (optional)
# requiresCore required core version of Vulkan (optional)
# promotedTo extension or Vulkan version it was promoted to
# deprecatedBy extension or Vulkan version which deprecated this extension,
# or empty string if deprecated without replacement
# obsoletedBy extension or Vulkan version which obsoleted this extension,
# or empty string if obsoleted without replacement
# requires list of comma-separated required API extensions (optional)
# requiresCore required core version of API (optional)
# promotedTo extension or API version it was promoted to
# deprecatedBy extension or API version which deprecated this extension,
# or empty string if deprecated without replacement
# obsoletedBy extension or API version which obsoleted this extension,
# or empty string if obsoleted without replacement
# provisional 'true' if this extension is released provisionally
#
# ---- methods ----
@ -299,17 +361,27 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
diagFile = sys.stdout):
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
self.extensions = []
# List of strings containing all vendor tags
self.vendor_tags = []
self.file_suffix = ''
def newFile(self, filename):
self.logMsg('diag', '# Generating include file:', filename)
fp = open(filename, 'w', encoding='utf-8')
write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
write(self.genOpts.conventions.warning_comment, file=fp)
return fp
def beginFile(self, genOpts):
OutputGenerator.beginFile(self, genOpts)
self.directory = self.genOpts.directory
self.file_suffix = self.genOpts.conventions.file_suffix
# Iterate over all 'tag' Elements and add the names of all the valid vendor
# tags to the list
root = self.registry.tree.getroot()
for tag in root.findall('tags/tag'):
self.vendor_tags.append(tag.get('name'))
# Create subdirectory, if needed
self.makeDir(self.directory)
@ -343,6 +415,22 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
return doc
def outputExtensionInclude(self, name, vendor, deprecation_type, conditions, current_fp, current_toc_fp, deprecated_fp, deprecated_toc_fp, guard_fp):
include = 'include::../' + vendor.lower() + '/' + name[3:].lower() + '' + self.file_suffix + '[]'
link = ' * <<' + name + '>>'
if deprecation_type is None:
write(self.conditionalExt(name, include), file=current_fp)
write(self.conditionalExt(name, link), file=current_toc_fp)
else:
write(self.conditionalExt(name, include, 'ifndef', conditions), file=current_fp)
write(self.conditionalExt(name, link, 'ifndef', conditions), file=current_toc_fp)
write(self.conditionalExt(name, include, 'ifdef', conditions), file=deprecated_fp)
write(self.conditionalExt(name, link, 'ifdef', conditions), file=deprecated_toc_fp)
write(self.conditionalExt(name, ':HAS_DEPRECATED_EXTENSIONS:', 'ifdef', conditions), file=guard_fp)
def endFile(self):
self.extensions.sort()
@ -351,11 +439,11 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
promotedExtensions = {}
for ext in self.extensions:
if ext.deprecationType == 'promotion' and ext.supercedingVkVersion:
promotedExtensions.setdefault(ext.supercedingVkVersion, []).append(ext)
if ext.deprecationType == 'promotion' and ext.supercedingAPIVersion:
promotedExtensions.setdefault(ext.supercedingAPIVersion, []).append(ext)
for coreVersion, extensions in promotedExtensions.items():
promoted_extensions_fp = self.newFile(self.directory + '/promoted_extensions_' + coreVersion + '.txt')
promoted_extensions_fp = self.newFile(self.directory + '/promoted_extensions_' + coreVersion + self.file_suffix)
for ext in extensions:
indent = ''
@ -363,19 +451,19 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
promoted_extensions_fp.close()
current_extensions_appendix_fp = self.newFile(self.directory + '/current_extensions_appendix.txt')
deprecated_extensions_appendix_fp = self.newFile(self.directory + '/deprecated_extensions_appendix.txt')
current_extension_appendices_fp = self.newFile(self.directory + '/current_extension_appendices.txt')
current_extension_appendices_toc_fp = self.newFile(self.directory + '/current_extension_appendices_toc.txt')
deprecated_extension_appendices_fp = self.newFile(self.directory + '/deprecated_extension_appendices.txt')
deprecated_extension_appendices_toc_fp = self.newFile(self.directory + '/deprecated_extension_appendices_toc.txt')
deprecated_extensions_guard_macro_fp = self.newFile(self.directory + '/deprecated_extensions_guard_macro.txt')
provisional_extensions_appendix_fp = self.newFile(self.directory + '/provisional_extensions_appendix.txt')
provisional_extension_appendices_fp = self.newFile(self.directory + '/provisional_extension_appendices.txt')
provisional_extension_appendices_toc_fp = self.newFile(self.directory + '/provisional_extension_appendices_toc.txt')
provisional_extensions_guard_macro_fp = self.newFile(self.directory + '/provisional_extensions_guard_macro.txt')
current_extensions_appendix_fp = self.newFile(self.directory + '/current_extensions_appendix' + self.file_suffix)
deprecated_extensions_appendix_fp = self.newFile(self.directory + '/deprecated_extensions_appendix' + self.file_suffix)
current_extension_appendices_fp = self.newFile(self.directory + '/current_extension_appendices' + self.file_suffix)
current_extension_appendices_toc_fp = self.newFile(self.directory + '/current_extension_appendices_toc' + self.file_suffix)
deprecated_extension_appendices_fp = self.newFile(self.directory + '/deprecated_extension_appendices' + self.file_suffix)
deprecated_extension_appendices_toc_fp = self.newFile(self.directory + '/deprecated_extension_appendices_toc' + self.file_suffix)
deprecated_extensions_guard_macro_fp = self.newFile(self.directory + '/deprecated_extensions_guard_macro' + self.file_suffix)
provisional_extensions_appendix_fp = self.newFile(self.directory + '/provisional_extensions_appendix' + self.file_suffix)
provisional_extension_appendices_fp = self.newFile(self.directory + '/provisional_extension_appendices' + self.file_suffix)
provisional_extension_appendices_toc_fp = self.newFile(self.directory + '/provisional_extension_appendices_toc' + self.file_suffix)
provisional_extensions_guard_macro_fp = self.newFile(self.directory + '/provisional_extensions_guard_macro' + self.file_suffix)
write('include::deprecated_extensions_guard_macro.txt[]', file=current_extensions_appendix_fp)
write('include::deprecated_extensions_guard_macro' + self.file_suffix + '[]', file=current_extensions_appendix_fp)
write('', file=current_extensions_appendix_fp)
write('ifndef::HAS_DEPRECATED_EXTENSIONS[]', file=current_extensions_appendix_fp)
write('[[extension-appendices-list]]', file=current_extensions_appendix_fp)
@ -386,18 +474,18 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
write('== List of Current Extensions', file=current_extensions_appendix_fp)
write('endif::HAS_DEPRECATED_EXTENSIONS[]', file=current_extensions_appendix_fp)
write('', file=current_extensions_appendix_fp)
write('include::current_extension_appendices_toc.txt[]', file=current_extensions_appendix_fp)
write('include::current_extension_appendices_toc' + self.file_suffix + '[]', file=current_extensions_appendix_fp)
write('<<<', file=current_extensions_appendix_fp)
write('include::current_extension_appendices.txt[]', file=current_extensions_appendix_fp)
write('include::current_extension_appendices' + self.file_suffix + '[]', file=current_extensions_appendix_fp)
write('include::deprecated_extensions_guard_macro.txt[]', file=deprecated_extensions_appendix_fp)
write('include::deprecated_extensions_guard_macro' + self.file_suffix + '[]', file=deprecated_extensions_appendix_fp)
write('', file=deprecated_extensions_appendix_fp)
write('ifdef::HAS_DEPRECATED_EXTENSIONS[]', file=deprecated_extensions_appendix_fp)
write('[[deprecated-extension-appendices-list]]', file=deprecated_extensions_appendix_fp)
write('== List of Deprecated Extensions', file=deprecated_extensions_appendix_fp)
write('include::deprecated_extension_appendices_toc.txt[]', file=deprecated_extensions_appendix_fp)
write('include::deprecated_extension_appendices_toc' + self.file_suffix + '[]', file=deprecated_extensions_appendix_fp)
write('<<<', file=deprecated_extensions_appendix_fp)
write('include::deprecated_extension_appendices.txt[]', file=deprecated_extensions_appendix_fp)
write('include::deprecated_extension_appendices' + self.file_suffix + '[]', file=deprecated_extensions_appendix_fp)
write('endif::HAS_DEPRECATED_EXTENSIONS[]', file=deprecated_extensions_appendix_fp)
# add include guard to allow multiple includes
@ -406,18 +494,18 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
write('ifndef::PROVISIONAL_EXTENSIONS_GUARD_MACRO_INCLUDE_GUARD[]', file=provisional_extensions_guard_macro_fp)
write(':PROVISIONAL_EXTENSIONS_GUARD_MACRO_INCLUDE_GUARD:\n', file=provisional_extensions_guard_macro_fp)
write('include::provisional_extensions_guard_macro.txt[]', file=provisional_extensions_appendix_fp)
write('include::provisional_extensions_guard_macro' + self.file_suffix + '[]', file=provisional_extensions_appendix_fp)
write('', file=provisional_extensions_appendix_fp)
write('ifdef::HAS_PROVISIONAL_EXTENSIONS[]', file=provisional_extensions_appendix_fp)
write('[[provisional-extension-appendices-list]]', file=provisional_extensions_appendix_fp)
write('== List of Provisional Extensions', file=provisional_extensions_appendix_fp)
write('include::provisional_extension_appendices_toc.txt[]', file=provisional_extensions_appendix_fp)
write('include::provisional_extension_appendices_toc' + self.file_suffix + '[]', file=provisional_extensions_appendix_fp)
write('<<<', file=provisional_extensions_appendix_fp)
write('include::provisional_extension_appendices.txt[]', file=provisional_extensions_appendix_fp)
write('include::provisional_extension_appendices' + self.file_suffix + '[]', file=provisional_extensions_appendix_fp)
write('endif::HAS_PROVISIONAL_EXTENSIONS[]', file=provisional_extensions_appendix_fp)
for ext in self.extensions:
include = 'include::../' + ext.name + '.txt[]'
include = 'include::../' + ext.name + self.file_suffix + '[]'
link = ' * <<' + ext.name + '>>'
if ext.provisional == 'true':
@ -428,7 +516,7 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
write(self.conditionalExt(ext.name, include), file=current_extension_appendices_fp)
write(self.conditionalExt(ext.name, link), file=current_extension_appendices_toc_fp)
else:
condition = ext.supercedingVkVersion if ext.supercedingVkVersion else ext.supercedingExtension # potentially None too
condition = ext.supercedingAPIVersion if ext.supercedingAPIVersion else ext.supercedingExtension # potentially None too
write(self.conditionalExt(ext.name, include, 'ifndef', condition), file=current_extension_appendices_fp)
write(self.conditionalExt(ext.name, link, 'ifndef', condition), file=current_extension_appendices_toc_fp)
@ -461,7 +549,7 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
# These attributes must exist
name = self.featureName
number = self.getAttrib(interface, 'number')
type = self.getAttrib(interface, 'type')
ext_type = self.getAttrib(interface, 'type')
revision = self.getSpecVersion(interface, name)
# These attributes are optional
@ -474,9 +562,9 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
obsoletedBy = self.getAttrib(interface, 'obsoletedby', OPTIONAL)
provisional = self.getAttrib(interface, 'provisional', OPTIONAL, 'false')
filename = self.directory + '/' + name + '.txt'
filename = self.directory + '/' + name + self.file_suffix
self.extensions.append( Extension(self, filename, name, number, type, requires, requiresCore, contact, promotedTo, deprecatedBy, obsoletedBy, provisional, revision) )
self.extensions.append( Extension(self, filename, name, number, ext_type, requires, requiresCore, contact, promotedTo, deprecatedBy, obsoletedBy, provisional, revision) )
def endFeature(self):
# Finish processing in superclass
@ -488,14 +576,11 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
# required - whether attribute must exist
# default - default value if attribute not present
def getAttrib(self, elem, attribute, required=True, default=None):
attrib = elem.get(attribute, default)
if required and (attrib is None):
name = elem.get('name', 'UNKNOWN')
self.logMsg('error', 'While processing \'' + self.featureName + ', <' + elem.tag + '> \'' + name + '\' does not contain required attribute \'' + attribute + '\'')
return attrib
def content(tag, ET):
return tag.text + ''.join(ET.tostring(e) for e in tag)
attrib = elem.get(attribute, default)
if required and (attrib is None):
name = elem.get('name', 'UNKNOWN')
self.logMsg('error', 'While processing \'' + self.featureName + ', <' + elem.tag + '> \'' + name + '\' does not contain required attribute \'' + attribute + '\'')
return attrib
def numbersToWords(self, name):
whitelist = ['WIN32', 'INT16']
@ -536,3 +621,4 @@ class ExtensionMetaDocOutputGenerator(OutputGenerator):
return self.getAttrib(enum, 'value')
self.logMsg('error', 'Missing ' + versioningEnumName + '!')
return default

View File

@ -14,16 +14,30 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# genRef.py - create Vulkan ref pages from spec source files
#
# genRef.py - create API ref pages from spec source files
#
# Usage: genRef.py files
from reflib import *
import vkapi
import argparse, copy, io, os, pdb, re, string, sys
import argparse
import io
import os
import re
import sys
from collections import OrderedDict
from reflib import (findRefs, fixupRefs, loadFile, logDiag, logWarn,
printPageInfo, setLogFile)
from reg import Registry
import vkapi as api
from vkconventions import VulkanConventions as APIConventions
# Return True if name is a Vulkan extension name (ends with an upper-case
def makeExtensionInclude(name):
"""Return an include command, given an extension name."""
return 'include::{}/refpage.{}{}[]'.format(
conventions.specification_path,
name,
conventions.file_suffix)
# Return True if name is an API extension name (ends with an upper-case
# author ID). This assumes that author IDs are at least two characters.
def isextension(name):
return name[-2:].isalpha() and name[-2:].isupper()
@ -33,36 +47,35 @@ def isextension(name):
# file. Otherwise print as an asciidoc include of the copyright in markup,
# which copyrights the outputs. Also include some asciidoc boilerplate
# needed by all the standalone ref pages.
def printCopyrightSourceComments(fp):
print('// Copyright (c) 2014-2019 Khronos Group. This work is licensed under a', file=fp)
print('// Creative Commons Attribution 4.0 International License; see', file=fp)
print('// http://creativecommons.org/licenses/by/4.0/', file=fp)
print('', file=fp)
print('// Copyright (c) 2014-2019 Khronos Group. This work is licensed under a', file=fp)
print('// Creative Commons Attribution 4.0 International License; see', file=fp)
print('// http://creativecommons.org/licenses/by/4.0/', file=fp)
print('', file=fp)
def printFooter(fp):
print('include::footer.txt[]', file=fp)
print('', file=fp)
# Add a spec asciidoc macro prefix to a Vulkan name, depending on its type
# Add a spec asciidoc macro prefix to an API name, depending on its type
# (protos, structs, enums, etc.)
def macroPrefix(name):
if name in vkapi.basetypes.keys():
if name in api.basetypes:
return 'basetype:' + name
elif name in vkapi.defines.keys():
return 'slink:' + name
elif name in vkapi.enums.keys():
elif name in api.defines:
return 'dlink:' + name
elif name in api.enums:
return 'elink:' + name
elif name in vkapi.flags.keys():
elif name in api.flags:
return 'elink:' + name
elif name in vkapi.funcpointers.keys():
elif name in api.funcpointers:
return 'tlink:' + name
elif name in vkapi.handles.keys():
elif name in api.handles:
return 'slink:' + name
elif name in vkapi.protos.keys():
elif name in api.protos:
return 'flink:' + name
elif name in vkapi.structs.keys():
elif name in api.structs:
return 'slink:' + name
elif name == 'TBD':
return 'No cross-references are available'
@ -70,27 +83,27 @@ def macroPrefix(name):
return 'UNKNOWN:' + name
# Return an asciidoc string with a list of 'See Also' references for the
# Vulkan entity 'name', based on the relationship mapping in vkapi.py and
# API entity 'name', based on the relationship mapping in the api module and
# the additional references in explicitRefs. If no relationships are
# available, return None.
def seeAlsoList(apiName, explicitRefs = None):
refs = {}
# Add all the implicit references to refs
if apiName in vkapi.mapDict.keys():
for name in sorted(vkapi.mapDict[apiName].keys()):
if apiName in api.mapDict:
for name in sorted(api.mapDict[apiName]):
refs[name] = None
# Add all the explicit references
if explicitRefs != None:
for name in explicitRefs.split():
if explicitRefs is not None:
if isinstance(explicitRefs, str):
explicitRefs = explicitRefs.split()
for name in explicitRefs:
refs[name] = None
names = [macroPrefix(name) for name in sorted(refs.keys())]
if len(names) > 0:
return ', '.join(names) + '\n'
else:
if not refs:
return None
return ', '.join(macroPrefix(name) for name in sorted(refs.keys())) + '\n'
# Remap include directives in a list of lines so they can be extracted to a
# different directory. Returns remapped lines.
@ -100,25 +113,67 @@ def seeAlsoList(apiName, explicitRefs = None):
# specDir - source directory
def remapIncludes(lines, baseDir, specDir):
# This should be compiled only once
includePat = re.compile('^include::(?P<path>.*)\[\]')
includePat = re.compile(r'^include::(?P<path>.*)\[\]')
newLines = []
for line in lines:
matches = includePat.search(line)
if matches != None:
if matches is not None:
path = matches.group('path')
# Relative path to include file from here
incPath = specDir + '/' + path
# Remap to be relative to baseDir
newPath = os.path.relpath(incPath, baseDir)
newLine = 'include::' + newPath + '[]\n'
logDiag('remapIncludes: remapping', line, '->', newLine)
newLines.append(newLine)
if path[0] != '{':
# Relative path to include file from here
incPath = specDir + '/' + path
# Remap to be relative to baseDir
newPath = os.path.relpath(incPath, baseDir)
newLine = 'include::' + newPath + '[]\n'
logDiag('remapIncludes: remapping', line, '->', newLine)
newLines.append(newLine)
else:
# An asciidoctor variable starts the path.
# This must be an absolute path, not needing to be rewritten.
newLines.append(line)
else:
newLines.append(line)
return newLines
def refPageShell(pageName, pageDesc, fp, sections=None, tail_content=None, man_section=3):
printCopyrightSourceComments(fp)
print(':data-uri:',
':icons: font',
conventions.extra_refpage_headers,
'',
sep='\n', file=fp)
s = '{}({})'.format(pageName, man_section)
print('= ' + s,
'',
sep='\n', file=fp)
if pageDesc.strip() == '':
pageDesc = 'NO SHORT DESCRIPTION PROVIDED'
logWarn('refPageHead: no short description provided for', pageName)
print('== Name',
'{} - {}'.format(pageName, pageDesc),
'',
sep='\n', file=fp)
if sections:
for title, content in sections.items():
print('== {}'.format(title),
'',
content,
'',
sep='\n', file=fp)
if tail_content:
print(tail_content,
'',
sep='\n', file=fp)
# Generate header of a reference page
# pageName - string name of the page
# pageDesc - string short description of the page
@ -128,76 +183,42 @@ def remapIncludes(lines, baseDir, specDir):
# descText - string that goes in the "Description" section
# fp - file to write to
def refPageHead(pageName, pageDesc, specText, fieldName, fieldText, descText, fp):
printCopyrightSourceComments(fp)
sections = OrderedDict()
sections['C Specification'] = specText
if fieldName is not None:
sections[fieldName] = fieldText
print(':data-uri:',
':icons: font',
'include::../config/attribs.txt[]',
'',
sep='\n', file=fp)
if descText is None or descText.strip() == '':
logWarn('refPageHead: no description provided for', pageName)
s = pageName + '(3)'
print('= ' + s,
'',
sep='\n', file=fp)
if descText is not None:
sections['Description'] = descText
if pageDesc.strip() == '':
pageDesc = 'NO SHORT DESCRIPTION PROVIDED'
logWarn('refPageHead: no short description provided for', pageName)
print('== Name',
pageName + ' - ' + pageDesc,
'',
sep='\n', file=fp)
print('== C Specification',
'',
specText,
'',
sep='\n', file=fp)
if fieldName != None:
print('== ' + fieldName,
'',
fieldText,
sep='\n', file=fp)
print('== Description',
'',
descText,
'',
sep='\n', file=fp)
refPageShell(pageName, pageDesc, fp, sections=sections)
def refPageTail(pageName, seeAlso, fp, auto = False):
# This is difficult to get working properly in asciidoc
# specURL = 'link:{vkspecpath}/vkspec.html'
# Where to find the current all-extensions Vulkan HTML spec, so xrefs in
# the asciidoc source that aren't to ref pages can link into it instead.
specURL = 'https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html'
if seeAlso == None:
if seeAlso is None:
seeAlso = 'No cross-references are available\n'
notes = [
'For more information, see the Vulkan Specification at URL',
'For more information, see the ' + apiName + ' Specification at URL',
'',
specURL + '#' + pageName,
conventions.specURL + '#' + pageName,
'',
]
if auto:
notes.extend([
notes.extend((
'This page is a generated document.',
'Fixes and changes should be made to the generator scripts, '
'not directly.',
])
))
else:
notes.extend([
'This page is extracted from the Vulkan Specification. ',
notes.extend((
'This page is extracted from the ' + apiName + ' Specification. ',
'Fixes and changes should be made to the Specification, '
'not directly.',
])
))
print('== See Also',
'',
@ -227,12 +248,12 @@ def emitPage(baseDir, specDir, pi, file):
logDiag('emitPage:', pageName)
# Short description
if pi.desc == None:
if pi.desc is None:
pi.desc = '(no short description available)'
# Not sure how this happens yet
if pi.include == None:
logWarn('emitPage:', pageName, 'INCLUDE == None, no page generated')
if pi.include is None:
logWarn('emitPage:', pageName, 'INCLUDE is None, no page generated')
return
# Specification text
@ -242,7 +263,7 @@ def emitPage(baseDir, specDir, pi, file):
# Member/parameter list, if there is one
field = None
fieldText = None
if pi.param != None:
if pi.param is not None:
if pi.type == 'structs':
field = 'Members'
elif pi.type in ['protos', 'funcpointers']:
@ -254,16 +275,23 @@ def emitPage(baseDir, specDir, pi, file):
fieldText = ''.join(lines)
# Description text
lines = remapIncludes(file[pi.body:pi.end+1], baseDir, specDir)
descText = ''.join(lines)
if pi.body != pi.include:
lines = remapIncludes(file[pi.body:pi.end+1], baseDir, specDir)
descText = ''.join(lines)
else:
descText = None
logWarn('emitPage: INCLUDE == BODY, so description will be empty for', pi.name)
if pi.begin != pi.include:
logWarn('emitPage: Note: BEGIN != INCLUDE, so the description might be incorrectly located before the API include!')
# Substitute xrefs to point at the main spec
specLinksPattern = re.compile(r'<<([^>,]+)[,]?[ \t\n]*([^>,]*)>>')
specLinksSubstitute = r"link:{html_spec_relative}#\1[\2]"
specText, n = specLinksPattern.subn(specLinksSubstitute, specText)
if fieldText != None:
fieldText, n = specLinksPattern.subn(specLinksSubstitute, fieldText)
descText, n = specLinksPattern.subn(specLinksSubstitute, descText)
specText, _ = specLinksPattern.subn(specLinksSubstitute, specText)
if fieldText is not None:
fieldText, _ = specLinksPattern.subn(specLinksSubstitute, fieldText)
if descText is not None:
descText, _ = specLinksPattern.subn(specLinksSubstitute, descText)
fp = open(pageName, 'w', encoding='utf-8')
refPageHead(pi.name,
@ -290,7 +318,7 @@ def autoGenEnumsPage(baseDir, pi, file):
logDiag('autoGenEnumsPage:', pageName)
# Short description
if pi.desc == None:
if pi.desc is None:
pi.desc = '(no short description available)'
# Description text. Allow for the case where an enum definition
@ -298,16 +326,16 @@ def autoGenEnumsPage(baseDir, pi, file):
if not pi.embed:
embedRef = ''
else:
embedRef = ''.join([
' * The reference page for ',
macroPrefix(pi.embed),
', where this interface is defined.\n' ])
embedRef = ''.join((
' * The reference page for ',
macroPrefix(pi.embed),
', where this interface is defined.\n' ))
txt = ''.join([
txt = ''.join((
'For more information, see:\n\n',
embedRef,
' * The See Also section for other reference pages using this type.\n',
' * The Vulkan Specification.\n' ])
' * The ' + apiName + ' Specification.\n' ))
refPageHead(pi.name,
pi.desc,
@ -318,12 +346,15 @@ def autoGenEnumsPage(baseDir, pi, file):
refPageTail(pi.name, seeAlsoList(pi.name, pi.refs), fp, auto = True)
fp.close()
# Pattern to break apart a Vk*Flags{authorID} name, used in autoGenFlagsPage.
flagNamePat = re.compile('(?P<name>\w+)Flags(?P<author>[A-Z]*)')
# Autogenerate a single reference page in baseDir for a Vk*Flags type
# Pattern to break apart an API *Flags{authorID} name, used in
# autoGenFlagsPage.
flagNamePat = re.compile(r'(?P<name>\w+)Flags(?P<author>[A-Z]*)')
# Autogenerate a single reference page in baseDir for an API *Flags type
# baseDir - base directory to emit page into
# flagName - Vk*Flags name
# flagName - API *Flags name
def autoGenFlagsPage(baseDir, flagName):
pageName = baseDir + '/' + flagName + '.txt'
fp = open(pageName, 'w', encoding='utf-8')
@ -335,7 +366,7 @@ def autoGenFlagsPage(baseDir, flagName):
# Short description
matches = flagNamePat.search(flagName)
if matches != None:
if matches is not None:
name = matches.group('name')
author = matches.group('author')
logDiag('autoGenFlagsPage: split name into', name, 'Flags', author)
@ -344,19 +375,19 @@ def autoGenFlagsPage(baseDir, flagName):
else:
logWarn('autoGenFlagsPage:', pageName, 'does not end in "Flags{author ID}". Cannot infer FlagBits type.')
flagBits = None
desc = 'Unknown Vulkan flags type'
desc = 'Unknown ' + apiName + ' flags type'
# Description text
if flagBits != None:
txt = ''.join([
if flagBits is not None:
txt = ''.join((
'etext:' + flagName,
' is a mask of zero or more elink:' + flagBits + '.\n',
'It is used as a member and/or parameter of the structures and commands\n',
'in the See Also section below.\n' ])
'in the See Also section below.\n' ))
else:
txt = ''.join([
txt = ''.join((
'etext:' + flagName,
' is an unknown Vulkan type, assumed to be a bitmask.\n' ])
' is an unknown ' + apiName + ' type, assumed to be a bitmask.\n' ))
refPageHead(flagName,
desc,
@ -367,9 +398,9 @@ def autoGenFlagsPage(baseDir, flagName):
refPageTail(flagName, seeAlsoList(flagName), fp, auto = True)
fp.close()
# Autogenerate a single handle page in baseDir for a Vk* handle type
# Autogenerate a single handle page in baseDir for an API handle type
# baseDir - base directory to emit page into
# handleName - Vk* handle name
# handleName - API handle name
# @@ Need to determine creation function & add handles/ include for the
# @@ interface in generator.py.
def autoGenHandlePage(baseDir, handleName):
@ -382,14 +413,14 @@ def autoGenHandlePage(baseDir, handleName):
logDiag('autoGenHandlePage:', pageName)
# Short description
desc = 'Vulkan object handle'
desc = apiName + ' object handle'
descText = ''.join([
descText = ''.join((
'sname:' + handleName,
' is an object handle type, referring to an object used\n',
'by the Vulkan implementation. These handles are created or allocated\n',
'by the vk @@ TBD @@ function, and used by other Vulkan structures\n',
'and commands in the See Also section below.\n' ])
'by the ' + apiName + ' implementation. These handles are created or allocated\n',
'by the @@ TBD @@ function, and used by other ' + apiName + ' structures\n',
'and commands in the See Also section below.\n' ))
refPageHead(handleName,
desc,
@ -406,7 +437,7 @@ def autoGenHandlePage(baseDir, handleName):
#
def genRef(specFile, baseDir):
file = loadFile(specFile)
if file == None:
if file is None:
return
# Save the path to this file for later use in rewriting relative includes
@ -422,7 +453,7 @@ def genRef(specFile, baseDir):
# Create each page, if possible
for name in sorted(pageMap.keys()):
for name in sorted(pageMap):
pi = pageMap[name]
printPageInfo(pi, file)
@ -441,7 +472,7 @@ def genRef(specFile, baseDir):
logWarn('genRef: Cannot extract or autogenerate:', pi.name)
# Generate baseDir/apispec.txt, the single-page version of the ref pages.
# This assumes there's a page for everything in the vkapi.py dictionaries.
# This assumes there's a page for everything in the api module dictionaries.
# Extensions (KHR, EXT, etc.) are currently skipped
def genSinglePageRef(baseDir):
# Accumulate head of page
@ -449,7 +480,7 @@ def genSinglePageRef(baseDir):
printCopyrightSourceComments(head)
print('= Vulkan API Reference Pages',
print('= ' + apiName + ' API Reference Pages',
':data-uri:',
':icons: font',
':doctype: book',
@ -467,14 +498,16 @@ def genSinglePageRef(baseDir):
# this for us.
sections = [
[ vkapi.protos, 'protos', 'Vulkan Commands' ],
[ vkapi.handles, 'handles', 'Object Handles' ],
[ vkapi.structs, 'structs', 'Structures' ],
[ vkapi.enums, 'enums', 'Enumerations' ],
[ vkapi.flags, 'flags', 'Flags' ],
[ vkapi.funcpointers, 'funcpointers', 'Function Pointer Types' ],
[ vkapi.basetypes, 'basetypes', 'Vulkan Scalar types' ],
[ vkapi.defines, 'defines', 'C Macro Definitions' ] ]
[ api.protos, 'protos', apiName + ' Commands' ],
[ api.handles, 'handles', 'Object Handles' ],
[ api.structs, 'structs', 'Structures' ],
[ api.enums, 'enums', 'Enumerations' ],
[ api.flags, 'flags', 'Flags' ],
[ api.funcpointers, 'funcpointers', 'Function Pointer Types' ],
[ api.basetypes, 'basetypes', apiName + ' Scalar types' ],
[ api.defines, 'defines', 'C Macro Definitions' ],
[ extensions, 'extensions', apiName + ' Extensions' ]
]
# Accumulate body of page
body = io.StringIO()
@ -489,34 +522,34 @@ def genSinglePageRef(baseDir):
'',
sep='\n', file=body)
for refPage in sorted(apiDict.keys()):
if label == 'extensions':
# preserve order of extensions since we already sorted the way we want.
keys = apiDict.keys()
else:
keys = sorted(apiDict.keys())
for refPage in keys:
# Don't generate links for aliases, which are included with the
# aliased page
if refPage not in vkapi.alias:
if refPage not in vkapi.flags:
# Add page to body
print('include::' + refPage + '.txt[]', file=body)
elif vkapi.flags[refPage] is not None:
# Add page to body
print('include::' + refPage + '.txt[]', file=body)
if refPage not in api.alias:
# Add page to body
if 'FlagBits' in refPage and conventions.unified_flag_refpages:
# OpenXR does not create separate ref pages for FlagBits:
# the FlagBits includes go in the Flags refpage.
# Previously the Vulkan script would only emit non-empty
# Vk*Flags pages, via the logic
# if refPage not in api.flags or api.flags[refPage] is not None
# emit page
# Now, all are emitted.
continue
else:
# Don't add page
logWarn('(Benign) Not including', refPage,
'in single-page reference',
'because it is an empty Flags type')
# Previously, a page was added only when:
# if apiDict == defines or not isextension(refPage):
# Now, all extensions are added (though ideally, only the
# extensions specifically requested would be added - there's an
# implicit expectation here that 'make man/apispec.txt' was
# generated via 'makeAllExts' or equivalent).
print('include::' + refPage + '.txt[]', file=body)
else:
# Alternatively, we could (probably should) link to the
# aliased refpage
logWarn('(Benign) Not including', refPage,
'in single-page reference',
'because it is an alias of', vkapi.alias[refPage])
'because it is an alias of', api.alias[refPage])
print('\n' + ':leveloffset: 0' + '\n', file=body)
@ -531,9 +564,57 @@ def genSinglePageRef(baseDir):
body.close()
fp.close()
if __name__ == '__main__':
def genExtension(baseDir, name, info):
# Add a dictionary entry for this page
global genDict
genDict[name] = None
declares = []
elem = info.elem
ext_type = elem.get('type')
for required in elem.find('require'):
req_name = required.get('name')
if not req_name:
# This isn't what we're looking for
continue
if req_name.endswith('_SPEC_VERSION') or req_name.endswith('_EXTENSION_NAME'):
# Don't link to spec version or extension name - those ref pages aren't created.
continue
if required.get('extends'):
# These are either extensions of enums,
# or enum values: neither of which get a ref page.
continue
if req_name not in genDict:
logWarn('ERROR: {} (in extension {}) does not have a ref page.'.format(req_name, name))
declares.append(req_name)
pageName = baseDir + '/' + name + '.txt'
logDiag('genExtension:', pageName)
fp = open(pageName, 'w', encoding='utf-8')
sections = OrderedDict()
sections['Specification'] = 'See link:{html_spec_relative}#%s[ %s] in the main specification for complete information.' % (
name, name)
refPageShell(name,
"{} extension".format(ext_type),
fp,
sections=sections,
tail_content=makeExtensionInclude(name))
refPageTail(name, seeAlsoList(name, declares), fp, auto=True)
fp.close()
if __name__ == '__main__':
global genDict, extensions, conventions, apiName
genDict = {}
extensions = OrderedDict()
conventions = APIConventions()
apiName = conventions.api_name
parser = argparse.ArgumentParser()
@ -551,6 +632,12 @@ if __name__ == '__main__':
parser.add_argument('files', metavar='filename', nargs='*',
help='a filename to extract ref pages from')
parser.add_argument('--version', action='version', version='%(prog)s 1.0')
parser.add_argument('-extension', action='append',
default=[],
help='Specify an extension or extensions to add to targets')
parser.add_argument('-registry', action='store',
default=conventions.registry_path,
help='Use specified registry file instead of default')
results = parser.parse_args()
@ -564,39 +651,64 @@ if __name__ == '__main__':
genRef(file, baseDir)
# Now figure out which pages *weren't* generated from the spec.
# This relies on the dictionaries of API constructs in vkapi.py.
# This relies on the dictionaries of API constructs in the api module.
# For Flags (e.g. Vk*Flags types), it's easy to autogenerate pages.
if not results.noauto:
registry = Registry()
registry.loadFile(results.registry)
if conventions.write_refpage_include:
# Only extensions with a supported="..." attribute in this set
# will be considered for extraction/generation.
supported_strings = set((conventions.xml_supported_name_of_api,))
ext_names = set(k for k, v in registry.extdict.items()
if v.supported in supported_strings)
desired_extensions = ext_names.intersection(set(results.extension))
for prefix in conventions.extension_index_prefixes:
# Splits up into chunks, sorted within each chunk.
filtered_extensions = sorted(
[name for name in ext_names
if name.startswith(prefix) and name not in extensions])
for name in filtered_extensions:
extensions[name] = None
genExtension(baseDir, name, registry.extdict[name])
# autoGenFlagsPage is no longer needed because they are added to
# the spec sources now.
# for page in flags.keys():
# if not (page in genDict.keys()):
# for page in api.flags:
# if page not in genDict:
# autoGenFlagsPage(baseDir, page)
# autoGenHandlePage is no longer needed because they are added to
# the spec sources now.
# for page in structs.keys():
# for page in api.structs:
# if typeCategory[page] == 'handle':
# autoGenHandlePage(baseDir, page)
sections = [
[ vkapi.flags, 'Flags Type' ],
[ vkapi.enums, 'Enum Type ' ],
[ vkapi.structs, 'Structure ' ],
[ vkapi.protos, 'Command ' ],
[ vkapi.funcpointers, 'Funcptr ' ],
[ vkapi.basetypes, 'Base Type ' ] ]
( api.flags, 'Flag Types' ),
( api.enums, 'Enumerated Types' ),
( api.structs, 'Structures' ),
( api.protos, 'Prototypes' ),
( api.funcpointers, 'Function Pointers' ),
( api.basetypes, apiName + ' Scalar Types' ),
( extensions, apiName + ' Extensions'),
]
# Summarize pages that weren't generated, for good or bad reasons
for (apiDict,title) in sections:
for page in apiDict.keys():
if not (page in genDict.keys()):
# OpenXR was keeping a 'flagged' state which only printed out a
# warning for the first non-generated page, but was otherwise
# unused. This doesn't seem helpful.
for page in apiDict:
if page not in genDict:
# Page was not generated - why not?
if page in vkapi.alias:
logWarn('(Benign, is an alias) Ref page for', title, page, 'is aliased into', vkapi.alias[page])
elif page in vkapi.flags and vkapi.flags[page] is None:
if page in api.alias:
logWarn('(Benign, is an alias) Ref page for', title, page, 'is aliased into', api.alias[page])
elif page in api.flags and api.flags[page] is None:
logWarn('(Benign, no FlagBits defined) No ref page generated for ', title,
page)
else:

View File

@ -15,35 +15,34 @@
# limitations under the License.
from __future__ import unicode_literals
import io,os,re,sys,pdb
import io
import os
import re
import pdb
import sys
from pathlib import Path
def write( *args, **kwargs ):
file = kwargs.pop('file',sys.stdout)
end = kwargs.pop('end','\n')
file.write(' '.join([str(arg) for arg in args]))
file.write(' '.join(str(arg) for arg in args))
file.write(end)
# noneStr - returns string argument, or "" if argument is None.
# Used in converting etree Elements into text.
# str - string to convert
def noneStr(str):
if (str):
return str
else:
return ""
# s - string to convert
def noneStr(s):
if s:
return s
return ""
# enquote - returns string argument with surrounding quotes,
# for serialization into Python code.
def enquote(str):
if (str):
return "'" + str + "'"
else:
return None
# apiName - returns True if name is a Vulkan name (vk/Vk/VK prefix, or a
# function pointer type), False otherwise.
def apiName(str):
return str[0:2].lower() == 'vk' or str[0:3] == 'PFN'
def enquote(s):
if s:
return "'{}'".format(s)
return None
# Primary sort key for regSortFeatures.
# Sorts by category of the feature name string:
@ -52,14 +51,14 @@ def apiName(str):
# other (EXT/vendor extensions)
# This will need changing for Vulkan!
def regSortCategoryKey(feature):
if (feature.elem.tag == 'feature'):
if feature.elem.tag == 'feature':
return 0
elif (feature.category == 'ARB' or
feature.category == 'KHR' or
feature.category == 'OES'):
if (feature.category == 'ARB' or
feature.category == 'KHR' or
feature.category == 'OES'):
return 1
else:
return 2
return 2
# Secondary sort key for regSortFeatures.
# Sorts by extension name.
@ -90,6 +89,8 @@ def regSortFeatures(featureList):
# Registry.apiGen() and by base OutputGenerator objects.
#
# Members
# conventions - may be mandatory for some generators:
# an object that implements ConventionsBase
# filename - basename of file to generate, or None to write to stdout.
# directory - directory in which to generate filename
# apiname - string matching <api> 'apiname' attribute, e.g. 'gl'.
@ -119,7 +120,9 @@ def regSortFeatures(featureList):
# nothing.
class GeneratorOptions:
"""Represents options during header production from an API registry"""
def __init__(self,
conventions = None,
filename = None,
directory = '.',
apiname = None,
@ -131,6 +134,7 @@ class GeneratorOptions:
removeExtensions = None,
emitExtensions = None,
sortProcedure = regSortFeatures):
self.conventions = conventions
self.filename = filename
self.directory = directory
self.apiname = apiname
@ -142,14 +146,14 @@ class GeneratorOptions:
self.removeExtensions = self.emptyRegex(removeExtensions)
self.emitExtensions = self.emptyRegex(emitExtensions)
self.sortProcedure = sortProcedure
#
# Substitute a regular expression which matches no version
# or extension names for None or the empty string.
def emptyRegex(self,pat):
if (pat == None or pat == ''):
def emptyRegex(self, pat):
if pat is None or pat == '':
return '_nomatch_^'
else:
return pat
return pat
# OutputGenerator - base class for generating API interfaces.
# Manages basic logic, logging, and output file control
@ -195,7 +199,7 @@ class GeneratorOptions:
#
class OutputGenerator:
"""Generate specified API interfaces in a specific style, such as a C header"""
#
# categoryToPath - map XML 'category' to include file directory name
categoryToPath = {
'bitmask' : 'flags',
@ -205,7 +209,7 @@ class OutputGenerator:
'define' : 'defines',
'basetype' : 'basetypes',
}
#
# Constructor
def __init__(self,
errFile = sys.stderr,
@ -223,7 +227,7 @@ class OutputGenerator:
self.extBase = 1000000000
self.extBlockSize = 1000
self.madeDirs = {}
#
# logMsg - write a message of different categories to different
# destinations.
# level -
@ -233,22 +237,22 @@ class OutputGenerator:
# *args - print()-style arguments to direct to corresponding log
def logMsg(self, level, *args):
"""Log a message at the given level. Can be ignored or log to a file"""
if (level == 'error'):
if level == 'error':
strfile = io.StringIO()
write('ERROR:', *args, file=strfile)
if (self.errFile != None):
if self.errFile is not None:
write(strfile.getvalue(), file=self.errFile)
raise UserWarning(strfile.getvalue())
elif (level == 'warn'):
if (self.warnFile != None):
elif level == 'warn':
if self.warnFile is not None:
write('WARNING:', *args, file=self.warnFile)
elif (level == 'diag'):
if (self.diagFile != None):
elif level == 'diag':
if self.diagFile is not None:
write('DIAG:', *args, file=self.diagFile)
else:
raise UserWarning(
'*** FATAL ERROR in Generator.logMsg: unknown level:' + level)
#
# enumToValue - parses and converts an <enum> tag into a value.
# Returns a list
# first element - integer representation of the value, or None
@ -264,39 +268,41 @@ class OutputGenerator:
# 'extbase' extension name, which is then cast to the
# typename specified by 'extends'. This requires probing
# the registry database, and imbeds knowledge of the
# Vulkan extension enum scheme in this function.
# API extension enum scheme in this function.
# A 'alias' attribute contains the name of another enum
# which this is an alias of. The other enum must be
# declared first when emitting this enum.
def enumToValue(self, elem, needsNum):
name = elem.get('name')
numVal = None
if ('value' in elem.keys()):
if 'value' in elem.keys():
value = elem.get('value')
# print('About to translate value =', value, 'type =', type(value))
if (needsNum):
if needsNum:
numVal = int(value, 0)
# If there's a non-integer, numeric 'type' attribute (e.g. 'u' or
# 'ull'), append it to the string value.
# t = enuminfo.elem.get('type')
# if (t != None and t != '' and t != 'i' and t != 's'):
# if t is not None and t != '' and t != 'i' and t != 's':
# value += enuminfo.type
self.logMsg('diag', 'Enum', name, '-> value [', numVal, ',', value, ']')
return [numVal, value]
if ('bitpos' in elem.keys()):
if 'bitpos' in elem.keys():
value = elem.get('bitpos')
numVal = int(value, 0)
numVal = 1 << numVal
bitpos = int(value, 0)
numVal = 1 << bitpos
value = '0x%08x' % numVal
if( bitpos >= 32 ):
value = value + 'ULL'
self.logMsg('diag', 'Enum', name, '-> bitpos [', numVal, ',', value, ']')
return [numVal, value]
if ('offset' in elem.keys()):
if 'offset' in elem.keys():
# Obtain values in the mapping from the attributes
enumNegative = False
offset = int(elem.get('offset'),0)
extnumber = int(elem.get('extnumber'),0)
extends = elem.get('extends')
if ('dir' in elem.keys()):
if 'dir' in elem.keys():
enumNegative = True
self.logMsg('diag', 'Enum', name, 'offset =', offset,
'extnumber =', extnumber, 'extends =', extends,
@ -304,8 +310,8 @@ class OutputGenerator:
# Now determine the actual enumerant value, as defined
# in the "Layers and Extensions" appendix of the spec.
numVal = self.extBase + (extnumber - 1) * self.extBlockSize + offset
if (enumNegative):
numVal = -numVal
if enumNegative:
numVal *= -1
value = '%d' % numVal
# More logic needed!
self.logMsg('diag', 'Enum', name, '-> offset [', numVal, ',', value, ']')
@ -313,7 +319,7 @@ class OutputGenerator:
if 'alias' in elem.keys():
return [None, elem.get('alias')]
return [None, None]
#
# checkDuplicateEnums - sanity check for enumerated values
# enums - list of <enum> Elements
# returns the list with duplicates stripped
@ -336,7 +342,7 @@ class OutputGenerator:
# Duplicate enum values for the same name are benign. This
# happens when defining the same enum conditionally in
# several extension blocks.
if (strVal2 == strVal or (numVal != None and
if (strVal2 == strVal or (numVal is not None and
numVal == numVal2)):
True
# self.logMsg('info', 'checkDuplicateEnums: Duplicate enum (' + name +
@ -361,7 +367,7 @@ class OutputGenerator:
# Track this enum to detect followon duplicates
nameMap[name] = [ elem, numVal, strVal ]
if numVal != None:
if numVal is not None:
valueMap[numVal] = [ elem, numVal, strVal ]
# Add this enum to the list
@ -369,58 +375,194 @@ class OutputGenerator:
# Return the list
return stripped
#
# buildEnumCDecl
# Generates the C declaration for an enum
def buildEnumCDecl(self, expand, groupinfo, groupName):
groupElem = groupinfo.elem
if self.genOpts.conventions.constFlagBits and groupElem.get('type') == 'bitmask':
return self.buildEnumCDecl_Bitmask( groupinfo, groupName)
else:
return self.buildEnumCDecl_Enum(expand, groupinfo, groupName)
# buildEnumCDecl_Bitmask
# Generates the C declaration for an "enum" that is actually a
# set of flag bits
def buildEnumCDecl_Bitmask(self, groupinfo, groupName):
groupElem = groupinfo.elem
flagTypeName = groupinfo.flagType.elem.get('name')
# Prefix
body = "// Flag bits for " + flagTypeName + "\n"
# Loop over the nested 'enum' tags.
for elem in groupElem.findall('enum'):
# Convert the value to an integer and use that to track min/max.
# Values of form -(number) are accepted but nothing more complex.
# Should catch exceptions here for more complex constructs. Not yet.
(_, strVal) = self.enumToValue(elem, True)
name = elem.get('name')
body += "static const " + flagTypeName + " " + name + " = " + strVal + ";\n"
# Postfix
return ("bitmask", body)
# Generates the C declaration for an enumerated type
def buildEnumCDecl_Enum(self, expand, groupinfo, groupName):
groupElem = groupinfo.elem
# Break the group name into prefix and suffix portions for range
# enum generation
expandName = re.sub(r'([0-9a-z_])([A-Z0-9])',r'\1_\2',groupName).upper()
expandPrefix = expandName
expandSuffix = ''
expandSuffixMatch = re.search(r'[A-Z][A-Z]+$',groupName)
if expandSuffixMatch:
expandSuffix = '_' + expandSuffixMatch.group()
# Strip off the suffix from the prefix
expandPrefix = expandName.rsplit(expandSuffix, 1)[0]
# Prefix
body = "typedef enum " + groupName + " {\n"
# @@ Should use the type="bitmask" attribute instead
isEnum = ('FLAG_BITS' not in expandPrefix)
# Get a list of nested 'enum' tags.
enums = groupElem.findall('enum')
# Check for and report duplicates, and return a list with them
# removed.
enums = self.checkDuplicateEnums(enums)
# Loop over the nested 'enum' tags. Keep track of the minimum and
# maximum numeric values, if they can be determined; but only for
# core API enumerants, not extension enumerants. This is inferred
# by looking for 'extends' attributes.
minName = None
# Accumulate non-numeric enumerant values separately and append
# them following the numeric values, to allow for aliases.
# NOTE: this doesn't do a topological sort yet, so aliases of
# aliases can still get in the wrong order.
aliasText = ""
for elem in enums:
# Convert the value to an integer and use that to track min/max.
# Values of form -(number) are accepted but nothing more complex.
# Should catch exceptions here for more complex constructs. Not yet.
(numVal,strVal) = self.enumToValue(elem, True)
name = elem.get('name')
# Extension enumerants are only included if they are required
if self.isEnumRequired(elem):
decl = " " + name + " = " + strVal + ",\n"
if numVal is not None:
body += decl
else:
aliasText += decl
# Don't track min/max for non-numbers (numVal is None)
if isEnum and numVal is not None and elem.get('extends') is None:
if minName is None:
minName = maxName = name
minValue = maxValue = numVal
elif numVal < minValue:
minName = name
minValue = numVal
elif numVal > maxValue:
maxName = name
maxValue = numVal
# Now append the non-numeric enumerant values
body += aliasText
# Generate min/max value tokens and a range-padding enum. Need some
# additional padding to generate correct names...
if isEnum and expand:
body += " " + expandPrefix + "_BEGIN_RANGE" + expandSuffix + " = " + minName + ",\n"
body += " " + expandPrefix + "_END_RANGE" + expandSuffix + " = " + maxName + ",\n"
body += " " + expandPrefix + "_RANGE_SIZE" + expandSuffix + " = (" + maxName + " - " + minName + " + 1),\n"
# Always generate this to make sure the enumerated type is 32 bits
body += " " + expandPrefix + "_MAX_ENUM" + expandSuffix + " = 0x7FFFFFFF\n"
# Postfix
body += "} " + groupName + ";"
# Determine appropriate section for this declaration
if groupElem.get('type') == 'bitmask':
section = 'bitmask'
else:
section = 'group'
return (section, body)
def makeDir(self, path):
self.logMsg('diag', 'OutputGenerator::makeDir(' + path + ')')
if not (path in self.madeDirs.keys()):
if path not in self.madeDirs:
# This can get race conditions with multiple writers, see
# https://stackoverflow.com/questions/273192/
if not os.path.exists(path):
os.makedirs(path)
self.madeDirs[path] = None
#
def beginFile(self, genOpts):
self.genOpts = genOpts
#
# Open specified output file. Not done in constructor since a
# Generator can be used without writing to a file.
if (self.genOpts.filename != None):
filename = self.genOpts.directory + '/' + self.genOpts.filename
self.outFile = io.open(filename, 'w', encoding='utf-8')
if self.genOpts.filename is not None:
if sys.platform == 'win32':
directory = Path(self.genOpts.directory)
if not os.path.exists(directory):
os.makedirs(directory)
self.outFile = io.open(directory / self.genOpts.filename, 'w', encoding='utf-8')
else:
filename = self.genOpts.directory + '/' + self.genOpts.filename
self.outFile = io.open(filename, 'w', encoding='utf-8')
else:
self.outFile = sys.stdout
def endFile(self):
self.errFile and self.errFile.flush()
self.warnFile and self.warnFile.flush()
self.diagFile and self.diagFile.flush()
if self.errFile:
self.errFile.flush()
if self.warnFile:
self.warnFile.flush()
if self.diagFile:
self.diagFile.flush()
self.outFile.flush()
if (self.outFile != sys.stdout and self.outFile != sys.stderr):
if self.outFile != sys.stdout and self.outFile != sys.stderr:
self.outFile.close()
self.genOpts = None
#
def beginFeature(self, interface, emit):
self.emit = emit
self.featureName = interface.get('name')
# If there's an additional 'protect' attribute in the feature, save it
self.featureExtraProtect = interface.get('protect')
def endFeature(self):
# Derived classes responsible for emitting feature
self.featureName = None
self.featureExtraProtect = None
# Utility method to validate we're generating something only inside a
# <feature> tag
def validateFeature(self, featureType, featureName):
if (self.featureName == None):
if self.featureName is None:
raise UserWarning('Attempt to generate', featureType,
featureName, 'when not in feature')
#
featureName, 'when not in feature')
# Type generation
def genType(self, typeinfo, name, alias):
self.validateFeature('type', name)
#
# Struct (e.g. C "struct" type) generation
def genStruct(self, typeinfo, name, alias):
self.validateFeature('struct', name)
def genStruct(self, typeinfo, typeName, alias):
self.validateFeature('struct', typeName)
# The mixed-mode <member> tags may contain no-op <comment> tags.
# It is convenient to remove them here where all output generators
@ -428,28 +570,29 @@ class OutputGenerator:
for member in typeinfo.elem.findall('.//member'):
for comment in member.findall('comment'):
member.remove(comment)
#
# Group (e.g. C "enum" type) generation
def genGroup(self, groupinfo, name, alias):
self.validateFeature('group', name)
#
def genGroup(self, groupinfo, groupName, alias):
self.validateFeature('group', groupName)
# Enumerant (really, constant) generation
def genEnum(self, enuminfo, name, alias):
self.validateFeature('enum', name)
#
def genEnum(self, enuminfo, typeName, alias):
self.validateFeature('enum', typeName)
# Command generation
def genCmd(self, cmd, name, alias):
self.validateFeature('command', name)
#
def genCmd(self, cmd, cmdinfo, alias):
self.validateFeature('command', cmdinfo)
# Utility functions - turn a <proto> <name> into C-language prototype
# and typedef declarations for that name.
# name - contents of <name> tag
# tail - whatever text follows that tag in the Element
def makeProtoName(self, name, tail):
return self.genOpts.apientry + name + tail
def makeTypedefName(self, name, tail):
return '(' + self.genOpts.apientryp + 'PFN_' + name + tail + ')'
#
return '(' + self.genOpts.apientryp + 'PFN_' + name + tail + ')'
# makeCParamDecl - return a string which is an indented, formatted
# declaration for a <param> or <member> block (e.g. function parameter
# or structure/union member).
@ -461,7 +604,11 @@ class OutputGenerator:
for elem in param:
text = noneStr(elem.text)
tail = noneStr(elem.tail)
if (elem.tag == 'name' and aligncol > 0):
if self.genOpts.conventions.is_voidpointer_alias(elem.tag, text, tail):
# OpenXR-specific macro insertion
tail = self.genOpts.conventions.make_voidpointer_alias(tail)
if elem.tag == 'name' and aligncol > 0:
self.logMsg('diag', 'Aligning parameter', elem.text, 'to column', self.genOpts.alignFuncParam)
# Align at specified column, if possible
paramdecl = paramdecl.rstrip()
@ -474,7 +621,7 @@ class OutputGenerator:
self.logMsg('diag', 'Adjust length of parameter decl from', oldLen, 'to', newLen, ':', paramdecl)
paramdecl += text + tail
return paramdecl
#
# getCParamTypeLength - return the length of the type field is an indented, formatted
# declaration for a <param> or <member> block (e.g. function parameter
# or structure/union member).
@ -484,18 +631,23 @@ class OutputGenerator:
for elem in param:
text = noneStr(elem.text)
tail = noneStr(elem.tail)
if (elem.tag == 'name'):
if self.genOpts.conventions.is_voidpointer_alias(elem.tag, text, tail):
# OpenXR-specific macro insertion
tail = self.genOpts.conventions.make_voidpointer_alias(tail)
if elem.tag == 'name':
# Align at specified column, if possible
newLen = len(paramdecl.rstrip())
self.logMsg('diag', 'Identifying length of', elem.text, 'as', newLen)
paramdecl += text + tail
return newLen
#
# isEnumRequired(elem) - return True if this <enum> element is
# required, False otherwise
# elem - <enum> element to test
def isEnumRequired(self, elem):
required = elem.get('required') != None
required = elem.get('required') is not None
self.logMsg('diag', 'isEnumRequired:', elem.get('name'),
'->', required)
return required
@ -520,7 +672,6 @@ class OutputGenerator:
return required
#
# makeCDecls - return C prototype and function pointer typedef for a
# command, as a two-element list of strings.
# cmd - Element containing a <command> tag
@ -531,7 +682,7 @@ class OutputGenerator:
# Begin accumulating prototype and typedef strings
pdecl = self.genOpts.apicall
tdecl = 'typedef '
#
# Insert the function return type/name.
# For prototypes, add APIENTRY macro before the name
# For typedefs, add (APIENTRY *<name>) around the name and
@ -547,7 +698,7 @@ class OutputGenerator:
for elem in proto:
text = noneStr(elem.text)
tail = noneStr(elem.tail)
if (elem.tag == 'name'):
if elem.tag == 'name':
pdecl += self.makeProtoName(text, tail)
tdecl += self.makeTypedefName(text, tail)
else:
@ -560,36 +711,28 @@ class OutputGenerator:
# Uses: self.indentFuncProto
# self.indentFuncPointer
# self.alignFuncParam
# Might be able to doubly-nest the joins, e.g.
# ','.join(('_'.join([l[i] for i in range(0,len(l))])
n = len(params)
# Indented parameters
if n > 0:
indentdecl = '(\n'
for i in range(0,n):
paramdecl = self.makeCParamDecl(params[i], self.genOpts.alignFuncParam)
if (i < n - 1):
paramdecl += ',\n'
else:
paramdecl += ');'
indentdecl += paramdecl
indentdecl += ',\n'.join(self.makeCParamDecl(p, self.genOpts.alignFuncParam)
for p in params)
indentdecl += ');'
else:
indentdecl = '(void);'
# Non-indented parameters
paramdecl = '('
if n > 0:
for i in range(0,n):
paramdecl += ''.join([t for t in params[i].itertext()])
if (i < n - 1):
paramdecl += ', '
paramnames = (''.join(t for t in p.itertext())
for p in params)
paramdecl += ', '.join(paramnames)
else:
paramdecl += 'void'
paramdecl += ");";
paramdecl += ");"
return [ pdecl + indentdecl, tdecl + paramdecl ]
#
def newline(self):
write('', file=self.outFile)
def setRegistry(self, registry):
self.registry = registry
#

View File

@ -66,12 +66,12 @@ def buildRelease(label,
outarg = 'OUTDIR=' + outdir
if (versions != None and len(versions) > 0):
if versions != None and len(versions) > 0:
versarg = 'VERSIONS="' + ' '.join(versions) + '"'
else:
versarg = ''
if (extensions != None and len(extensions) > 0):
if extensions != None and len(extensions) > 0:
extarg = 'EXTENSIONS="' + ' '.join(extensions) + '"'
else:
extarg = ''
@ -81,7 +81,7 @@ def buildRelease(label,
else:
ratifiedarg = ''
if (apititle != None):
if apititle != None:
titlearg = 'APITITLE="' + apititle + '"'
else:
titlearg = ''
@ -112,7 +112,7 @@ def buildRelease(label,
'NOTEOPTS="-a implementation-guide"',
specTargets)
if (miscSrc != None and miscDst != None):
if miscSrc != None and miscDst != None:
print('mkdir -p', miscDst)
print('cp', miscSrc + '/*.txt', miscDst + '/')

View File

@ -23,7 +23,7 @@ from extensionmetadocgenerator import ExtensionMetaDocGeneratorOptions, Extensio
from pygenerator import PyOutputGenerator
from validitygenerator import ValidityOutputGenerator
from hostsyncgenerator import HostSynchronizationOutputGenerator
from extensionStubSource import ExtensionStubSourceOutputGenerator
from vkconventions import VulkanConventions
# Simple timer functions
startTime = None
@ -122,6 +122,9 @@ def makeGenOpts(args):
protectFeature = protect
protectProto = protect
# An API style conventions object
conventions = VulkanConventions()
# API include files for spec and ref pages
# Overwrites include subdirectories in spec source tree
# The generated include files do not include the calling convention
@ -132,6 +135,7 @@ def makeGenOpts(args):
genOpts['apiinc'] = [
DocOutputGenerator,
DocGeneratorOptions(
conventions = conventions,
filename = 'timeMarker',
directory = directory,
apiname = 'vulkan',
@ -154,6 +158,7 @@ def makeGenOpts(args):
genOpts['vkapi.py'] = [
PyOutputGenerator,
DocGeneratorOptions(
conventions = conventions,
filename = 'vkapi.py',
directory = directory,
apiname = 'vulkan',
@ -170,6 +175,7 @@ def makeGenOpts(args):
genOpts['validinc'] = [
ValidityOutputGenerator,
DocGeneratorOptions(
conventions = conventions,
filename = 'timeMarker',
directory = directory,
apiname = 'vulkan',
@ -186,6 +192,7 @@ def makeGenOpts(args):
genOpts['hostsyncinc'] = [
HostSynchronizationOutputGenerator,
DocGeneratorOptions(
conventions = conventions,
filename = 'timeMarker',
directory = directory,
apiname = 'vulkan',
@ -198,30 +205,11 @@ def makeGenOpts(args):
emitExtensions = emitExtensionsPat)
]
# Extension stub source dispatcher
# This target is no longer maintained and supported.
# See README.adoc for discussion.
genOpts['vulkan_ext.c'] = [
ExtensionStubSourceOutputGenerator,
CGeneratorOptions(
filename = 'vulkan_ext.c',
directory = directory,
apiname = 'vulkan',
profile = None,
versions = featuresPat,
emitversions = None,
defaultExtensions = None,
addExtensions = '.*',
removeExtensions = removeExtensionsPat,
emitExtensions = emitExtensionsPat,
prefixText = prefixStrings + vkPrefixStrings,
alignFuncParam = 48)
]
# Extension metainformation for spec extension appendices
genOpts['extinc'] = [
ExtensionMetaDocOutputGenerator,
ExtensionMetaDocGeneratorOptions(
conventions = conventions,
filename = 'timeMarker',
directory = directory,
apiname = 'vulkan',
@ -260,7 +248,7 @@ def makeGenOpts(args):
[ 'vulkan_macos.h', [ 'VK_MVK_macos_surface' ], commonSuppressExtensions ],
[ 'vulkan_vi.h', [ 'VK_NN_vi_surface' ], commonSuppressExtensions ],
[ 'vulkan_wayland.h', [ 'VK_KHR_wayland_surface' ], commonSuppressExtensions ],
[ 'vulkan_win32.h', [ 'VK_.*_win32(|_.*)' ], commonSuppressExtensions + [ 'VK_KHR_external_semaphore', 'VK_KHR_external_memory_capabilities', 'VK_KHR_external_fence', 'VK_KHR_external_fence_capabilities', 'VK_NV_external_memory_capabilities' ] ],
[ 'vulkan_win32.h', [ 'VK_.*_win32(|_.*)', 'VK_EXT_full_screen_exclusive'], commonSuppressExtensions + [ 'VK_KHR_external_semaphore', 'VK_KHR_external_memory_capabilities', 'VK_KHR_external_fence', 'VK_KHR_external_fence_capabilities', 'VK_NV_external_memory_capabilities' ] ],
[ 'vulkan_xcb.h', [ 'VK_KHR_xcb_surface' ], commonSuppressExtensions ],
[ 'vulkan_xlib.h', [ 'VK_KHR_xlib_surface' ], commonSuppressExtensions ],
[ 'vulkan_xlib_xrandr.h', [ 'VK_EXT_acquire_xlib_display' ], commonSuppressExtensions ],
@ -276,6 +264,7 @@ def makeGenOpts(args):
emitPlatformExtensionsRE = makeREstring(platform[1])
opts = CGeneratorOptions(
conventions = conventions,
filename = headername,
directory = directory,
apiname = 'vulkan',
@ -295,7 +284,8 @@ def makeGenOpts(args):
apicall = 'VKAPI_ATTR ',
apientry = 'VKAPI_CALL ',
apientryp = 'VKAPI_PTR *',
alignFuncParam = 48)
alignFuncParam = 48,
genEnumBeginEndRange = True)
genOpts[headername] = [ COutputGenerator, opts ]
@ -312,6 +302,7 @@ def makeGenOpts(args):
genOpts['vulkan_core.h'] = [
COutputGenerator,
CGeneratorOptions(
conventions = conventions,
filename = 'vulkan_core.h',
directory = directory,
apiname = 'vulkan',
@ -331,7 +322,8 @@ def makeGenOpts(args):
apicall = 'VKAPI_ATTR ',
apientry = 'VKAPI_CALL ',
apientryp = 'VKAPI_PTR *',
alignFuncParam = 48)
alignFuncParam = 48,
genEnumBeginEndRange = True)
]
# Unused - vulkan10.h target.
@ -342,6 +334,7 @@ def makeGenOpts(args):
genOpts['vulkan10.h'] = [
COutputGenerator,
CGeneratorOptions(
conventions = conventions,
filename = 'vulkan10.h',
directory = directory,
apiname = 'vulkan',
@ -367,6 +360,7 @@ def makeGenOpts(args):
genOpts['alias.h'] = [
COutputGenerator,
CGeneratorOptions(
conventions = conventions,
filename = 'alias.h',
directory = directory,
apiname = 'vulkan',
@ -404,7 +398,7 @@ def genTarget(args):
# Create generator options with specified parameters
makeGenOpts(args)
if (args.target in genOpts.keys()):
if args.target in genOpts.keys():
createGenerator = genOpts[args.target][0]
options = genOpts[args.target][1]
@ -504,27 +498,27 @@ if __name__ == '__main__':
reg.loadElementTree(tree)
endTimer(args.time, '* Time to parse ElementTree =')
if (args.validate):
if args.validate:
reg.validateGroups()
if (args.dump):
if args.dump:
write('* Dumping registry to regdump.txt', file=sys.stderr)
reg.dumpReg(filehandle = open('regdump.txt', 'w', encoding='utf-8'))
# create error/warning & diagnostic files
if (args.errfile):
if args.errfile:
errWarn = open(args.errfile, 'w', encoding='utf-8')
else:
errWarn = sys.stderr
if (args.diagfile):
if args.diagfile:
diag = open(args.diagfile, 'w', encoding='utf-8')
else:
diag = None
if (args.debug):
if args.debug:
pdb.run('genTarget(args)')
elif (args.profile):
elif args.profile:
import cProfile, pstats
cProfile.run('genTarget(args)', 'profile.txt')
p = pstats.Stats('profile.txt')

View File

@ -14,12 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os,re,sys
from generator import *
import re
import sys
from generator import OutputGenerator, write
# HostSynchronizationOutputGenerator - subclass of OutputGenerator.
# Generates AsciiDoc includes of the externsync parameter table for the
# fundamentals chapter of the Vulkan specification. Similar to
# fundamentals chapter of the API specification. Similar to
# DocOutputGenerator.
#
# ---- methods ----
@ -43,7 +45,6 @@ class HostSynchronizationOutputGenerator(OutputGenerator):
def makeFLink(self, name):
return 'flink:' + name
#
# Generate an include file
#
# directory - subdirectory to put file in
@ -58,7 +59,7 @@ class HostSynchronizationOutputGenerator(OutputGenerator):
fp = open(filename, 'w', encoding='utf-8')
# Host Synchronization
write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
write(self.genOpts.conventions.warning_comment, file=fp)
write('.Externally Synchronized Parameters', file=fp)
write('****', file=fp)
write(self.threadsafety['parameters'], file=fp, end='')
@ -72,7 +73,7 @@ class HostSynchronizationOutputGenerator(OutputGenerator):
fp = open(filename, 'w', encoding='utf-8')
# Host Synchronization
write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
write(self.genOpts.conventions.warning_comment, file=fp)
write('.Externally Synchronized Parameter Lists', file=fp)
write('****', file=fp)
write(self.threadsafety['parameterlists'], file=fp, end='')
@ -86,7 +87,7 @@ class HostSynchronizationOutputGenerator(OutputGenerator):
fp = open(filename, 'w', encoding='utf-8')
# Host Synchronization
write('// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry', file=fp)
write(self.genOpts.conventions.warning_comment, file=fp)
write('.Implicit Externally Synchronized Parameters', file=fp)
write('****', file=fp)
write(self.threadsafety['implicit'], file=fp, end='')
@ -95,10 +96,9 @@ class HostSynchronizationOutputGenerator(OutputGenerator):
fp.close()
#
# Check if the parameter passed in is a pointer to an array
def paramIsArray(self, param):
return param.attrib.get('len') is not None
return param.get('len') is not None
# Check if the parameter passed in is a pointer
def paramIsPointer(self, param):
@ -132,9 +132,9 @@ class HostSynchronizationOutputGenerator(OutputGenerator):
# Find and add any parameters that are thread unsafe
explicitexternsyncparams = cmd.findall(paramtext + "[@externsync]")
if (explicitexternsyncparams is not None):
if explicitexternsyncparams is not None:
for param in explicitexternsyncparams:
externsyncattribs = param.attrib.get('externsync')
externsyncattribs = param.get('externsync')
paramname = param.find('name')
for externsyncattrib in externsyncattribs.split(','):
@ -163,10 +163,9 @@ class HostSynchronizationOutputGenerator(OutputGenerator):
else:
self.threadsafety['parameters'] += tempstring
# Find and add any "implicit" parameters that are thread unsafe
implicitexternsyncparams = cmd.find('implicitexternsyncparams')
if (implicitexternsyncparams is not None):
if implicitexternsyncparams is not None:
for elem in implicitexternsyncparams:
self.threadsafety['implicit'] += '* '
self.threadsafety['implicit'] += elem.text[0].upper()
@ -175,16 +174,15 @@ class HostSynchronizationOutputGenerator(OutputGenerator):
self.threadsafety['implicit'] += self.makeFLink(protoname)
self.threadsafety['implicit'] += '\n'
# For any vkCmd* functions, the command pool is externally synchronized
if protoname is not None and 'vkCmd' in protoname:
# Add a VU for any command requiring host synchronization.
# This could be further parameterized, if a future non-Vulkan API
# requires it.
if self.genOpts.conventions.is_externsync_command(protoname):
self.threadsafety['implicit'] += '* '
self.threadsafety['implicit'] += 'The sname:VkCommandPool that pname:commandBuffer was allocated from, in '
self.threadsafety['implicit'] += self.makeFLink(protoname)
self.threadsafety['implicit'] += '\n'
#
# Command generation
def genCmd(self, cmdinfo, name, alias):
OutputGenerator.genCmd(self, cmdinfo, name, alias)

View File

@ -69,7 +69,7 @@ if __name__ == '__main__':
name = elem.get('name')
supported = elem.get('supported')
if (supported == 'vulkan'):
if supported == 'vulkan':
# Relies on name being in the form VK_<vendor>_stuff
(vk, vendor) = name.split('_')[0:2]

View File

@ -14,8 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os,re,sys,io,pdb
from generator import *
import sys
from generator import OutputGenerator, enquote, noneStr, write
from pprint import pprint
# PyOutputGenerator - subclass of OutputGenerator.
@ -40,7 +40,13 @@ class PyOutputGenerator(OutputGenerator):
warnFile = sys.stderr,
diagFile = sys.stdout):
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
#
def apiName(self, name):
"""Returns True if name is in the reserved API namespace.
Delegate to the conventions object.
"""
return self.genOpts.conventions.is_api_name(name)
def beginFile(self, genOpts):
OutputGenerator.beginFile(self, genOpts)
#
@ -66,6 +72,7 @@ class PyOutputGenerator(OutputGenerator):
# (e.g. the string name of the dictionary with its contents).
self.typeCategory = {}
self.mapDict = {}
def endFile(self):
# Print out all the dictionaries as Python strings.
# Could just print(dict) but that's not human-readable
@ -81,10 +88,10 @@ class PyOutputGenerator(OutputGenerator):
[ self.typeCategory, 'typeCategory' ],
[ self.alias, 'alias' ],
]
for (dict, name) in dicts:
for (entry_dict, name) in dicts:
write(name + ' = {}', file=self.outFile)
for key in sorted(dict.keys()):
write(name + '[' + enquote(key) + '] = ', dict[key],
for key in sorted(entry_dict.keys()):
write(name + '[' + enquote(key) + '] = ', entry_dict[key],
file=self.outFile)
# Dictionary containing the relationships of a type
@ -98,25 +105,28 @@ class PyOutputGenerator(OutputGenerator):
pprint(self.mapDict[baseType], self.outFile)
OutputGenerator.endFile(self)
# Add a string entry to the dictionary, quoting it so it gets printed
# out correctly in self.endFile()
def addName(self, dict, name, value):
dict[name] = enquote(value)
# Add a mapping between types to mapDict. Only include Vulkan types,
def addName(self, entry_dict, name, value):
entry_dict[name] = enquote(value)
# Add a mapping between types to mapDict. Only include API types,
# so we don't end up with a lot of useless uint32_t and void types.
def addMapping(self, baseType, refType):
if (not apiName(baseType) or not apiName(refType)):
if not self.apiName(baseType) or not self.apiName(refType):
self.logMsg('diag', 'PyOutputGenerator::addMapping: IGNORE map from', baseType, '<->', refType)
return
else:
self.logMsg('diag', 'PyOutputGenerator::addMapping: map from', baseType, '<->', refType)
if (not baseType in self.mapDict.keys()):
self.logMsg('diag', 'PyOutputGenerator::addMapping: map from',
baseType, '<->', refType)
if baseType not in self.mapDict:
baseDict = {}
self.mapDict[baseType] = baseDict
else:
baseDict = self.mapDict[baseType]
if (not refType in self.mapDict.keys()):
if refType not in self.mapDict:
refDict = {}
self.mapDict[refType] = refDict
else:
@ -124,7 +134,7 @@ class PyOutputGenerator(OutputGenerator):
baseDict[refType] = None
refDict[baseType] = None
#
# Type generation
# For 'struct' or 'union' types, defer to genStruct() to
# add to the dictionary.
@ -142,14 +152,14 @@ class PyOutputGenerator(OutputGenerator):
def genType(self, typeinfo, name, alias):
OutputGenerator.genType(self, typeinfo, name, alias)
typeElem = typeinfo.elem
# If the type is a struct type, traverse the imbedded <member> tags
# If the type is a struct type, traverse the embedded <member> tags
# generating a structure. Otherwise, emit the tag text.
category = typeElem.get('category')
# Add a typeCategory{} entry for the category of this type.
self.addName(self.typeCategory, name, category)
if (category == 'struct' or category == 'union'):
if category in ('struct', 'union'):
self.genStruct(typeinfo, name, alias)
else:
if alias:
@ -167,38 +177,39 @@ class PyOutputGenerator(OutputGenerator):
count = len(noneStr(typeElem.text))
for elem in typeElem:
count += len(noneStr(elem.text)) + len(noneStr(elem.tail))
if (count > 0):
if (category == 'bitmask'):
if count > 0:
if category == 'bitmask':
requiredEnum = typeElem.get('requires')
self.addName(self.flags, name, requiredEnum)
# This happens when the Flags type is defined, but no
# FlagBits are defined yet.
if (requiredEnum != None):
if requiredEnum is not None:
self.addMapping(name, requiredEnum)
elif (category == 'enum'):
elif category == 'enum':
# This case does not seem to come up. It nominally would
# result from
# <type name="VkSomething" category="enum"/>,
# <type name="Something" category="enum"/>,
# but the output generator doesn't emit them directly.
self.logMsg('warn', 'PyOutputGenerator::genType: invalid \'enum\' category for name:', name)
elif (category == 'funcpointer'):
elif category == 'funcpointer':
self.funcpointers[name] = None
elif (category == 'handle'):
elif category == 'handle':
self.handles[name] = None
elif (category == 'define'):
elif category == 'define':
self.defines[name] = None
elif (category == 'basetype'):
# Don't add an entry for base types that aren't Vulkan types
# e.g. VkBool32 gets one, uint32_t does not
if (apiName(name)):
elif category == 'basetype':
# Don't add an entry for base types that are not API types
# e.g. an API Bool type gets an entry, uint32_t does not
if self.apiName(name):
self.basetypes[name] = None
self.addName(self.typeCategory, name, 'basetype')
else:
self.logMsg('diag', 'PyOutputGenerator::genType: unprocessed type:', name, 'category:', category)
else:
self.logMsg('diag', 'PyOutputGenerator::genType: unprocessed type:', name)
#
# Struct (e.g. C "struct" type) generation.
#
# Add the struct name to the 'structs' dictionary, with the
@ -216,9 +227,9 @@ class PyOutputGenerator(OutputGenerator):
members = [member.text for member in typeinfo.elem.findall('.//member/name')]
self.structs[typeName] = members
memberTypes = [member.text for member in typeinfo.elem.findall('.//member/type')]
for type in memberTypes:
self.addMapping(typeName, type)
#
for member_type in memberTypes:
self.addMapping(typeName, member_type)
# Group (e.g. C "enum" type) generation.
# These are concatenated together with other types.
#
@ -242,6 +253,7 @@ class PyOutputGenerator(OutputGenerator):
for name in enumerants:
self.addName(self.consts, name, groupName)
self.enums[groupName] = enumerants
# Enumerant generation (compile-time constants)
#
# Add the constant name to the 'consts' dictionary, with the
@ -254,7 +266,7 @@ class PyOutputGenerator(OutputGenerator):
self.addName(self.typeCategory, name, 'consts')
self.consts[name] = None
#
# Command generation
#
# Add the command name to the 'protos' dictionary, with the
@ -275,5 +287,5 @@ class PyOutputGenerator(OutputGenerator):
params = [param.text for param in cmdinfo.elem.findall('param/name')]
self.protos[name] = params
paramTypes = [param.text for param in cmdinfo.elem.findall('param/type')]
for type in paramTypes:
self.addMapping(name, type)
for param_type in paramTypes:
self.addMapping(name, param_type)

View File

@ -16,7 +16,9 @@
# Utility functions for automatic ref page generation
import io,os,re,sys
import io
import re
import sys
# global errFile, warnFile, diagFile
@ -28,13 +30,13 @@ logProcname = None
logLine = None
# Remove \' escape sequences in a string (refpage description)
def unescapeQuotes(str):
return str.replace('\\\'', '\'')
def unescapeQuotes(s):
return s.replace('\\\'', '\'')
def write(*args, **kwargs ):
file = kwargs.pop('file',sys.stdout)
end = kwargs.pop('end','\n')
file.write(' '.join([str(arg) for arg in args]))
file.write(' '.join(str(arg) for arg in args))
file.write(end)
# Metadata which may be printed (if not None) for diagnostic messages
@ -69,9 +71,10 @@ def logHeader(severity):
def setLogFile(setDiag, setWarn, filename):
global diagFile, warnFile
if filename == None:
if filename is None:
return
elif filename == '-':
if filename == '-':
fp = sys.stdout
else:
fp = open(filename, 'w', encoding='utf-8')
@ -84,15 +87,15 @@ def setLogFile(setDiag, setWarn, filename):
def logDiag(*args, **kwargs):
file = kwargs.pop('file', diagFile)
end = kwargs.pop('end','\n')
if file != None:
file.write(logHeader('DIAG') + ' '.join([str(arg) for arg in args]))
if file is not None:
file.write(logHeader('DIAG') + ' '.join(str(arg) for arg in args))
file.write(end)
def logWarn(*args, **kwargs):
file = kwargs.pop('file', warnFile)
end = kwargs.pop('end','\n')
if file != None:
file.write(logHeader('WARN') + ' '.join([str(arg) for arg in args]))
if file is not None:
file.write(logHeader('WARN') + ' '.join(str(arg) for arg in args))
file.write(end)
def logErr(*args, **kwargs):
@ -100,10 +103,10 @@ def logErr(*args, **kwargs):
end = kwargs.pop('end','\n')
strfile = io.StringIO()
strfile.write(logHeader('ERROR') + ' '.join([str(arg) for arg in args]))
strfile.write(logHeader('ERROR') + ' '.join(str(arg) for arg in args))
strfile.write(end)
if file != None:
if file is not None:
file.write(strfile.getvalue())
raise UserWarning(strfile.getvalue())
@ -116,7 +119,7 @@ def isempty(s):
#
# extractPage - True if page should be extracted
# Warning - string warning if page is suboptimal or can't be generated
# embed - False or the name of the ref page this include is imbedded within
# embed - False or the name of the ref page this include is embedded within
#
# type - 'structs', 'protos', 'funcpointers', 'flags', 'enums'
# name - struct/proto/enumerant/etc. name
@ -150,7 +153,7 @@ class pageInfo:
# line - field value or None
# file - indexed by line
def printPageInfoField(desc, line, file):
if line != None:
if line is not None:
logDiag(desc + ':', line + 1, '\t-> ', file[line], end='')
else:
logDiag(desc + ':', line)
@ -211,7 +214,7 @@ def nextPara(file, line):
# Return (creating if needed) the pageInfo entry in pageMap for name
def lookupPage(pageMap, name):
if not name in pageMap.keys():
if name not in pageMap:
pi = pageInfo()
pi.name = name
pageMap[name] = pi
@ -236,14 +239,14 @@ def loadFile(filename):
# If the line number is None, just return it.
# If minline is None, don't clamp to that value.
def clampToBlock(line, minline, maxline):
if line == None:
if line is None:
return line
elif minline and line < minline:
if minline and line < minline:
return minline
elif line > maxline:
if line > maxline:
return maxline
else:
return line
return line
# Fill in missing fields in pageInfo structures, to the extent they can be
# inferred.
@ -264,7 +267,7 @@ def fixupRefs(pageMap, specFile, file):
# # Examples include the host sync table includes in
# # chapters/fundamentals.txt and the table of Vk*Flag types in
# # appendices/boilerplate.txt.
# if pi.begin == None and pi.validity == None and pi.end == None:
# if pi.begin is None and pi.validity is None and pi.end is None:
# pi.begin = pi.include
# pi.extractPage = False
# pi.Warning = 'No begin, validity, or end lines identified'
@ -272,22 +275,21 @@ def fixupRefs(pageMap, specFile, file):
# Using open block delimiters, ref pages must *always* have a
# defined begin and end. If either is undefined, that's fatal.
if pi.begin == None:
if pi.begin is None:
pi.extractPage = False
pi.Warning = 'Can\'t identify begin of ref page open block'
continue
if pi.end == None:
if pi.end is None:
pi.extractPage = False
pi.Warning = 'Can\'t identify end of ref page open block'
continue
# If there's no description of the page, infer one from the type
if pi.desc == None:
if pi.type != None:
if pi.desc is None:
if pi.type is not None:
# pi.desc = pi.type[0:len(pi.type)-1] + ' (no short description available)'
pi.Warning = 'No short description available; could infer from the type and name'
True
else:
pi.extractPage = False
pi.Warning = 'No short description available, cannot infer from the type'
@ -297,13 +299,13 @@ def fixupRefs(pageMap, specFile, file):
# begin. funcpointer, proto, and struct pages infer the location of
# the parameter and body sections. Other pages infer the location of
# the body, but have no parameter sections.
if pi.include != None:
if pi.include is not None:
if pi.type in ['funcpointers', 'protos', 'structs']:
pi.param = nextPara(file, pi.include)
if pi.body == None:
if pi.body is None:
pi.body = nextPara(file, pi.param)
else:
if pi.body == None:
if pi.body is None:
pi.body = nextPara(file, pi.include)
else:
pi.Warning = 'Page does not have an API definition include::'
@ -329,7 +331,7 @@ def fixupRefs(pageMap, specFile, file):
for name in sorted(pageMap.keys()):
pi = pageMap[name]
if pi.end == None:
if pi.end is None:
for embedName in sorted(pageMap.keys()):
logDiag('fixupRefs: comparing', pi.name, 'to', embedName)
embed = pageMap[embedName]
@ -337,14 +339,14 @@ def fixupRefs(pageMap, specFile, file):
if not embed.extractPage:
logDiag('Skipping check for embedding in:', embed.name)
continue
if embed.begin == None or embed.end == None:
if embed.begin is None or embed.end is None:
logDiag('fixupRefs:', name + ':',
'can\'t compare to unanchored ref:', embed.name,
'in', specFile, 'at line', pi.include )
printPageInfo(pi, file)
printPageInfo(embed, file)
# If an embed is found, change the error to a warning
elif (pi.include != None and pi.include >= embed.begin and
elif (pi.include is not None and pi.include >= embed.begin and
pi.include <= embed.end):
logDiag('fixupRefs: Found embed for:', name,
'inside:', embedName,
@ -360,14 +362,22 @@ def fixupRefs(pageMap, specFile, file):
# Patterns used to recognize interesting lines in an asciidoc source file.
# These patterns are only compiled once.
includePat = re.compile('^include::(\.\./)+api/+(?P<type>\w+)/(?P<name>\w+).txt\[\]')
endifPat = re.compile('^endif::(?P<condition>[\w_+,]+)\[\]')
validPat = re.compile('^include::(\.\./)+validity/(?P<type>\w+)/(?P<name>\w+).txt\[\]')
beginPat = re.compile('^\[open,(?P<attribs>refpage=.*)\]')
INCSVAR_DEF = re.compile(r':INCS-VAR: (?P<value>.*)')
endifPat = re.compile(r'^endif::(?P<condition>[\w_+,]+)\[\]')
beginPat = re.compile(r'^\[open,(?P<attribs>refpage=.*)\]')
# attribute key/value pairs of an open block
attribStr = "([a-z]+)='([^'\\\\]*(?:\\\\.[^'\\\\]*)*)'"
attribStr = r"([a-z]+)='([^'\\]*(?:\\.[^'\\]*)*)'"
attribPat = re.compile(attribStr)
bodyPat = re.compile('^// *refBody')
bodyPat = re.compile(r'^// *refBody')
# This regex transplanted from check_spec_links
# It looks for either OpenXR or Vulkan generated file conventions, and for
# the api/validity include (generated_type), protos/struct/etc path
# (category), and API name (entity_name). It could be put into the API
# conventions object.
INCLUDE = re.compile(
r'include::(?P<directory_traverse>((../){1,4}|\{INCS-VAR\}/)(generated/)?)(?P<generated_type>[\w]+)/(?P<category>\w+)/(?P<entity_name>[^./]+).txt[\[][\]]')
# Identify reference pages in a list of strings, returning a dictionary of
# pageInfo entries for each one found, or None on failure.
@ -387,8 +397,8 @@ def findRefs(file, filename):
# 'inside' - have found the following '--' line
openBlockState = 'outside'
# This is a dictionary of interesting line numbers and strings related
# to a Vulkan API name
# Dictionary of interesting line numbers and strings related to an API
# name
pageMap = {}
numLines = len(file)
@ -396,16 +406,32 @@ def findRefs(file, filename):
# Track the pageInfo object corresponding to the current open block
pi = None
incsvar = None
while (line < numLines):
setLogLine(line)
# Look for a file-wide definition
matches = INCSVAR_DEF.match(file[line])
if matches:
incsvar = matches.group('value')
logDiag('Matched INCS-VAR definition:', incsvar)
line = line + 1
continue
# Perform INCS-VAR substitution immediately.
if incsvar and '{INCS-VAR}' in file[line]:
newLine = file[line].replace('{INCS-VAR}', incsvar)
logDiag('PERFORMING SUBSTITUTION', file[line], '->', newLine)
file[line] = newLine
# Only one of the patterns can possibly match. Add it to
# the dictionary for that name.
# [open,refpage=...] starting a refpage block
matches = beginPat.search(file[line])
if matches != None:
if matches is not None:
logDiag('Matched open block pattern')
attribs = matches.group('attribs')
@ -422,7 +448,7 @@ def findRefs(file, filename):
# Extract each attribute
name = None
desc = None
type = None
refpage_type = None
xrefs = None
for (key,value) in matches:
@ -432,25 +458,25 @@ def findRefs(file, filename):
elif key == 'desc':
desc = unescapeQuotes(value)
elif key == 'type':
type = value
refpage_type = value
elif key == 'xrefs':
xrefs = value
else:
logWarn('unknown open block attribute:', key)
if name == None or desc == None or type == None:
if name is None or desc is None or refpage_type is None:
logWarn('missing one or more required open block attributes:'
'refpage, desc, or type')
# Leave pi == None so open block delimiters are ignored
# Leave pi is None so open block delimiters are ignored
else:
pi = lookupPage(pageMap, name)
pi.desc = desc
# Must match later type definitions in interface/validity includes
pi.type = type
pi.type = refpage_type
if xrefs:
pi.refs = xrefs
logDiag('open block for', name, 'added DESC =', desc,
'TYPE =', type, 'XREFS =', xrefs)
'TYPE =', refpage_type, 'XREFS =', xrefs)
line = line + 1
continue
@ -464,14 +490,14 @@ def findRefs(file, filename):
# -- delimiter following [open,refpage=...]
openBlockState = 'inside'
if pi == None:
if pi is None:
logWarn('no pageInfo available for opening -- delimiter')
else:
pi.begin = line + 1
logDiag('opening -- delimiter: added BEGIN =', pi.begin)
elif openBlockState == 'inside':
# -- delimiter ending an open block
if pi == None:
if pi is None:
logWarn('no pageInfo available for closing -- delimiter')
else:
pi.end = line - 1
@ -485,44 +511,46 @@ def findRefs(file, filename):
line = line + 1
continue
matches = validPat.search(file[line])
if matches != None:
logDiag('Matched validity pattern')
type = matches.group('type')
name = matches.group('name')
matches = INCLUDE.search(file[line])
if matches is not None:
# Something got included, not sure what yet.
gen_type = matches.group('generated_type')
refpage_type = matches.group('category')
name = matches.group('entity_name')
if pi != None:
if pi.type and type != pi.type:
logWarn('ERROR: pageMap[' + name + '] type:',
pi.type, 'does not match type:', type)
pi.type = type
pi.validity = line
logDiag('added TYPE =', pi.type, 'VALIDITY =', pi.validity)
else:
logWarn('validity include:: line NOT inside block')
if gen_type == 'validity':
logDiag('Matched validity pattern')
if pi is not None:
if pi.type and refpage_type != pi.type:
logWarn('ERROR: pageMap[' + name + '] type:',
pi.type, 'does not match type:', refpage_type)
pi.type = refpage_type
pi.validity = line
logDiag('added TYPE =', pi.type, 'VALIDITY =', pi.validity)
else:
logWarn('validity include:: line NOT inside block')
line = line + 1
continue
line = line + 1
continue
matches = includePat.search(file[line])
if matches != None:
logDiag('Matched include pattern')
type = matches.group('type')
name = matches.group('name')
if pi != None:
if pi.include != None:
logDiag('found multiple includes for this block')
if pi.type and type != pi.type:
logWarn('ERROR: pageMap[' + name + '] type:',
pi.type, 'does not match type:', type)
pi.type = type
pi.include = line
logDiag('added TYPE =', pi.type, 'INCLUDE =', pi.include)
else:
logWarn('interface include:: line NOT inside block')
if gen_type == 'api':
logDiag('Matched include pattern')
if pi is not None:
if pi.include is not None:
logDiag('found multiple includes for this block')
if pi.type and refpage_type != pi.type:
logWarn('ERROR: pageMap[' + name + '] type:',
pi.type, 'does not match type:', refpage_type)
pi.type = refpage_type
pi.include = line
logDiag('added TYPE =', pi.type, 'INCLUDE =', pi.include)
else:
logWarn('interface include:: line NOT inside block')
line = line + 1
continue
line = line + 1
continue
logDiag('ignoring unrecognized include line ', matches.group())
# Vulkan 1.1 markup allows the last API include construct to be
# followed by an asciidoctor endif:: construct (and also preceded,
@ -530,7 +558,7 @@ def findRefs(file, filename):
# This looks for endif:: immediately following an include:: line
# and, if found, moves the include boundary to this line.
matches = endifPat.search(file[line])
if matches != None and pi != None:
if matches is not None and pi is not None:
if pi.include == line - 1:
logDiag('Matched endif pattern following include; moving include')
pi.include = line
@ -541,9 +569,9 @@ def findRefs(file, filename):
continue
matches = bodyPat.search(file[line])
if matches != None:
if matches is not None:
logDiag('Matched // refBody pattern')
if pi != None:
if pi is not None:
pi.body = line
logDiag('added BODY =', pi.body)
else:
@ -555,7 +583,7 @@ def findRefs(file, filename):
line = line + 1
continue
if pi != None:
if pi is not None:
logErr('Unclosed open block at EOF!')
setLogSourcefile(None)
@ -563,4 +591,3 @@ def findRefs(file, filename):
setLogLine(None)
return pageMap

View File

@ -36,10 +36,19 @@
# files are asciidoc source files from the Vulkan spec to reflow.
# For error and file-loading interfaces only
from reflib import *
import argparse
import os
import re
import sys
from reflib import loadFile, logDiag, logWarn, setLogFile
from reflow_count import startVUID
import argparse, copy, os, pdb, re, string, sys
# Vulkan-specific - will consolidate into scripts/ like OpenXR soon
sys.path.insert(0, 'xml')
import vkapi as api
from vkconventions import VulkanConventions as APIConventions
conventions = APIConventions()
# Markup that always ends a paragraph
# empty line or whitespace
@ -51,25 +60,28 @@ import argparse, copy, os, pdb, re, string, sys
# macro-directive::terms
# + standalone list item continuation
# label:: labelled list - label must be standalone
endPara = re.compile('^( *|\[.*\]|//.*|<<<<|:.*|[a-z]+::.*|\+|.*::)$')
endPara = re.compile(r'^( *|\[.*\]|//.*|<<<<|:.*|[a-z]+::.*|\+|.*::)$')
# Special case of markup ending a paragraph, used to track the current command/structure
includePat = re.compile('^include::(\.\./)+api/+(?P<type>\w+)/(?P<name>\w+).txt\[\]')
# Special case of markup ending a paragraph, used to track the current
# command/structure. This allows for either OpenXR or Vulkan API path
# conventions, and uses the file suffix defined by the API conventions.
includePat = re.compile(r'^include::(\.\./)+(generated/+)?api/+(?P<type>\w+)/(?P<name>\w+)'
+ conventions.file_suffix + r'\[\]')
# Find the first pname: pattern in a Valid Usage statement
pnamePat = re.compile('pname:(?P<param>\w+)')
pnamePat = re.compile(r'pname:(?P<param>\w+)')
# Markup that's OK in a contiguous paragraph but otherwise passed through
# .anything
# === Section Titles
endParaContinue = re.compile('^(\..*|=+ .*)$')
endParaContinue = re.compile(r'^(\..*|=+ .*)$')
# Markup for block delimiters whose contents *should* be reformatted
# -- (exactly two) (open block)
# **** (4 or more) (sidebar block - why do we have these?!)
# ==== (4 or more) (example block)
# ____ (4 or more) (quote block)
blockReflow = re.compile('^(--|[*=_]{4,})$')
blockReflow = re.compile(r'^(--|[*=_]{4,})$')
# Markup for block delimiters whose contents should *not* be reformatted
# |=== (3 or more) (table)
@ -78,7 +90,7 @@ blockReflow = re.compile('^(--|[*=_]{4,})$')
# //// (4 or more) (comment block)
# ---- (4 or more) (listing block)
# **** (4 or more) (sidebar block)
blockPassthrough = re.compile('^(\|={3,}|[-+./]{4,})$')
blockPassthrough = re.compile(r'^(\|={3,}|[-+./]{4,})$')
# Markup for introducing bullet points (hanging paragraphs)
# * bullet
@ -86,14 +98,14 @@ blockPassthrough = re.compile('^(\|={3,}|[-+./]{4,})$')
# -- bullet
# . bullet
# :: bullet
beginBullet = re.compile('^ *([*-.]+|::) ')
beginBullet = re.compile(r'^ *([*-.]+|::) ')
# Text that (may) not end sentences
# A single letter followed by a period, typically a middle initial.
endInitial = re.compile('^[A-Z]\.$')
endInitial = re.compile(r'^[A-Z]\.$')
# An abbreviation, which doesn't (usually) end a line.
endAbbrev = re.compile('(e\.g|i\.e|c\.f)\.$', re.IGNORECASE)
endAbbrev = re.compile(r'(e\.g|i\.e|c\.f)\.$', re.IGNORECASE)
# State machine for reflowing.
#
@ -172,10 +184,10 @@ class ReflowState:
def endSentence(self, word):
if (word[-1:] != '.' or
endAbbrev.search(word) or
(self.breakInitial and endInitial.match(word))):
(self.breakInitial and endInitial.match(word))):
return False
else:
return True
return True
# Returns True if word is a Valid Usage ID Tag anchor.
def vuidAnchor(self, word):
@ -183,7 +195,7 @@ class ReflowState:
# Reflow the current paragraph, respecting the paragraph lead and
# hanging indentation levels. The algorithm also respects trailing '+'
# signs that indicate imbedded newlines, and will not reflow a very long
# signs that indicate embedded newlines, and will not reflow a very long
# word immediately after a bullet point.
# Just return the paragraph unchanged if the -noflow argument was
# given.
@ -216,12 +228,12 @@ class ReflowState:
wordCount += 1
endEscape = False
if (i == numWords and word == '+'):
if i == numWords and word == '+':
# Trailing ' +' must stay on the same line
endEscape = word
# logDiag('reflowPara last word of line =', word, 'prevWord =', prevWord, 'endEscape =', endEscape)
else:
True
pass
# logDiag('reflowPara wordCount =', wordCount, 'word =', word, 'prevWord =', prevWord)
if wordCount == 1:
@ -267,7 +279,7 @@ class ReflowState:
# Are we on the first word following a bullet point?
firstBullet = (wordCount == 2 and bulletPoint)
if (endEscape):
if endEscape:
# If the new word ends the input line with ' +',
# add it to the current line.
@ -327,7 +339,7 @@ class ReflowState:
prevWord = word
# Add this line to the output paragraph.
if (outLine):
if outLine:
outPara.append(outLine + '\n')
return outPara
@ -335,10 +347,8 @@ class ReflowState:
# Emit a paragraph, possibly reflowing it depending on the block
# context. Reset the paragraph accumulator.
def emitPara(self):
global vuPat, nestedVuPat
if self.para != []:
if self.vuStack[-1] and self.nextvu != None:
if self.vuStack[-1] and self.nextvu is not None:
# If:
# - this paragraph is in a Valid Usage block,
# - VUID tags are being assigned,
@ -357,7 +367,7 @@ class ReflowState:
# Split the first line after the bullet point
matches = vuPat.search(self.para[0])
if matches != None:
if matches is not None:
logDiag('findRefs: Matched vuPat on line:', self.para[0], end='')
head = matches.group('head')
tail = matches.group('tail')
@ -367,10 +377,10 @@ class ReflowState:
# be correct, but should be highly reliable.
for vuLine in self.para:
matches = pnamePat.search(vuLine)
if matches != None:
if matches is not None:
break
if matches != None:
if matches is not None:
paramName = matches.group('param')
else:
paramName = 'None'
@ -495,7 +505,7 @@ def reflowFile(filename, args):
logDiag('reflow: filename', filename)
lines = loadFile(filename)
if (lines == None):
if lines is None:
return
# Output file handle and reflow object for this file. There are no race
@ -511,7 +521,7 @@ def reflowFile(filename, args):
fp = open(outFilename, 'w', encoding='utf8')
except:
logWarn('Cannot open output file', filename, ':', sys.exc_info()[0])
return None
return
state = ReflowState(filename,
file = fp,
@ -538,9 +548,9 @@ def reflowFile(filename, args):
# structure or command, track that for use in VUID generation.
matches = includePat.search(line)
if matches != None:
type = matches.group('type')
if (type == 'protos' or type == 'structs'):
if matches is not None:
include_type = matches.group('type')
if include_type in ('protos', 'structs'):
state.apiName = matches.group('name')
elif endParaContinue.match(line):
@ -592,20 +602,20 @@ def reflowFile(filename, args):
fp.close()
# Update the 'nextvu' value
if (args.nextvu != state.nextvu):
if args.nextvu != state.nextvu:
logWarn('Updated nextvu to', state.nextvu, 'after file', filename)
args.nextvu = state.nextvu
def reflowAllAdocFiles(folder_to_reflow, args):
for root, subdirs, files in os.walk(folder_to_reflow):
for file in files:
if file.endswith(".txt"):
if file.endswith(conventions.file_suffix):
file_path = os.path.join(root, file)
reflowFile(file_path, args)
for subdir in subdirs:
sub_folder = os.path.join(root, subdir)
print('Sub-folder = %s' % sub_folder)
if not (subdir.lower() == "scripts") and not (subdir.lower() == "style"):
if subdir.lower() not in conventions.spec_no_reflow_dirs:
print(' Parsing = %s' % sub_folder)
reflowAllAdocFiles(sub_folder, args)
else:
@ -617,11 +627,11 @@ def reflowAllAdocFiles(folder_to_reflow, args):
# Explicit Valid Usage list item with one or more leading asterisks
# The re.DOTALL is needed to prevent vuPat.search() from stripping
# the trailing newline.
global vuPat
vuPat = re.compile('^(?P<head> [*]+)( *)(?P<tail>.*)', re.DOTALL)
vuPat = re.compile(r'^(?P<head> [*]+)( *)(?P<tail>.*)', re.DOTALL)
# Pattern matching leading nested bullet points
global nestedVuPat
nestedVuPat = re.compile('^ \*\*')
nestedVuPat = re.compile(r'^ \*\*')
if __name__ == '__main__':
parser = argparse.ArgumentParser()
@ -660,22 +670,22 @@ if __name__ == '__main__':
if args.overwrite:
logWarn('reflow.py: will overwrite all input files')
if args.tagvu and args.nextvu == None:
if args.tagvu and args.nextvu is None:
args.nextvu = startVUID
if args.nextvu != None:
if args.nextvu is not None:
logWarn('Tagging untagged Valid Usage statements starting at', args.nextvu)
# If no files are specified, reflow the entire specification chapters folder
if len(args.files) == 0:
if not args.files:
folder_to_reflow = os.getcwd()
# folder_to_reflow += '/chapters'
folder_to_reflow += '/' + conventions.spec_reflow_path
reflowAllAdocFiles(folder_to_reflow, args)
else:
for file in args.files:
reflowFile(file, args)
if args.nextvu != None and args.nextvu != startVUID:
if args.nextvu is not None and args.nextvu != startVUID:
try:
reflow_count_file_path = os.path.dirname(os.path.realpath(__file__))
reflow_count_file_path += '/reflow_count.py'

View File

@ -1,2 +1,2 @@
# The value to start tagging VU statements at, unless overridden by -nextvu
startVUID = 2665
startVUID = 2680

View File

@ -14,9 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import io,os,pdb,re,string,sys,copy
import copy
import re
import sys
import xml.etree.ElementTree as etree
from collections import defaultdict
from collections import defaultdict, namedtuple
from generator import OutputGenerator, write
# matchAPIProfile - returns whether an API and profile
# being generated matches an element's profile
@ -48,20 +51,21 @@ from collections import defaultdict
# like "gl(core)|gles1(common-lite)".
def matchAPIProfile(api, profile, elem):
"""Match a requested API & profile name to a api & profile attributes of an Element"""
match = True
# Match 'api', if present
if ('api' in elem.attrib):
if (api == None):
elem_api = elem.get('api')
if elem_api:
if api is None:
raise UserWarning("No API requested, but 'api' attribute is present with value '" +
elem.get('api') + "'")
elif (api != elem.get('api')):
elem_api + "'")
elif api != elem_api:
# Requested API doesn't match attribute
return False
if ('profile' in elem.attrib):
if (profile == None):
elem_profile = elem.get('profile')
if elem_profile:
if profile is None:
raise UserWarning("No profile requested, but 'profile' attribute is present with value '" +
elem.get('profile') + "'")
elif (profile != elem.get('profile')):
elem_profile + "'")
elif profile != elem_profile:
# Requested profile doesn't match attribute
return False
return True
@ -134,7 +138,7 @@ class EnumInfo(BaseInfo):
def __init__(self, elem):
BaseInfo.__init__(self, elem)
self.type = elem.get('type')
if (self.type == None):
if self.type is None:
self.type = ''
# CmdInfo - registry information about a command
@ -168,7 +172,7 @@ class FeatureInfo(BaseInfo):
self.name = elem.get('name')
# Determine element category (vendor). Only works
# for <extension> elements.
if (elem.tag == 'feature'):
if elem.tag == 'feature':
self.category = 'VERSION'
self.version = elem.get('name')
self.versionNumber = elem.get('number')
@ -182,8 +186,6 @@ class FeatureInfo(BaseInfo):
self.supported = elem.get('supported')
self.emit = False
from generator import write, GeneratorOptions, OutputGenerator
# Registry - object representing an API registry, loaded from an XML file
# Members
# tree - ElementTree containing the root <registry>
@ -229,7 +231,15 @@ class Registry:
self.apidict = {}
self.extensions = []
self.requiredextensions = [] # Hack - can remove it after validity generator goes away
# ** Global types for automatic source generation **
# Length Member data
self.commandextensiontuple = namedtuple('commandextensiontuple',
['command', # The name of the command being modified
'value', # The value to append to the command
'extension']) # The name of the extension that added it
self.validextensionstructs = defaultdict(list)
self.commandextensionsuccesses = []
self.commandextensionerrors = []
self.extdict = {}
# A default output generator, so commands prior to apiGen can report
# errors via the generator object.
@ -238,14 +248,17 @@ class Registry:
self.emitFeatures = False
self.breakPat = None
# self.breakPat = re.compile('VkFenceImportFlagBits.*')
def loadElementTree(self, tree):
"""Load ElementTree into a Registry object and parse it"""
self.tree = tree
self.parseTree()
def loadFile(self, file):
"""Load an API registry XML file into a Registry object and parse it"""
self.tree = etree.parse(file)
self.parseTree()
def setGenerator(self, gen):
"""Specify output generator object. None restores the default generator"""
self.gen = gen
@ -263,9 +276,9 @@ class Registry:
def addElementInfo(self, elem, info, infoName, dictionary):
# self.gen.logMsg('diag', 'Adding ElementInfo.required =',
# info.required, 'name =', elem.get('name'))
if ('api' in elem.attrib):
key = (elem.get('name'),elem.get('api'))
api = elem.get('api')
if api:
key = (elem.get('name'), api)
else:
key = elem.get('name')
if key in dictionary:
@ -277,28 +290,30 @@ class Registry:
# 'with identical value')
else:
dictionary[key] = info
#
# lookupElementInfo - find a {Type|Enum|Cmd}Info object by name.
# If an object qualified by API name exists, use that.
# fname - name of type / enum / command
# dictionary - self.{type|enum|cmd}dict
def lookupElementInfo(self, fname, dictionary):
key = (fname, self.genOpts.apiname)
if (key in dictionary):
if key in dictionary:
# self.gen.logMsg('diag', 'Found API-specific element for feature', fname)
return dictionary[key]
elif (fname in dictionary):
if fname in dictionary:
# self.gen.logMsg('diag', 'Found generic element for feature', fname)
return dictionary[fname]
else:
return None
return None
def breakOnName(self, regexp):
self.breakPat = re.compile(regexp)
def parseTree(self):
"""Parse the registry Element, once created"""
# This must be the Element for the root <registry>
self.reg = self.tree.getroot()
#
# Create dictionary of registry types from toplevel <types> tags
# and add 'name' attribute to each <type> tag (where missing)
# based on its <name> element.
@ -306,13 +321,13 @@ class Registry:
# There's usually one <types> block; more are OK
# Required <type> attributes: 'name' or nested <name> tag contents
self.typedict = {}
for type in self.reg.findall('types/type'):
for type_elem in self.reg.findall('types/type'):
# If the <type> doesn't already have a 'name' attribute, set
# it from contents of its <name> tag.
if (type.get('name') == None):
type.attrib['name'] = type.find('name').text
self.addElementInfo(type, TypeInfo(type), 'type', self.typedict)
#
if type_elem.get('name') is None:
type_elem.set('name', type_elem.find('name').text)
self.addElementInfo(type_elem, TypeInfo(type_elem), 'type', self.typedict)
# Create dictionary of registry enum groups from <enums> tags.
#
# Required <enums> attributes: 'name'. If no name is given, one is
@ -321,7 +336,7 @@ class Registry:
self.groupdict = {}
for group in self.reg.findall('enums'):
self.addElementInfo(group, GroupInfo(group), 'group', self.groupdict)
#
# Create dictionary of registry enums from <enum> tags
#
# <enums> tags usually define different namespaces for the values
@ -333,14 +348,12 @@ class Registry:
# a better scheme for tagging core and extension enums is created.
self.enumdict = {}
for enums in self.reg.findall('enums'):
required = (enums.get('type') != None)
required = (enums.get('type') is not None)
for enum in enums.findall('enum'):
enumInfo = EnumInfo(enum)
enumInfo.required = required
self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
# self.gen.logMsg('diag', 'parseTree: marked req =',
# required, 'for', enum.get('name'))
#
# Create dictionary of registry commands from <command> tags
# and add 'name' attribute to each <command> tag (where missing)
# based on its <proto><name> element.
@ -356,13 +369,14 @@ class Registry:
# If the <command> doesn't already have a 'name' attribute, set
# it from contents of its <proto><name> tag.
name = cmd.get('name')
if name == None:
name = cmd.attrib['name'] = cmd.find('proto/name').text
if name is None:
name = cmd.set('name', cmd.find('proto/name').text)
ci = CmdInfo(cmd)
self.addElementInfo(cmd, ci, 'command', self.cmddict)
alias = cmd.get('alias')
if alias:
cmdAlias.append([name, alias, cmd])
# Now loop over aliases, injecting a copy of the aliased command's
# Element with the aliased prototype name replaced with the command
# name - if it exists.
@ -372,8 +386,8 @@ class Registry:
aliasInfo = self.cmddict[alias]
cmdElem = copy.deepcopy(aliasInfo.elem)
cmdElem.find('proto/name').text = name
cmdElem.attrib['name'] = name
cmdElem.attrib['alias'] = alias
cmdElem.set('name', name)
cmdElem.set('alias', alias)
ci = CmdInfo(cmdElem)
# Replace the dictionary entry for the CmdInfo element
self.cmddict[name] = ci
@ -384,10 +398,8 @@ class Registry:
self.gen.logMsg('warn', 'No matching <command> found for command',
cmd.get('name'), 'alias', alias)
#
# Create dictionaries of API and extension interfaces
# from toplevel <api> and <extension> tags.
#
self.apidict = {}
for feature in self.reg.findall('feature'):
featureInfo = FeatureInfo(feature)
@ -418,36 +430,35 @@ class Registry:
# add an EnumInfo record to the dictionary. That works because
# output generation of constants is purely dependency-based, and
# doesn't need to iterate through the XML tags.
#
for elem in feature.findall('require'):
for enum in elem.findall('enum'):
addEnumInfo = False
groupName = enum.get('extends')
if (groupName != None):
# self.gen.logMsg('diag', 'Found extension enum',
# enum.get('name'))
# Add version number attribute to the <enum> element
enum.attrib['version'] = featureInfo.version
# Look up the GroupInfo with matching groupName
if (groupName in self.groupdict.keys()):
# self.gen.logMsg('diag', 'Matching group',
# groupName, 'found, adding element...')
gi = self.groupdict[groupName]
gi.elem.append(enum)
# Remove element from parent <require> tag
# This should be a no-op in lxml.etree
elem.remove(enum)
else:
self.gen.logMsg('warn', 'NO matching group',
groupName, 'for enum', enum.get('name'), 'found.')
addEnumInfo = True
elif (enum.get('value') or enum.get('bitpos') or enum.get('alias')):
# self.gen.logMsg('diag', 'Adding extension constant "enum"',
# enum.get('name'))
addEnumInfo = True
if (addEnumInfo):
enumInfo = EnumInfo(enum)
self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
for enum in elem.findall('enum'):
addEnumInfo = False
groupName = enum.get('extends')
if groupName is not None:
# self.gen.logMsg('diag', 'Found extension enum',
# enum.get('name'))
# Add version number attribute to the <enum> element
enum.set('version', featureInfo.version)
# Look up the GroupInfo with matching groupName
if groupName in self.groupdict:
# self.gen.logMsg('diag', 'Matching group',
# groupName, 'found, adding element...')
gi = self.groupdict[groupName]
gi.elem.append(enum)
# Remove element from parent <require> tag
# This should be a no-op in lxml.etree
elem.remove(enum)
else:
self.gen.logMsg('warn', 'NO matching group',
groupName, 'for enum', enum.get('name'), 'found.')
addEnumInfo = True
elif enum.get('value') or enum.get('bitpos') or enum.get('alias'):
# self.gen.logMsg('diag', 'Adding extension constant "enum"',
# enum.get('name'))
addEnumInfo = True
if addEnumInfo:
enumInfo = EnumInfo(enum)
self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
self.extensions = self.reg.findall('extensions/extension')
self.extdict = {}
@ -461,58 +472,57 @@ class Registry:
#
# This code also adds a 'extnumber' attribute containing the
# extension number, used for enumerant value calculation.
#
for elem in feature.findall('require'):
for enum in elem.findall('enum'):
addEnumInfo = False
groupName = enum.get('extends')
if (groupName != None):
# self.gen.logMsg('diag', 'Found extension enum',
# enum.get('name'))
for enum in elem.findall('enum'):
addEnumInfo = False
groupName = enum.get('extends')
if groupName is not None:
# self.gen.logMsg('diag', 'Found extension enum',
# enum.get('name'))
# Add <extension> block's extension number attribute to
# the <enum> element unless specified explicitly, such
# as when redefining an enum in another extension.
extnumber = enum.get('extnumber')
if not extnumber:
enum.attrib['extnumber'] = featureInfo.number
# Add <extension> block's extension number attribute to
# the <enum> element unless specified explicitly, such
# as when redefining an enum in another extension.
extnumber = enum.get('extnumber')
if not extnumber:
enum.set('extnumber', featureInfo.number)
enum.attrib['extname'] = featureInfo.name
enum.attrib['supported'] = featureInfo.supported
# Look up the GroupInfo with matching groupName
if (groupName in self.groupdict.keys()):
# self.gen.logMsg('diag', 'Matching group',
# groupName, 'found, adding element...')
gi = self.groupdict[groupName]
gi.elem.append(enum)
# Remove element from parent <require> tag
# This should be a no-op in lxml.etree
elem.remove(enum)
else:
self.gen.logMsg('warn', 'NO matching group',
groupName, 'for enum', enum.get('name'), 'found.')
addEnumInfo = True
elif (enum.get('value') or enum.get('bitpos') or enum.get('alias')):
# self.gen.logMsg('diag', 'Adding extension constant "enum"',
# enum.get('name'))
addEnumInfo = True
if (addEnumInfo):
enumInfo = EnumInfo(enum)
self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
enum.set('extname', featureInfo.name)
enum.set('supported', featureInfo.supported)
# Look up the GroupInfo with matching groupName
if groupName in self.groupdict:
# self.gen.logMsg('diag', 'Matching group',
# groupName, 'found, adding element...')
gi = self.groupdict[groupName]
gi.elem.append(enum)
# Remove element from parent <require> tag
# This should be a no-op in lxml.etree
elem.remove(enum)
else:
self.gen.logMsg('warn', 'NO matching group',
groupName, 'for enum', enum.get('name'), 'found.')
addEnumInfo = True
elif enum.get('value') or enum.get('bitpos') or enum.get('alias'):
# self.gen.logMsg('diag', 'Adding extension constant "enum"',
# enum.get('name'))
addEnumInfo = True
if addEnumInfo:
enumInfo = EnumInfo(enum)
self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
# Construct a "validextensionstructs" list for parent structures
# based on "structextends" tags in child structures
disabled_types = []
for disabled_ext in self.reg.findall('extensions/extension[@supported="disabled"]'):
for type in disabled_ext.findall("*/type"):
disabled_types.append(type.get('name'))
for type in self.reg.findall('types/type'):
if type.get('name') not in disabled_types:
parentStructs = type.get('structextends')
if (parentStructs != None):
for type_elem in disabled_ext.findall("*/type"):
disabled_types.append(type_elem.get('name'))
for type_elem in self.reg.findall('types/type'):
if type_elem.get('name') not in disabled_types:
parentStructs = type_elem.get('structextends')
if parentStructs is not None:
for parent in parentStructs.split(','):
# self.gen.logMsg('diag', type.get('name'), 'extends', parent)
self.validextensionstructs[parent].append(type.get('name'))
self.validextensionstructs[parent].append(type_elem.get('name'))
# Sort the lists so they don't depend on the XML order
for parent in self.validextensionstructs:
self.validextensionstructs[parent].sort()
@ -550,26 +560,26 @@ class Registry:
# write(' ** Dumping XML ElementTree **', file=filehandle)
# write('***************************************', file=filehandle)
# write(etree.tostring(self.tree.getroot(),pretty_print=True), file=filehandle)
#
# typename - name of type
# required - boolean (to tag features as required or not)
def markTypeRequired(self, typename, required):
"""Require (along with its dependencies) or remove (but not its dependencies) a type"""
self.gen.logMsg('diag', 'tagging type:', typename, '-> required =', required)
# Get TypeInfo object for <type> tag corresponding to typename
type = self.lookupElementInfo(typename, self.typedict)
if (type != None):
if (required):
typeinfo = self.lookupElementInfo(typename, self.typedict)
if typeinfo is not None:
if required:
# Tag type dependencies in 'alias' and 'required' attributes as
# required. This DOES NOT un-tag dependencies in a <remove>
# tag. See comments in markRequired() below for the reason.
for attrib in [ 'requires', 'alias' ]:
depname = type.elem.get(attrib)
for attrib_name in [ 'requires', 'alias' ]:
depname = typeinfo.elem.get(attrib_name)
if depname:
self.gen.logMsg('diag', 'Generating dependent type',
depname, 'for', attrib, 'type', typename)
depname, 'for', attrib_name, 'type', typename)
# Don't recurse on self-referential structures.
if (typename != depname):
if typename != depname:
self.markTypeRequired(depname, required)
else:
self.gen.logMsg('diag', 'type', typename, 'is self-referential')
@ -577,27 +587,39 @@ class Registry:
# <type> tags)
# Look for <type> in entire <command> tree,
# not just immediate children
for subtype in type.elem.findall('.//type'):
for subtype in typeinfo.elem.findall('.//type'):
self.gen.logMsg('diag', 'markRequired: type requires dependent <type>', subtype.text)
if (typename != subtype.text):
if typename != subtype.text:
self.markTypeRequired(subtype.text, required)
else:
self.gen.logMsg('diag', 'type', typename, 'is self-referential')
# Tag enums used in defining this type, for example in
# <member><name>member</name>[<enum>MEMBER_SIZE</enum>]</member>
for subenum in type.elem.findall('.//enum'):
for subenum in typeinfo.elem.findall('.//enum'):
self.gen.logMsg('diag', 'markRequired: type requires dependent <enum>', subenum.text)
self.markEnumRequired(subenum.text, required)
type.required = required
else:
# Tag type dependency in 'bitvalues' attributes as
# required. This ensures that the bit values for a flag
# are emitted
depType = typeinfo.elem.get('bitvalues')
if depType:
self.gen.logMsg('diag', 'Generating bitflag type',
depType, 'for type', typename)
self.markTypeRequired(depType, required)
group = self.lookupElementInfo(depType, self.groupdict)
if group is not None:
group.flagType = typeinfo
typeinfo.required = required
elif '.h' not in typename:
self.gen.logMsg('warn', 'type:', typename , 'IS NOT DEFINED')
#
# enumname - name of enum
# required - boolean (to tag features as required or not)
def markEnumRequired(self, enumname, required):
self.gen.logMsg('diag', 'tagging enum:', enumname, '-> required =', required)
enum = self.lookupElementInfo(enumname, self.enumdict)
if (enum != None):
if enum is not None:
enum.required = required
# Tag enum dependencies in 'alias' attribute as required
depname = enum.elem.get('alias')
@ -607,13 +629,13 @@ class Registry:
self.markEnumRequired(depname, required)
else:
self.gen.logMsg('warn', 'enum:', enumname , 'IS NOT DEFINED')
#
# cmdname - name of command
# required - boolean (to tag features as required or not)
def markCmdRequired(self, cmdname, required):
self.gen.logMsg('diag', 'tagging command:', cmdname, '-> required =', required)
cmd = self.lookupElementInfo(cmdname, self.cmddict)
if (cmd != None):
if cmd is not None:
cmd.required = required
# Tag command dependencies in 'alias' attribute as required
depname = cmd.elem.get('alias')
@ -626,67 +648,88 @@ class Registry:
# tag, because many other commands may use the same type.
# We could be more clever and reference count types,
# instead of using a boolean.
if (required):
if required:
# Look for <type> in entire <command> tree,
# not just immediate children
for type in cmd.elem.findall('.//type'):
self.gen.logMsg('diag', 'markRequired: command implicitly requires dependent type', type.text)
self.markTypeRequired(type.text, required)
for type_elem in cmd.elem.findall('.//type'):
self.gen.logMsg('diag', 'markRequired: command implicitly requires dependent type', type_elem.text)
self.markTypeRequired(type_elem.text, required)
else:
self.gen.logMsg('warn', 'command:', name, 'IS NOT DEFINED')
#
# features - Element for <require> or <remove> tag
# featurename - name of the feature
# feature - Element for <require> or <remove> tag
# required - boolean (to tag features as required or not)
def markRequired(self, features, required):
def markRequired(self, featurename, feature, required):
"""Require or remove features specified in the Element"""
self.gen.logMsg('diag', 'markRequired (features = <too long to print>, required =', required, ')')
self.gen.logMsg('diag', 'markRequired (feature = <too long to print>, required =', required, ')')
# Loop over types, enums, and commands in the tag
# @@ It would be possible to respect 'api' and 'profile' attributes
# in individual features, but that's not done yet.
for typeElem in features.findall('type'):
for typeElem in feature.findall('type'):
self.markTypeRequired(typeElem.get('name'), required)
for enumElem in features.findall('enum'):
for enumElem in feature.findall('enum'):
self.markEnumRequired(enumElem.get('name'), required)
for cmdElem in features.findall('command'):
for cmdElem in feature.findall('command'):
self.markCmdRequired(cmdElem.get('name'), required)
#
# Extensions may need to extend existing commands or other items in the future.
# So, look for extend tags.
for extendElem in feature.findall('extend'):
extendType = extendElem.get('type')
if extendType == 'command':
commandName = extendElem.get('name')
successExtends = extendElem.get('successcodes')
if successExtends is not None:
for success in successExtends.split(','):
self.commandextensionsuccesses.append(self.commandextensiontuple(command=commandName,
value=success,
extension=featurename))
errorExtends = extendElem.get('errorcodes')
if errorExtends is not None:
for error in errorExtends.split(','):
self.commandextensionerrors.append(self.commandextensiontuple(command=commandName,
value=error,
extension=featurename))
else:
self.gen.logMsg('warn', 'extend type:', extendType, 'IS NOT SUPPORTED')
# interface - Element for <version> or <extension>, containing
# <require> and <remove> tags
# featurename - name of the feature
# api - string specifying API name being generated
# profile - string specifying API profile being generated
def requireAndRemoveFeatures(self, interface, api, profile):
"""Process <recquire> and <remove> tags for a <version> or <extension>"""
def requireAndRemoveFeatures(self, interface, featurename, api, profile):
"""Process <require> and <remove> tags for a <version> or <extension>"""
# <require> marks things that are required by this version/profile
for feature in interface.findall('require'):
if (matchAPIProfile(api, profile, feature)):
self.markRequired(feature,True)
if matchAPIProfile(api, profile, feature):
self.markRequired(featurename, feature, True)
# <remove> marks things that are removed by this version/profile
for feature in interface.findall('remove'):
if (matchAPIProfile(api, profile, feature)):
self.markRequired(feature,False)
if matchAPIProfile(api, profile, feature):
self.markRequired(featurename, feature, False)
def assignAdditionalValidity(self, interface, api, profile):
#
# Loop over all usage inside all <require> tags.
for feature in interface.findall('require'):
if (matchAPIProfile(api, profile, feature)):
if matchAPIProfile(api, profile, feature):
for v in feature.findall('usage'):
if v.get('command'):
self.cmddict[v.get('command')].additionalValidity.append(copy.deepcopy(v))
if v.get('struct'):
self.typedict[v.get('struct')].additionalValidity.append(copy.deepcopy(v))
#
# Loop over all usage inside all <remove> tags.
for feature in interface.findall('remove'):
if (matchAPIProfile(api, profile, feature)):
if matchAPIProfile(api, profile, feature):
for v in feature.findall('usage'):
if v.get('command'):
self.cmddict[v.get('command')].removedValidity.append(copy.deepcopy(v))
if v.get('struct'):
self.typedict[v.get('struct')].removedValidity.append(copy.deepcopy(v))
#
# generateFeature - generate a single type / enum group / enum / command,
# and all its dependencies as needed.
# fname - name of feature (<type>/<enum>/<command>)
@ -699,17 +742,17 @@ class Registry:
self.gen.logMsg('diag', 'generateFeature: generating', ftype, fname)
f = self.lookupElementInfo(fname, dictionary)
if (f == None):
if f is None:
# No such feature. This is an error, but reported earlier
self.gen.logMsg('diag', 'No entry found for feature', fname,
'returning!')
return
#
# If feature isn't required, or has already been declared, return
if (not f.required):
if not f.required:
self.gen.logMsg('diag', 'Skipping', ftype, fname, '(not required)')
return
if (f.declared):
if f.declared:
self.gen.logMsg('diag', 'Skipping', ftype, fname, '(already declared)')
return
# Always mark feature declared, as though actually emitted
@ -720,23 +763,25 @@ class Registry:
if alias:
self.gen.logMsg('diag', fname, 'is an alias of', alias)
#
# Pull in dependent declaration(s) of the feature.
# For types, there may be one type in the 'required' attribute of
# For types, there may be one type in the 'requires' attribute of
# the element, one in the 'alias' attribute, and many in
# imbedded <type> and <enum> tags within the element.
# embedded <type> and <enum> tags within the element.
# For commands, there may be many in <type> tags within the element.
# For enums, no dependencies are allowed (though perhaps if you
# have a uint64 enum, it should require that type).
genProc = None
if (ftype == 'type'):
followupFeature = None
if ftype == 'type':
genProc = self.gen.genType
# Generate type dependencies in 'alias' and 'required' attributes
# Generate type dependencies in 'alias' and 'requires' attributes
if alias:
self.generateFeature(alias, 'type', self.typedict)
requires = f.elem.get('requires')
if requires:
self.gen.logMsg('diag', 'Generating required dependent type',
requires)
self.generateFeature(requires, 'type', self.typedict)
# Generate types used in defining this type (e.g. in nested
@ -757,10 +802,10 @@ class Registry:
# If the type is an enum group, look up the corresponding
# group in the group dictionary and generate that instead.
if (f.elem.get('category') == 'enum'):
if f.elem.get('category') == 'enum':
self.gen.logMsg('diag', 'Type', fname, 'is an enum group, so generate that instead')
group = self.lookupElementInfo(fname, self.groupdict)
if alias != None:
if alias is not None:
# An alias of another group name.
# Pass to genGroup with 'alias' parameter = aliased name
self.gen.logMsg('diag', 'Generating alias', fname,
@ -769,7 +814,7 @@ class Registry:
# with an additional parameter which is the alias name.
genProc = self.gen.genGroup
f = self.lookupElementInfo(alias, self.groupdict)
elif group == None:
elif group is None:
self.gen.logMsg('warn', 'Skipping enum type', fname,
': No matching enumerant group')
return
@ -817,7 +862,7 @@ class Registry:
self.gen.logMsg('diag', '* required =', required, 'for', name)
if required:
# Mark this element as required (in the element, not the EnumInfo)
elem.attrib['required'] = 'true'
elem.set('required', 'true')
# If it's an alias, track that for later use
enumAlias = elem.get('alias')
if enumAlias:
@ -825,20 +870,22 @@ class Registry:
for elem in enums:
name = elem.get('name')
if name in enumAliases:
elem.attrib['required'] = 'true'
elem.set('required', 'true')
self.gen.logMsg('diag', '* also need to require alias', name)
elif (ftype == 'command'):
if f.elem.get('category') == 'bitmask':
followupFeature = f.elem.get( 'bitvalues' )
elif ftype == 'command':
# Generate command dependencies in 'alias' attribute
if alias:
self.generateFeature(alias, 'command', self.cmddict)
genProc = self.gen.genCmd
for type in f.elem.findall('.//type'):
depname = type.text
for type_elem in f.elem.findall('.//type'):
depname = type_elem.text
self.gen.logMsg('diag', 'Generating required parameter type',
depname)
self.generateFeature(depname, 'type', self.typedict)
elif (ftype == 'enum'):
elif ftype == 'enum':
# Generate enum dependencies in 'alias' attribute
if alias:
self.generateFeature(alias, 'enum', self.enumdict)
@ -846,19 +893,23 @@ class Registry:
# Actually generate the type only if emitting declarations
if self.emitFeatures:
self.gen.logMsg('diag', 'Emitting', ftype, fname, 'declaration')
self.gen.logMsg('diag', 'Emitting', ftype, 'decl for', fname)
genProc(f, fname, alias)
else:
self.gen.logMsg('diag', 'Skipping', ftype, fname,
'(should not be emitted)')
#
if followupFeature :
self.gen.logMsg('diag', 'Generating required bitvalues <enum>',
followupFeature)
self.generateFeature(followupFeature, "type", self.typedict)
# generateRequiredInterface - generate all interfaces required
# by an API version or extension
# interface - Element for <version> or <extension>
def generateRequiredInterface(self, interface):
"""Generate required C interface for specified API version/extension"""
#
# Loop over all features inside all <require> tags.
for features in interface.findall('require'):
for t in features.findall('type'):
@ -868,30 +919,29 @@ class Registry:
for c in features.findall('command'):
self.generateFeature(c.get('name'), 'command', self.cmddict)
#
# apiGen(genOpts) - generate interface for specified versions
# genOpts - GeneratorOptions object with parameters used
# by the Generator object.
def apiGen(self, genOpts):
"""Generate interfaces for the specified API type and range of versions"""
#
self.gen.logMsg('diag', '*******************************************')
self.gen.logMsg('diag', ' Registry.apiGen file:', genOpts.filename,
'api:', genOpts.apiname,
'profile:', genOpts.profile)
self.gen.logMsg('diag', '*******************************************')
#
self.genOpts = genOpts
# Reset required/declared flags for all features
self.apiReset()
#
# Compile regexps used to select versions & extensions
regVersions = re.compile(self.genOpts.versions)
regEmitVersions = re.compile(self.genOpts.emitversions)
regAddExtensions = re.compile(self.genOpts.addExtensions)
regRemoveExtensions = re.compile(self.genOpts.removeExtensions)
regEmitExtensions = re.compile(self.genOpts.emitExtensions)
#
# Get all matching API feature names & add to list of FeatureInfo
# Note we used to select on feature version attributes, not names.
features = []
@ -899,15 +949,15 @@ class Registry:
for key in self.apidict:
fi = self.apidict[key]
api = fi.elem.get('api')
if (api == self.genOpts.apiname):
if api == self.genOpts.apiname:
apiMatch = True
if (regVersions.match(fi.name)):
if regVersions.match(fi.name):
# Matches API & version #s being generated. Mark for
# emission and add to the features[] list .
# @@ Could use 'declared' instead of 'emit'?
fi.emit = (regEmitVersions.match(fi.name) != None)
fi.emit = (regEmitVersions.match(fi.name) is not None)
features.append(fi)
if (not fi.emit):
if not fi.emit:
self.gen.logMsg('diag', 'NOT tagging feature api =', api,
'name =', fi.name, 'version =', fi.version,
'for emission (does not match emitversions pattern)')
@ -923,9 +973,9 @@ class Registry:
self.gen.logMsg('diag', 'NOT including feature api =', api,
'name =', fi.name,
'(does not match requested API)')
if (not apiMatch):
if not apiMatch:
self.gen.logMsg('warn', 'No matching API versions found!')
#
# Get all matching extensions, in order by their extension number,
# and add to the list of features.
# Start with extensions tagged with 'api' pattern matching the API
@ -935,7 +985,7 @@ class Registry:
for (extName,ei) in sorted(self.extdict.items(),key = lambda x : x[1].number):
extName = ei.name
include = False
#
# Include extension if defaultExtensions is not None and if the
# 'supported' attribute matches defaultExtensions. The regexp in
# 'supported' must exactly match defaultExtensions, so bracket
@ -946,12 +996,12 @@ class Registry:
self.gen.logMsg('diag', 'Including extension',
extName, "(defaultExtensions matches the 'supported' attribute)")
include = True
#
# Include additional extensions if the extension name matches
# the regexp specified in the generator options. This allows
# forcing extensions into an interface even if they're not
# tagged appropriately in the registry.
if (regAddExtensions.match(extName) != None):
if regAddExtensions.match(extName) is not None:
self.gen.logMsg('diag', 'Including extension',
extName, '(matches explicitly requested extensions to add)')
include = True
@ -959,20 +1009,21 @@ class Registry:
# in generator options. This allows forcing removal of
# extensions from an interface even if they're tagged that
# way in the registry.
if (regRemoveExtensions.match(extName) != None):
if regRemoveExtensions.match(extName) is not None:
self.gen.logMsg('diag', 'Removing extension',
extName, '(matches explicitly requested extensions to remove)')
include = False
#
# If the extension is to be included, add it to the
# extension features list.
if (include):
ei.emit = (regEmitExtensions.match(extName) != None)
if include:
ei.emit = (regEmitExtensions.match(extName) is not None)
features.append(ei)
if (not ei.emit):
if not ei.emit:
self.gen.logMsg('diag', 'NOT tagging extension',
extName,
'for emission (does not match emitextensions pattern)')
# Hack - can be removed when validity generator goes away
# (Jon) I'm not sure what this does, or if it should respect
# the ei.emit flag above.
@ -980,11 +1031,11 @@ class Registry:
else:
self.gen.logMsg('diag', 'NOT including extension',
extName, '(does not match api attribute or explicitly requested extensions)')
#
# Sort the extension features list, if a sort procedure is defined
if (self.genOpts.sortProcedure):
if self.genOpts.sortProcedure:
self.genOpts.sortProcedure(features)
#
# Pass 1: loop over requested API versions and extensions tagging
# types/commands/features as required (in an <require> block) or no
# longer required (in an <remove> block). It is possible to remove
@ -993,23 +1044,23 @@ class Registry:
# If a profile other than 'None' is being generated, it must
# match the profile attribute (if any) of the <require> and
# <remove> tags.
self.gen.logMsg('diag', '*******PASS 1: TAG FEATURES **********')
self.gen.logMsg('diag', 'PASS 1: TAG FEATURES')
for f in features:
self.gen.logMsg('diag', 'PASS 1: Tagging required and removed features for',
f.name)
self.requireAndRemoveFeatures(f.elem, self.genOpts.apiname, self.genOpts.profile)
self.requireAndRemoveFeatures(f.elem, f.name, self.genOpts.apiname, self.genOpts.profile)
self.assignAdditionalValidity(f.elem, self.genOpts.apiname, self.genOpts.profile)
#
# Pass 2: loop over specified API versions and extensions printing
# declarations for required things which haven't already been
# generated.
self.gen.logMsg('diag', '*******PASS 2: GENERATE INTERFACES FOR FEATURES **********')
self.gen.logMsg('diag', 'PASS 2: GENERATE INTERFACES FOR FEATURES')
self.gen.beginFile(self.genOpts)
for f in features:
self.gen.logMsg('diag', 'PASS 2: Generating interface for',
f.name)
emit = self.emitFeatures = f.emit
if (not emit):
if not emit:
self.gen.logMsg('diag', 'PASS 2: NOT declaring feature',
f.elem.get('name'), 'because it is not tagged for emission')
# Generate the interface (or just tag its elements as having been
@ -1018,54 +1069,51 @@ class Registry:
self.generateRequiredInterface(f.elem)
self.gen.endFeature()
self.gen.endFile()
#
# apiReset - use between apiGen() calls to reset internal state
#
def apiReset(self):
"""Reset type/enum/command dictionaries before generating another API"""
for type in self.typedict:
self.typedict[type].resetState()
for datatype in self.typedict:
self.typedict[datatype].resetState()
for enum in self.enumdict:
self.enumdict[enum].resetState()
for cmd in self.cmddict:
self.cmddict[cmd].resetState()
for cmd in self.apidict:
self.apidict[cmd].resetState()
#
# validateGroups - check that group= attributes match actual groups
#
def validateGroups(self):
"""Validate group= attributes on <param> and <proto> tags"""
# Keep track of group names not in <group> tags
badGroup = {}
self.gen.logMsg('diag', 'VALIDATING GROUP ATTRIBUTES ***')
self.gen.logMsg('diag', 'VALIDATING GROUP ATTRIBUTES')
for cmd in self.reg.findall('commands/command'):
proto = cmd.find('proto')
funcname = cmd.find('proto/name').text
if ('group' in proto.attrib.keys()):
group = proto.get('group')
# self.gen.logMsg('diag', 'Command ', funcname, ' has return group ', group)
if (group not in self.groupdict.keys()):
# self.gen.logMsg('diag', 'Command ', funcname, ' has UNKNOWN return group ', group)
if (group not in badGroup.keys()):
# funcname = cmd.find('proto/name').text
group = proto.get('group')
if group is not None and group not in self.groupdict:
# self.gen.logMsg('diag', '*** Command ', funcname, ' has UNKNOWN return group ', group)
if group not in badGroup:
badGroup[group] = 1
else:
badGroup[group] = badGroup[group] + 1
for param in cmd.findall('param'):
pname = param.find('name')
if pname is not None:
pname = pname.text
else:
pname = param.get('name')
group = param.get('group')
if group is not None and group not in self.groupdict:
# self.gen.logMsg('diag', '*** Command ', funcname, ' param ', pname, ' has UNKNOWN group ', group)
if group not in badGroup:
badGroup[group] = 1
else:
badGroup[group] = badGroup[group] + 1
for param in cmd.findall('param'):
pname = param.find('name')
if (pname != None):
pname = pname.text
else:
pname = type.get('name')
if ('group' in param.attrib.keys()):
group = param.get('group')
if (group not in self.groupdict.keys()):
# self.gen.logMsg('diag', 'Command ', funcname, ' param ', pname, ' has UNKNOWN group ', group)
if (group not in badGroup.keys()):
badGroup[group] = 1
else:
badGroup[group] = badGroup[group] + 1
if (len(badGroup.keys()) > 0):
self.gen.logMsg('diag', 'SUMMARY OF UNRECOGNIZED GROUPS ***')
if badGroup:
self.gen.logMsg('diag', 'SUMMARY OF UNRECOGNIZED GROUPS')
for key in sorted(badGroup.keys()):
self.gen.logMsg('diag', ' ', key, ' occurred ', badGroup[key], ' times')

File diff suppressed because it is too large Load Diff

214
scripts/vkconventions.py Normal file
View File

@ -0,0 +1,214 @@
#!/usr/bin/python3 -i
#
# Copyright (c) 2013-2019 The Khronos Group Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Working-group-specific style conventions,
# used in generation.
from conventions import ConventionsBase
class VulkanConventions(ConventionsBase):
def formatExtension(self, name):
"""Mark up a name as an extension for the spec."""
return '`<<{}>>`'.format(name)
@property
def null(self):
"""Preferred spelling of NULL."""
return '`NULL`'
@property
def constFlagBits(self):
"""Returns True if static const flag bits should be generated, False if an enumerated type should be generated."""
return False
@property
def struct_macro(self):
return 'sname:'
@property
def external_macro(self):
return 'code:'
@property
def structtype_member_name(self):
"""Return name of the structure type member"""
return 'sType'
@property
def nextpointer_member_name(self):
"""Return name of the structure pointer chain member"""
return 'pNext'
@property
def valid_pointer_prefix(self):
"""Return prefix to pointers which must themselves be valid"""
return 'valid'
def is_structure_type_member(self, paramtype, paramname):
"""Determine if member type and name match the structure type member."""
return paramtype == 'VkStructureType' and paramname == self.structtype_member_name
def is_nextpointer_member(self, paramtype, paramname):
"""Determine if member type and name match the next pointer chain member."""
return paramtype == 'void' and paramname == self.nextpointer_member_name
@property
def warning_comment(self):
"""Return warning comment to be placed in header of generated Asciidoctor files"""
return '// WARNING: DO NOT MODIFY! This file is automatically generated from the vk.xml registry'
@property
def file_suffix(self):
"""Return suffix of generated Asciidoctor files"""
return '.txt'
@property
def api_name(self):
"""Return API name"""
return 'Vulkan'
@property
def xml_supported_name_of_api(self):
"""Return the supported= attribute used in API XML"""
return 'vulkan'
@property
def api_prefix(self):
"""Return API token prefix"""
return 'VK_'
@property
def api_version_prefix(self):
"""Return API core version token prefix"""
return 'VK_VERSION_'
@property
def KHR_prefix(self):
"""Return extension name prefix for KHR extensions"""
return 'VK_KHR_'
@property
def EXT_prefix(self):
"""Return extension name prefix for EXT extensions"""
return 'VK_EXT_'
@property
def write_contacts(self):
"""Return whether contact list should be written to extension appendices"""
return True
@property
def write_refpage_include(self):
"""Return whether refpage include should be written to extension appendices"""
return True
def writeFeature(self, featureExtraProtect, filename):
"""Returns True if OutputGenerator.endFeature should write this feature.
Used in COutputGenerator
"""
return True
def requires_error_validation(self, return_type):
"""Returns True if the return_type element is an API result code
requiring error validation.
"""
return False
@property
def required_errors(self):
"""Return a list of required error codes for validation."""
return []
def is_externsync_command(self, protoname):
"""Returns True if the protoname element is an API command requiring
external synchronization
"""
return protoname is not None and 'vkCmd' in protoname
def is_api_name(self, name):
"""Returns True if name is in the reserved API namespace.
For Vulkan, these are names with a case-insensitive 'vk' prefix, or
a 'PFN_vk' function pointer type prefix.
"""
return name[0:2].lower() == 'vk' or name[0:6] == 'PFN_vk'
def is_voidpointer_alias(self, tag, text, tail):
"""Return True if the declaration components (tag,text,tail) of an
element represents a void * type
"""
return tag == 'type' and text == 'void' and tail.startswith('*')
def make_voidpointer_alias(self, tail):
"""Reformat a void * declaration to include the API alias macro.
Vulkan doesn't have an API alias macro, so do nothing.
"""
return tail
@property
def specURL(self):
"""Return public registry URL which ref pages should link to for the
current all-extensions HTML specification, so xrefs in the
asciidoc source that aren't to ref pages can link into it
instead. N.b. this may need to change on a per-refpage basis if
there are multiple documents involved.
"""
return 'https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html'
@property
def xml_api_name(self):
"""Return the name used in the default API XML registry for the default API"""
return 'vulkan'
@property
def registry_path(self):
"""Return relpath to the default API XML registry in this project."""
return 'xml/vk.xml'
@property
def specification_path(self):
"""Return relpath to the Asciidoctor specification sources in this project."""
return '../appendices/meta'
@property
def extra_refpage_headers(self):
"""Return any extra text to add to refpage headers."""
return 'include::../config/attribs.txt[]'
@property
def extension_index_prefixes(self):
"""Return a list of extension prefixes used to group extension refpages."""
return ['VK_KHR', 'VK_EXT', 'VK']
@property
def unified_flag_refpages(self):
"""Returns True if Flags/FlagBits refpages are unified, False if
they're separate.
"""
return False
@property
def spec_reflow_path(self):
"""Return the relative path to the spec source folder to reflow"""
return '.'
@property
def spec_no_reflow_dirs(self):
"""Return a set of directories not to automatically descend into
when reflowing spec text
"""
return ('scripts', 'style')

View File

@ -195,23 +195,22 @@ This list is not intended to be complete.
[[writing-undefined]]
== Describing Undefined Behavior
When describing undefined behavior, be clear about what is and is not
defined.
When describing undefined behavior that results only in the values of
specified variables, or the contents of specified memory, becoming undefined
or implementation-defined, use the undefined{cl} macro to indicate that each
use of the term "`undefined`" has been carefully considered and accurately
represents the degree of undefined behavior allowed.
Do not write "`undefined results`" unless the effect of an operation is
truly completely undefined (up to and including termination of the
application, for example).
More often, what should be done is to say that the *values* of specified
variables, or the *contents* of specified memory, become undefined or
implementation-defined as a result of such operations.
Use the undefined{cl} macro to indicate that each use of the term
"`undefined`" has been carefully considered and accurately represents the
degree of undefined behavior allowed.
Any use of the word "`undefined`" without the trailing {cl} is suspect.
Note that this does not translate into visible markup in the output
document; it is simply markup to help track uses of the word.
Note that this does not result in visible markup in the output document; it
is simply markup to help track uses of the word.
When describing more general types of undefined behavior (up to and
including termination of the application), do *not* use the term
"`undefined`".
Instead, specify that the application must{cl} not create circumstances that
would lead to such behavior.
Such statements should be written as valid usage statements, if possible.
[[writing-describing]]

View File

@ -21,7 +21,7 @@
# GENOPTS can be e.g. '-noprotect'
PYTHON ?= python3
PYFILES = genheaders.py reg.py
SCRIPTS = ../scripts
GENOPTS =
# Generate Vulkan header from XML. Many other files can be generated
@ -62,10 +62,11 @@ default install: $(HEADERS)
# Autogenerate vulkan header from XML API description
# Python and XML files on which vulkan_core.h depends
VKH_DEPENDS = vk.xml genvk.py reg.py generator.py
GENSCRIPT = $(SCRIPTS)/genvk.py
VKH_DEPENDS = vk.xml $(GENSCRIPT) $(SCRIPTS)/reg.py $(SCRIPTS)/generator.py
$(HEADERS): $(VKH_DEPENDS)
$(PYTHON) genvk.py -registry vk.xml -o $(VULKAN) $(notdir $@)
$(PYTHON) $(GENSCRIPT) -registry vk.xml -o $(VULKAN) $(notdir $@)
platform: $(PLATFORM_HEADERS)
@ -87,17 +88,6 @@ test: $(HEADERS) $(VULKAN)/vulkan.h $(VULKAN)/vk_platform.h
################################################
# Autogenerate extension loader from XML API description
# Also generates $(EXTLOADER)/vulkan_ext.h
# No longer supported.
EXTLOADER = $(SRC)/ext_loader
EXTSRCS = $(EXTLOADER)/vulkan_ext.c
extloader $(EXTSRCS): $(VKH_DEPENDS)
$(PYTHON) genvk.py -registry vk.xml -o $(EXTLOADER) vulkan_ext.c
################################################
# Files to clean up
PYDIRT = diag.txt dumpReg.txt errwarn.txt *.pyc regdump.txt
DIRT = $(PYDIRT) ERRS \#*

View File

@ -51,27 +51,31 @@ processing XML.
* Makefile - generates headers and extension loader sources from XML (see
<<targets,Makefile Targets>> below).
* vk.xml - XML API description.
* genvk.py - Python script to generate vulkan_core.h and other targets.
* registry.rnc - RelaxNG compact schema for validating XML against the
schema.
* reg.py - Python tools to read XML file and convert it into C headers.
* generator.py - output generator base class.
** cgenerator.py - C header output generator.
** docgenerator.py - Asciidoc interface language include generator.
** extensionmetadocgenerator.py - Generator for Asciidoc extension
descriptions in spec appendices.
** extensionStubSource.py - Simple loader C source generator. Unsupported.
** hostsyncgenerator.py - Asciidoc host sync table generator.
** pygenerator.py - Generates python encoding of the API description.
** validitygenerator.py - Asciidoc validity language generator.
* Python scripts in ../scripts/ which operate on vk.xml.
** ../scripts/genvk.py - Python script to generate vulkan_core.h and other
targets.
** ../scripts/reg.py - Python tools to read XML file and convert it into C
headers.
** ../scripts/generator.py - output generator base class.
** ../scripts/cgenerator.py - C header output generator.
** ../scripts/docgenerator.py - Asciidoc interface language include
generator.
** ../scripts/extensionmetadocgenerator.py - Generator for Asciidoc
extension descriptions in spec appendices.
** ../scripts/hostsyncgenerator.py - Asciidoc host sync table generator.
** ../scripts/pygenerator.py - Generates python encoding of the API
description.
** ../scripts/validitygenerator.py - Asciidoc validity language generator.
* ../include/vulkan/vulkan_core.h - Generated Vulkan non-platform API
header.
* ../include/vulkan/vulkan_<platform>.h - Generated Vulkan platform API
headers.
* indexExt.py - generate HTML index of all extensions for inclusion into
the Vulkan registry index page.
* extDependency.py - generate extension dependencies in Bash and Python
form for use when building the specification.
* ../scripts/indexExt.py - generate HTML index of all extensions for
inclusion into the Vulkan registry index page.
* ../scripts/extDependency.py - generate extension dependencies in Bash
and Python form for use when building the specification.
[[targets]]
== Makefile Targets
@ -86,8 +90,6 @@ processing XML.
* `clean_dirt` - remove intermediate files.
* `clean` - remove generated files. Usually done when preparing to merge
to `master` branch via ```make clean ; make install```.
* `extloader` - generate simple extension loader source code in
`../src/vulkan_ext/`. Unsupported.
If you have trouble running the Makefile on your platform, the following
steps will build `vulkan_core.h` and test that it compiles:
@ -95,7 +97,7 @@ steps will build `vulkan_core.h` and test that it compiles:
[source,sh]
----
# Regenerate header from XML
python3 genvk.py -o ../include/vulkan vulkan_core.h
python3 ../scripts/genvk.py -o ../include/vulkan vulkan_core.h
# Verify that the resulting header compiles
gcc -Wall -c -I../include testcore.c
g++ -Wall -c -std=c++98 -I../include testcore.c
@ -136,6 +138,8 @@ Windows is:
[[history]]
== Revision History
* 2019/03/10 -
Update for script reorganization.
* 2018/05/21 -
Don't generate vulkan_ext.[ch] from the `install` target. Add a new
shortcut `extloader` target for people still using this code and needing

View File

@ -125,6 +125,7 @@ server.
<type requires="wayland-client.h" name="wl_surface"/>
<type requires="windows.h" name="HINSTANCE"/>
<type requires="windows.h" name="HWND"/>
<type requires="windows.h" name="HMONITOR"/>
<type requires="windows.h" name="HANDLE"/>
<type requires="windows.h" name="SECURITY_ATTRIBUTES"/>
<type requires="windows.h" name="DWORD"/>
@ -147,7 +148,7 @@ server.
<type category="define">// Vulkan 1.1 version number
#define <name>VK_API_VERSION_1_1</name> <type>VK_MAKE_VERSION</type>(1, 1, 0)// Patch version should always be set to 0</type>
<type category="define">// Version of this file
#define <name>VK_HEADER_VERSION</name> 103</type>
#define <name>VK_HEADER_VERSION</name> 104</type>
<type category="define">
#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;</type>
@ -259,6 +260,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="bitmask">typedef <type>VkFlags</type> <name>VkDescriptorUpdateTemplateCreateFlags</name>;</type>
<type category="bitmask" name="VkDescriptorUpdateTemplateCreateFlagsKHR" alias="VkDescriptorUpdateTemplateCreateFlags"/>
<type requires="VkPipelineCreationFeedbackFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCreationFeedbackFlagsEXT</name>;</type>
<comment>WSI extensions</comment>
<type requires="VkCompositeAlphaFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkCompositeAlphaFlagsKHR</name>;</type>
@ -487,6 +489,7 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkMemoryOverallocationBehaviorAMD" category="enum"/>
<type name="VkScopeNV" category="enum"/>
<type name="VkComponentTypeNV" category="enum"/>
<type name="VkPipelineCreationFeedbackFlagBitsEXT" category="enum"/>
<comment>WSI extensions</comment>
<type name="VkColorSpaceKHR" category="enum"/>
@ -541,6 +544,7 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkBlendOverlapEXT" category="enum"/>
<type name="VkDebugUtilsMessageSeverityFlagBitsEXT" category="enum"/>
<type name="VkDebugUtilsMessageTypeFlagBitsEXT" category="enum"/>
<type name="VkFullScreenExclusiveEXT" category="enum"/>
<comment>Enumerated types in the header, but not used by the API</comment>
<type name="VkVendorId" category="enum"/>
@ -2496,6 +2500,16 @@ typedef void <name>CAMetalLayer</name>;
<member noautovalidity="true"><type>float</type> <name>maxContentLightLevel</name><comment>Content maximum luminance</comment></member>
<member noautovalidity="true"><type>float</type> <name>maxFrameAverageLightLevel</name></member>
</type>
<type category="struct" name="VkDisplayNativeHdrSurfaceCapabilitiesAMD" returnedonly="true" structextends="VkSurfaceCapabilities2KHR">
<member values="VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD"><type>VkStructureType</type> <name>sType</name></member>
<member><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>localDimmingSupport</name></member>
</type>
<type category="struct" name="VkSwapchainDisplayNativeHdrCreateInfoAMD" structextends="VkSwapchainCreateInfoKHR">
<member values="VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD"><type>VkStructureType</type> <name>sType</name></member>
<member>const <type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>localDimmingEnable</name></member>
</type>
<type category="struct" name="VkRefreshCycleDurationGOOGLE" returnedonly="true">
<member><type>uint64_t</type> <name>refreshDuration</name><comment>Number of nanoseconds from the start of one refresh cycle to the next</comment></member>
</type>
@ -2645,12 +2659,12 @@ typedef void <name>CAMetalLayer</name>;
</type>
<type category="struct" name="VkPhysicalDevice16BitStorageFeaturesKHR" alias="VkPhysicalDevice16BitStorageFeatures"/>
<type category="struct" name="VkPhysicalDeviceSubgroupProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member><type>void</type>* <name>pNext</name></member>
<member noautovalidity="true"><type>uint32_t</type> <name>subgroupSize</name><comment>The size of a subgroup for this queue.</comment></member>
<member noautovalidity="true"><type>VkShaderStageFlags</type> <name>supportedStages</name><comment>Bitfield of what shader stages support subgroup operations</comment></member>
<member noautovalidity="true"><type>VkSubgroupFeatureFlags</type> <name>supportedOperations</name><comment>Bitfield of what subgroup operations are supported.</comment></member>
<member noautovalidity="true"><type>VkBool32</type> <name>quadOperationsInAllStages</name><comment>Flag to specify whether quad operations are available in all stages.</comment></member>
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member><type>void</type>* <name>pNext</name></member>
<member noautovalidity="true"><type>uint32_t</type> <name>subgroupSize</name><comment>The size of a subgroup for this queue.</comment></member>
<member noautovalidity="true"><type>VkShaderStageFlags</type> <name>supportedStages</name><comment>Bitfield of what shader stages support subgroup operations</comment></member>
<member noautovalidity="true"><type>VkSubgroupFeatureFlags</type> <name>supportedOperations</name><comment>Bitfield of what subgroup operations are supported.</comment></member>
<member noautovalidity="true"><type>VkBool32</type> <name>quadOperationsInAllStages</name><comment>Flag to specify whether quad operations are available in all stages.</comment></member>
</type>
<type category="struct" name="VkBufferMemoryRequirementsInfo2">
<member values="VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2"><type>VkStructureType</type> <name>sType</name></member>
@ -2977,6 +2991,11 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBool32</type> <name>shaderRoundingModeRTZFloat32</name></member> <!-- An implementation can support RTZ -->
<member><type>VkBool32</type> <name>shaderRoundingModeRTZFloat64</name></member> <!-- An implementation can support RTZ -->
</type>
<type category="struct" name="VkPhysicalDeviceHostQueryResetFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member noautovalidity="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>hostQueryReset</name></member>
</type>
<type category="struct" name="VkNativeBufferANDROID">
<member values="VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID"><type>VkStructureType</type> <name>sType</name></member>
<member>const <type>void</type>* <name>pNext</name></member>
@ -3698,6 +3717,11 @@ typedef void <name>CAMetalLayer</name>;
<member><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>scalarBlockLayout</name></member>
</type>
<type category="struct" name="VkSurfaceProtectedCapabilitiesKHR" structextends="VkSurfaceCapabilities2KHR">
<member values="VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member>const <type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>supportsProtected</name><comment>Represents if surface can be protected</comment></member>
</type>
<type category="struct" name="VkPhysicalDeviceDepthClipEnableFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member><type>void</type>* <name>pNext</name><comment>Pointer to next structure</comment></member>
@ -3740,7 +3764,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkBufferDeviceAddressCreateInfoEXT" structextends="VkBufferCreateInfo">
<member values="VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member>const <type>void</type>* <name>pNext</name></member>
<member><type>VkDeviceSize</type> <name>deviceAddress</name></member>
<member><type>VkDeviceAddress</type> <name>deviceAddress</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceImageViewImageFormatInfoEXT" structextends="VkPhysicalDeviceImageFormatInfo2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
@ -3788,6 +3812,32 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkDescriptorType</type> <name>descriptorType</name></member>
<member optional="true"><type>VkSampler</type> <name>sampler</name></member>
</type>
<type category="struct" name="VkPipelineCreationFeedbackEXT" returnedonly="true">
<member><type>VkPipelineCreationFeedbackFlagsEXT</type> <name>flags</name></member>
<member><type>uint64_t</type> <name>duration</name></member>
</type>
<type category="struct" name="VkPipelineCreationFeedbackCreateInfoEXT" structextends="VkGraphicsPipelineCreateInfo,VkComputePipelineCreateInfo,VkRayTracingPipelineCreateInfoNV">
<member values="VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member>const <type>void</type>* <name>pNext</name></member>
<member><type>VkPipelineCreationFeedbackEXT</type>* <name>pPipelineCreationFeedback</name><comment>Output pipeline creation feedback.</comment></member>
<member><type>uint32_t</type> <name>pipelineStageCreationFeedbackCount</name></member>
<member len="pipelineStageCreationFeedbackCount"><type>VkPipelineCreationFeedbackEXT</type>* <name>pPipelineStageCreationFeedbacks</name><comment>One entry for each shader stage specified in the parent Vk*PipelineCreateInfo struct</comment></member>
</type>
<type category="struct" name="VkSurfaceFullScreenExclusiveInfoEXT" structextends="VkPhysicalDeviceSurfaceInfo2KHR,VkSwapchainCreateInfoKHR">
<member values="VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member><type>void</type>* <name>pNext</name></member>
<member><type>VkFullScreenExclusiveEXT</type> <name>fullScreenExclusive</name></member>
</type>
<type category="struct" name="VkSurfaceFullScreenExclusiveWin32InfoEXT" structextends="VkPhysicalDeviceSurfaceInfo2KHR,VkSwapchainCreateInfoKHR">
<member values="VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member>const <type>void</type>* <name>pNext</name></member>
<member><type>HMONITOR</type> <name>hmonitor</name></member>
</type>
<type category="struct" name="VkSurfaceCapabilitiesFullScreenExclusiveEXT" structextends="VkSurfaceCapabilities2KHR">
<member values="VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>fullScreenExclusiveSupported</name></member>
</type>
</types>
<comment>Vulkan enumerant (token) definitions</comment>
@ -5010,6 +5060,17 @@ typedef void <name>CAMetalLayer</name>;
<enum value="9" name="VK_COMPONENT_TYPE_UINT32_NV"/>
<enum value="10" name="VK_COMPONENT_TYPE_UINT64_NV"/>
</enums>
<enums name="VkPipelineCreationFeedbackFlagBitsEXT" type="bitmask">
<enum bitpos="0" name="VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT"/>
<enum bitpos="1" name="VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT"/>
<enum bitpos="2" name="VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT"/>
</enums>
<enums name="VkFullScreenExclusiveEXT" type="enum">
<enum value="0" name="VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT"/>
<enum value="1" name="VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT"/>
<enum value="2" name="VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT"/>
<enum value="3" name="VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT"/>
</enums>
<commands comment="Vulkan command definitions">
<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>
@ -5333,6 +5394,13 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkDeviceSize</type> <name>stride</name></param>
<param optional="true"><type>VkQueryResultFlags</type> <name>flags</name></param>
</command>
<command>
<proto><type>void</type> <name>vkResetQueryPoolEXT</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param><type>VkQueryPool</type> <name>queryPool</name></param>
<param><type>uint32_t</type> <name>firstQuery</name></param>
<param><type>uint32_t</type> <name>queryCount</name></param>
</command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_DEVICE_ADDRESS_EXT">
<proto><type>VkResult</type> <name>vkCreateBuffer</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
@ -6066,7 +6134,7 @@ typedef void <name>CAMetalLayer</name>;
<param optional="false,true"><type>uint32_t</type>* <name>pPresentModeCount</name></param>
<param optional="true" len="pPresentModeCount"><type>VkPresentModeKHR</type>* <name>pPresentModes</name></param>
</command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_SURFACE_LOST_KHR,VK_ERROR_NATIVE_WINDOW_IN_USE_KHR">
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_SURFACE_LOST_KHR,VK_ERROR_NATIVE_WINDOW_IN_USE_KHR,VK_ERROR_INITIALIZATION_FAILED">
<proto><type>VkResult</type> <name>vkCreateSwapchainKHR</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param externsync="pCreateInfo.surface,pCreateInfo.oldSwapchain">const <type>VkSwapchainCreateInfoKHR</type>* <name>pCreateInfo</name></param>
@ -6086,7 +6154,7 @@ typedef void <name>CAMetalLayer</name>;
<param optional="false,true"><type>uint32_t</type>* <name>pSwapchainImageCount</name></param>
<param optional="true" len="pSwapchainImageCount"><type>VkImage</type>* <name>pSwapchainImages</name></param>
</command>
<command successcodes="VK_SUCCESS,VK_TIMEOUT,VK_NOT_READY,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR">
<command successcodes="VK_SUCCESS,VK_TIMEOUT,VK_NOT_READY,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR,VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT">
<proto><type>VkResult</type> <name>vkAcquireNextImageKHR</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param externsync="true"><type>VkSwapchainKHR</type> <name>swapchain</name></param>
@ -6095,7 +6163,7 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true" externsync="true"><type>VkFence</type> <name>fence</name></param>
<param><type>uint32_t</type>* <name>pImageIndex</name></param>
</command>
<command successcodes="VK_SUCCESS,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR">
<command successcodes="VK_SUCCESS,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR,VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT">
<proto><type>VkResult</type> <name>vkQueuePresentKHR</name></proto>
<param externsync="true"><type>VkQueue</type> <name>queue</name></param>
<param externsync="pPresentInfo.pWaitSemaphores[],pPresentInfo.pSwapchains[]">const <type>VkPresentInfoKHR</type>* <name>pPresentInfo</name></param>
@ -6564,7 +6632,7 @@ typedef void <name>CAMetalLayer</name>;
<param externsync="true"><type>VkSurfaceKHR</type> <name>surface</name></param>
<param optional="false,true"><type>VkDeviceGroupPresentModeFlagsKHR</type>* <name>pModes</name></param>
</command>
<command successcodes="VK_SUCCESS,VK_TIMEOUT,VK_NOT_READY,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR">
<command successcodes="VK_SUCCESS,VK_TIMEOUT,VK_NOT_READY,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR,VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT">
<proto><type>VkResult</type> <name>vkAcquireNextImage2KHR</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param>const <type>VkAcquireNextImageInfoKHR</type>* <name>pAcquireInfo</name></param>
@ -6594,7 +6662,7 @@ typedef void <name>CAMetalLayer</name>;
<param>const <type>VkDescriptorUpdateTemplateCreateInfo</type>* <name>pCreateInfo</name></param>
<param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
<param><type>VkDescriptorUpdateTemplate</type>* <name>pDescriptorUpdateTemplate</name></param>
</command>
</command>
<command name="vkCreateDescriptorUpdateTemplateKHR" alias="vkCreateDescriptorUpdateTemplate"/>
<command>
<proto><type>void</type> <name>vkDestroyDescriptorUpdateTemplate</name></proto>
@ -6626,7 +6694,7 @@ typedef void <name>CAMetalLayer</name>;
<param len="swapchainCount">const <type>VkSwapchainKHR</type>* <name>pSwapchains</name></param>
<param len="swapchainCount">const <type>VkHdrMetadataEXT</type>* <name>pMetadata</name></param>
</command>
<command successcodes="VK_SUCCESS,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR">
<command successcodes="VK_SUCCESS,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR,VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT">
<proto><type>VkResult</type> <name>vkGetSwapchainStatusKHR</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param externsync="true"><type>VkSwapchainKHR</type> <name>swapchain</name></param>
@ -6837,6 +6905,11 @@ typedef void <name>CAMetalLayer</name>;
<param optional="false,true"><type>size_t</type>* <name>pInfoSize</name></param>
<param optional="true" len="pInfoSize"><type>void</type>* <name>pInfo</name></param>
</command>
<command>
<proto><type>void</type> <name>vkSetLocalDimmingAMD</name></proto>
<param><type>VkSwapchainKHR</type> <name>swapChain</name></param>
<param><type>VkBool32</type> <name>localDimmingEnable</name></param>
</command>
<command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
<proto><type>VkResult</type> <name>vkGetPhysicalDeviceCalibrateableTimeDomainsEXT</name></proto>
<param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
@ -7216,6 +7289,30 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkDevice</type> <name>device</name></param>
<param>const <type>VkImageViewHandleInfoNVX</type>* <name>pInfo</name></param>
</command>
<command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
<proto><type>VkResult</type> <name>vkGetPhysicalDeviceSurfacePresentModes2EXT</name></proto>
<param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
<param>const <type>VkPhysicalDeviceSurfaceInfo2KHR</type>* <name>pSurfaceInfo</name></param>
<param optional="false,true"><type>uint32_t</type>* <name>pPresentModeCount</name></param>
<param optional="true" len="pPresentModeCount"><type>VkPresentModeKHR</type>* <name>pPresentModes</name></param>
</command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
<proto><type>VkResult</type> <name>vkGetDeviceGroupSurfacePresentModes2EXT</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param>const <type>VkPhysicalDeviceSurfaceInfo2KHR</type>* <name>pSurfaceInfo</name></param>
<param optional="false,true"><type>VkDeviceGroupPresentModeFlagsKHR</type>* <name>pModes</name></param>
</command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_SURFACE_LOST_KHR">
<proto><type>VkResult</type> <name>vkAcquireFullScreenExclusiveModeEXT</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param><type>VkSwapchainKHR</type> <name>swapchain</name></param>
</command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
<proto><type>VkResult</type> <name>vkReleaseFullScreenExclusiveModeEXT</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param><type>VkSwapchainKHR</type> <name>swapchain</name></param>
</command>
</commands>
<feature api="vulkan" name="VK_VERSION_1_0" number="1.0" comment="Vulkan core API interface definitions">
@ -7985,7 +8082,7 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_IMG_filter_cubic&quot;" name="VK_IMG_FILTER_CUBIC_EXTENSION_NAME"/>
<enum offset="0" extends="VkFilter" name="VK_FILTER_CUBIC_IMG"/>
<enum bitpos="13" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG" comment="Format can be filtered with VK_FILTER_CUBIC_IMG when being sampled"/>
</require>
</require>
</extension>
<extension name="VK_AMD_extension_17" number="17" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
<require>
@ -8454,6 +8551,9 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkDeviceGroupSwapchainCreateInfoKHR"/>
<command name="vkAcquireNextImage2KHR"/>
</require>
<require extension="VK_EXT_full_screen_exclusive">
<command name="vkGetDeviceGroupSurfacePresentModes2EXT"/>
</require>
</extension>
<extension name="VK_EXT_validation_flags" number="62" type="instance" author="GOOGLE" contact="Tobin Ehlis @tobine" supported="vulkan">
<require>
@ -10058,10 +10158,15 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_GOOGLE_extension_192&quot;" name="VK_GOOGLE_EXTENSION_192_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_GOOGLE_extension_193" number="193" author="GOOGLE" contact="Jean-Francois Roy @jfroy" supported="disabled">
<extension name="VK_EXT_pipeline_creation_feedback" number="193" type="device" author="GOOGLE" contact="Jean-Francois Roy @jfroy" supported="vulkan">
<require>
<enum value="0" name="VK_GOOGLE_EXTENSION_193_SPEC_VERSION"/>
<enum value="&quot;VK_GOOGLE_extension_193&quot;" name="VK_GOOGLE_EXTENSION_193_EXTENSION_NAME"/>
<enum value="1" name="VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_pipeline_creation_feedback&quot;" name="VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT"/>
<type name="VkPipelineCreationFeedbackFlagBitsEXT"/>
<type name="VkPipelineCreationFeedbackFlagsEXT"/>
<type name="VkPipelineCreationFeedbackCreateInfoEXT"/>
<type name="VkPipelineCreationFeedbackEXT"/>
</require>
</extension>
<extension name="VK_GOOGLE_extension_194" number="194" author="GOOGLE" contact="Jean-Francois Roy @jfroy" supported="disabled">
@ -10233,10 +10338,16 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkPhysicalDevicePCIBusInfoPropertiesEXT"/>
</require>
</extension>
<extension name="VK_AMD_extension_214" number="214" author="AMD" contact="Neil Henning @sheredom" supported="disabled">
<extension name="VK_AMD_display_native_hdr" number="214" type="device" author="AMD" requires="VK_KHR_get_physical_device_properties2,VK_KHR_get_surface_capabilities2,VK_KHR_swapchain" contact="Matthaeus G. Chajdas @anteru" supported="vulkan">
<require>
<enum value="0" name="VK_KHR_EXTENSION_214_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_extension_214&quot;" name="VK_KHR_EXTENSION_214_EXTENSION_NAME"/>
<enum value="1" name="VK_AMD_DISPLAY_NATIVE_HDR_SPEC_VERSION"/>
<enum value="&quot;VK_AMD_display_native_hdr&quot;" name="VK_AMD_DISPLAY_NATIVE_HDR_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_NATIVE_HDR_SURFACE_CAPABILITIES_AMD"/>
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SWAPCHAIN_DISPLAY_NATIVE_HDR_CREATE_INFO_AMD"/>
<enum offset="0" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_DISPLAY_NATIVE_AMD"/>
<type name="VkDisplayNativeHdrSurfaceCapabilitiesAMD"/>
<type name="VkSwapchainDisplayNativeHdrCreateInfoAMD"/>
<command name="vkSetLocalDimmingAMD"/>
</require>
</extension>
<extension name="VK_FUCHSIA_imagepipe_surface" number="215" type="instance" author="FUCHSIA" requires="VK_KHR_surface" platform="fuchsia" contact="Craig Stout @cdotstout" supported="vulkan">
@ -10421,10 +10532,12 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkMemoryPriorityAllocateInfoEXT"/>
</require>
</extension>
<extension name="VK_KHR_extension_240" number="240" author="KHR" contact="Sandeep Shinde @nvidia" supported="disabled">
<extension name="VK_KHR_surface_protected_capabilities" number="240" type="instance" requiresCore="1.1" requires="VK_KHR_get_surface_capabilities2" author="KHR" contact="Sandeep Shinde @sashinde" supported="vulkan">
<require>
<enum value="0" name="VK_KHR_EXTENSION_240_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_extension_240&quot;" name="VK_KHR_EXTENSION_240_EXTENSION_NAME"/>
<enum value="1" name="VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_surface_protected_capabilities&quot;" name="VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR"/>
<type name="VkSurfaceProtectedCapabilitiesKHR"/>
</require>
</extension>
<extension name="VK_NV_dedicated_allocation_image_aliasing" number="241" type="device" requires="VK_KHR_dedicated_allocation" author="NVIDIA" contact="Nuno Subtil @nsubtil" supported="vulkan">
@ -10544,10 +10657,26 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_EXT_extension_255&quot;" name="VK_EXT_EXTENSION_255_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_EXT_extension_256" number="256" author="EXT" contact="James Jones @cubanismo" supported="disabled">
<extension name="VK_EXT_full_screen_exclusive" number="256" type="device" author="EXT" requires="VK_KHR_get_physical_device_properties2,VK_KHR_surface,VK_KHR_get_surface_capabilities2,VK_KHR_swapchain" platform="win32" contact="James Jones @cubanismo" supported="vulkan">
<require>
<enum value="0" name="VK_EXT_EXTENSION_256_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_extension_256&quot;" name="VK_EXT_EXTENSION_256_EXTENSION_NAME"/>
<enum value="3" name="VK_EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_full_screen_exclusive&quot;" name="VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT"/>
<enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT"/>
<enum offset="0" extends="VkResult" dir="-" name="VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT"/>
<type name="VkFullScreenExclusiveEXT"/>
<type name="VkSurfaceFullScreenExclusiveInfoEXT"/>
<type name="VkSurfaceCapabilitiesFullScreenExclusiveEXT"/>
<command name="vkGetPhysicalDeviceSurfacePresentModes2EXT"/>
<command name="vkAcquireFullScreenExclusiveModeEXT"/>
<command name="vkReleaseFullScreenExclusiveModeEXT"/>
</require>
<require feature="VK_KHR_win32_surface">
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT"/>
<type name="VkSurfaceFullScreenExclusiveWin32InfoEXT"/>
</require>
<require feature="VK_VERSION_1_1">
<command name="vkGetDeviceGroupSurfacePresentModes2EXT"/>
</require>
</extension>
<extension name="VK_EXT_extension_257" number="257" author="EXT" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="disabled">
@ -10580,5 +10709,14 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_NV_extension_261&quot;" name="VK_NV_EXTENSION_261_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_EXT_host_query_reset" number="262" author="EXT" contact="Bas Nieuwenhuizen @BNieuwenhuizen" supported="vulkan" type="device" requires="VK_KHR_get_physical_device_properties2">
<require>
<enum value="1" name="VK_EXT_HOST_QUERY_RESET_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_host_query_reset&quot;" name="VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT"/>
<type name="VkPhysicalDeviceHostQueryResetFeaturesEXT"/>
<command name="vkResetQueryPoolEXT"/>
</require>
</extension>
</extensions>
</registry>