Vulkan-Docs/src/spec/pygenerator.py

243 lines
10 KiB
Python
Raw Normal View History

#!/usr/bin/python3 -i
#
Change log for January 23, 2017 Vulkan 1.0.39 spec update: * Bump API patch number and header version number to 39 for this update. Github Issues: * Clarified that only accesses via the specified buffer/image subresource ranges are included in the access scopes (public issue 306). * Add missing valid usage statements for flink:vkCreateComputePipelines and flink:vkCreateGraphicsPipelines (public issue 427). Internal Issues: * Add a Note to the <<invariance,Invariance>> appendix about a difference between OpenGL and Vulkan with regards to how primitives derived from offsets are handled (internal issue 355). * Add the +<<VK_KHR_get_physical_device_properties2>>+, +<<VK_KHR_maintenance1>>+, and +<<VK_KHR_shader_draw_parameters>>+ extensions (internal issue 448). * Add the +<<VK_EXT_shader_subgroup_vote>>+ and +<<VK_EXT_shader_subgroup_ballot>>+ extensions (internal issue 449). * Update the texture level-of-detail equation in the <<textures-scale-factor,Scale Factor Operation>> section to better approximate the ellipse major and minor axes (internal issue 547). * Forbid non-explicitly allowed uses of interface decorations in the introduction to the <<interfaces,Shader Interfaces>> chapter (internal issue 607). * Replace use of MathJax with KaTeX, for improved load-time performance as well as avoiding the scrolling-and-scrolling behavior due to MathJax asynchronous rendering when loading at an anchor inside the spec. This change also requires moving to HTML5 output for the spec instead of XHTML, and there is a visible difference in that the chapter navigation index is now in a scrollable sidebar instead of at the top of the document. We may or may not retain the nav sidebar based on feedback (internal issue 613). * Improve consistency of markup and formatting in extension appendices (internal issue 631). Other Issues: * Add explicit valid usage statements to slink:VkImageCopy requiring that the source and destination layer ranges be contained in their respective source and destination images. * Add valid usage language for swapchain of flink:vkAcquireNextImage. If the swapchain has been replaced, then it should not be passed to flink:vkAcquireNextImage. * Add a valid usage statement to flink:vkCreateImageView, that the image must have been created with an appropriate usage bit set. * Noted that slink:VkDisplayPresentInfoKHR is a valid extension of slink:VkPresentInfoKHR in the <<wsi_swapchain,WSI Swapchain>> section. * Update valid usage for flink:vkCmdSetViewport and flink:vkCmdSetScissor to account for the multiple viewport feature. If the feature is not enabled, the parameters for these functions have required values that are defined in the <<features-features-multiViewport,multiple viewports>> section of the spec but were not reflected in the valid usage text for these functions. * Add the +<<VK_EXT_swapchain_colorspace>>+ extension defining common color spaces.
2017-01-17 20:11:25 -08:00
# Copyright (c) 2013-2017 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.
import os,re,sys
from generator import *
# PyOutputGenerator - subclass of OutputGenerator.
# Generates Python data structures describing API names and relationships.
# Similar to DocOutputGenerator, but writes a single file.
#
# ---- methods ----
# PyOutputGenerator(errFile, warnFile, diagFile) - args as for
# OutputGenerator. Defines additional internal state.
# ---- methods overriding base class ----
# beginFile(genOpts)
# endFile()
# genType(typeinfo,name)
# genStruct(typeinfo,name)
# genGroup(groupinfo,name)
# genEnum(enuminfo, name)
# genCmd(cmdinfo)
class PyOutputGenerator(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)
#
def beginFile(self, genOpts):
OutputGenerator.beginFile(self, genOpts)
#
# Dictionaries are keyed by the name of the entity (e.g.
# self.structs is keyed by structure names). Values are
# the names of related entities (e.g. structs contain
# a list of type names of members, enums contain a list
# of enumerants belong to the enumerated type, etc.), or
# just None if there are no directly related entities.
#
# Collect the mappings, then emit the Python script in endFile
self.basetypes = {}
self.consts = {}
self.enums = {}
self.flags = {}
self.funcpointers = {}
self.protos = {}
self.structs = {}
self.handles = {}
self.defines = {}
# Dictionary containing the type of a type name
# (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
dicts = [ [ self.basetypes, 'basetypes' ],
[ self.consts, 'consts' ],
[ self.enums, 'enums' ],
[ self.flags, 'flags' ],
[ self.funcpointers, 'funcpointers' ],
[ self.protos, 'protos' ],
[ self.structs, 'structs' ],
[ self.handles, 'handles' ],
[ self.defines, 'defines' ],
[ self.typeCategory, 'typeCategory' ] ]
for (dict, name) in dicts:
write(name + ' = {}', file=self.outFile)
for key in sorted(dict.keys()):
write(name + '[' + enquote(key) + '] = ', dict[key], file=self.outFile)
# Dictionary containing the relationships of a type
# (e.g. a dictionary with each related type as keys).
write('mapDict = {}', file=self.outFile)
# Could just print(self.mapDict), but prefer something human-readable
for baseType in sorted(self.mapDict.keys()):
write('mapDict[' + enquote(baseType) + '] = ', self.mapDict[baseType], file=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,
# 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)):
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()):
baseDict = {}
self.mapDict[baseType] = baseDict
else:
baseDict = self.mapDict[baseType]
if (not refType in self.mapDict.keys()):
refDict = {}
self.mapDict[refType] = refDict
else:
refDict = self.mapDict[refType]
baseDict[refType] = None
refDict[baseType] = None
#
# Type generation
# For 'struct' or 'union' types, defer to genStruct() to
# add to the dictionary.
# For 'bitmask' types, add the type name to the 'flags' dictionary,
# with the value being the corresponding 'enums' name defining
# the acceptable flag bits.
# For 'enum' types, add the type name to the 'enums' dictionary,
# with the value being '@STOPHERE@' (because this case seems
# never to happen).
# For 'funcpointer' types, add the type name to the 'funcpointers'
# dictionary.
# For 'handle' and 'define' types, add the handle or #define name
# to the 'struct' dictionary, because that's how the spec sources
# tag these types even though they aren't structs.
def genType(self, typeinfo, name):
OutputGenerator.genType(self, typeinfo, name)
typeElem = typeinfo.elem
# If the type is a struct type, traverse the imbedded <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'):
self.genStruct(typeinfo, name)
else:
# Extract the type name
# (from self.genOpts). Copy other text through unchanged.
# If the resulting text is an empty string, don't emit it.
count = len(noneStr(typeElem.text))
for elem in typeElem:
count += len(noneStr(elem.text)) + len(noneStr(elem.tail))
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):
self.addMapping(name, requiredEnum)
elif (category == 'enum'):
# This case does not seem to come up. It nominally would
# result from
# <type name="VkSomething" 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'):
self.funcpointers[name] = None
elif (category == 'handle'):
self.handles[name] = None
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)):
self.basetypes[name] = None
self.addName(self.typeCategory, name, 'basetype')
else:
Change log for July 22, 2016 Vulkan 1.0.22 spec update: * Bump API patch number and header version number to 22 for this update. Github Issues: * Translate the subpass self-dependency language into concrete validity statements, and added a validity statement about the restrictions on layout parameters (public issue 267). * Add validity requirement that slink:VkAttachmentDescription::pname:finalLayout and slink:VkAttachmentReference::pname:layout must not be ename:VK_IMAGE_LAYOUT_UNDEFINED or ename:VK_IMAGE_LAYOUT_PREINITIALIZED (public issue 268). * Clarify that slink:VkSubpassDescription::pname:pResolveAttachments layouts are used. Make language consistent with other attachment arrays (public issue 270). * Changed 64-bit definition for dname:VK_DEFINE_NON_DISPATCHABLE_HANDLE to work for x32 platform in +vk.xml+ and the resulting +vulkan.h+ (public issue 282). * Add missing error return code for flink:vkEnumerateInstanceExtensionProperties and flink:vkEnumerateDeviceExtensionProperties (public issue 285) * Fix several cases of stext::VkStructName.memberName markup to stext::VkStructName::pname:memberName, to match other usage in the spec, and describe this markup in the style guide (public issue 286). * Modified validity language generation script to avoid redundant common ancestor language if covered by generic parent language, and used `Both' instead of `Each' when appropriate (public issue 288). Internal Issues: * Add language about behavior of flink:vkAllocateDescriptorSets when allocation fails due to fragmentation, a new error ename:VK_ERROR_FRAGMENTED_POOL, and a Note explaining the situation (internal issue 309). * For the features of code:PointSize, code:ClipDistance, and code:CullDistance, the SPIR-V capability is required to be declared on use (read or write) rather than on decoration (internal issue 359). * Have desktop versions of GLSL respect precision qualification (code:mediump and code:lowp) when compiling for Vulkan. These will get translated to SPIR-V's code:RelaxedPrecision decoration as they do with OpenGL ES versions of GLSL (ESSL). The default precision of all types is code:highp when using a desktop version (internal issue 360). * Add validity statement for slink:VkImageCreateInfo specifying that multisampled images must be two-dimensional, optimally tiled, and with a single mipmap level (internal issue 369). * Add validity statements to slink:VkImageViewCreateInfo disallowing creation of images or image views with no supported features. Made some slink:VkImageViewCreateInfo validity statements more precise and consistent. Added a Note to the <<features,features>> chapter about formats with no features (internal issue 371). * Remove +manpages+ from default build targets. Nroff outputs containing imbedded latexmath will not render properly. Fixing this is a lot of work for limited use cases (internal issue 401). Other Commits: * Fix flink:vkRenderPassBeginInfo::pname:clearValueCount validity statement to be based on attachment indices rather than the number of cleared attachments (Vulkan-LoaderAndValidationLayers/issues/601). * Convert registry documentation from LaTeX to asciidoc source and rename from +src/spec/readme.tex+ to +src/spec/registry.txt+. * Fix lack of Oxford commas in validity language. * Lots of cleanup of generator scripts and Makefiles to move extension list for generator into the script arguments instead of the body of genvk.py, and express better dependencies between XML, scripts, and generated files.
2016-07-23 03:15:48 -07:00
self.logMsg('diag', 'PyOutputGenerator::genType: unprocessed type:', name, 'category:', category)
else:
Change log for July 22, 2016 Vulkan 1.0.22 spec update: * Bump API patch number and header version number to 22 for this update. Github Issues: * Translate the subpass self-dependency language into concrete validity statements, and added a validity statement about the restrictions on layout parameters (public issue 267). * Add validity requirement that slink:VkAttachmentDescription::pname:finalLayout and slink:VkAttachmentReference::pname:layout must not be ename:VK_IMAGE_LAYOUT_UNDEFINED or ename:VK_IMAGE_LAYOUT_PREINITIALIZED (public issue 268). * Clarify that slink:VkSubpassDescription::pname:pResolveAttachments layouts are used. Make language consistent with other attachment arrays (public issue 270). * Changed 64-bit definition for dname:VK_DEFINE_NON_DISPATCHABLE_HANDLE to work for x32 platform in +vk.xml+ and the resulting +vulkan.h+ (public issue 282). * Add missing error return code for flink:vkEnumerateInstanceExtensionProperties and flink:vkEnumerateDeviceExtensionProperties (public issue 285) * Fix several cases of stext::VkStructName.memberName markup to stext::VkStructName::pname:memberName, to match other usage in the spec, and describe this markup in the style guide (public issue 286). * Modified validity language generation script to avoid redundant common ancestor language if covered by generic parent language, and used `Both' instead of `Each' when appropriate (public issue 288). Internal Issues: * Add language about behavior of flink:vkAllocateDescriptorSets when allocation fails due to fragmentation, a new error ename:VK_ERROR_FRAGMENTED_POOL, and a Note explaining the situation (internal issue 309). * For the features of code:PointSize, code:ClipDistance, and code:CullDistance, the SPIR-V capability is required to be declared on use (read or write) rather than on decoration (internal issue 359). * Have desktop versions of GLSL respect precision qualification (code:mediump and code:lowp) when compiling for Vulkan. These will get translated to SPIR-V's code:RelaxedPrecision decoration as they do with OpenGL ES versions of GLSL (ESSL). The default precision of all types is code:highp when using a desktop version (internal issue 360). * Add validity statement for slink:VkImageCreateInfo specifying that multisampled images must be two-dimensional, optimally tiled, and with a single mipmap level (internal issue 369). * Add validity statements to slink:VkImageViewCreateInfo disallowing creation of images or image views with no supported features. Made some slink:VkImageViewCreateInfo validity statements more precise and consistent. Added a Note to the <<features,features>> chapter about formats with no features (internal issue 371). * Remove +manpages+ from default build targets. Nroff outputs containing imbedded latexmath will not render properly. Fixing this is a lot of work for limited use cases (internal issue 401). Other Commits: * Fix flink:vkRenderPassBeginInfo::pname:clearValueCount validity statement to be based on attachment indices rather than the number of cleared attachments (Vulkan-LoaderAndValidationLayers/issues/601). * Convert registry documentation from LaTeX to asciidoc source and rename from +src/spec/readme.tex+ to +src/spec/registry.txt+. * Fix lack of Oxford commas in validity language. * Lots of cleanup of generator scripts and Makefiles to move extension list for generator into the script arguments instead of the body of genvk.py, and express better dependencies between XML, scripts, and generated files.
2016-07-23 03:15:48 -07:00
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
# value being an ordered list of the struct member names.
def genStruct(self, typeinfo, typeName):
OutputGenerator.genStruct(self, typeinfo, typeName)
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)
#
# Group (e.g. C "enum" type) generation.
# These are concatenated together with other types.
#
# Add the enum type name to the 'enums' dictionary, with
# the value being an ordered list of the enumerant names.
# Add each enumerant name to the 'consts' dictionary, with
# the value being the enum type the enumerant is part of.
def genGroup(self, groupinfo, groupName):
OutputGenerator.genGroup(self, groupinfo, groupName)
groupElem = groupinfo.elem
# Loop over the nested 'enum' tags.
enumerants = [elem.get('name') for elem in groupElem.findall('enum')]
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
# value being None to indicate that the constant isn't
# an enumeration value.
def genEnum(self, enuminfo, name):
OutputGenerator.genEnum(self, enuminfo, name)
# Add a typeCategory{} entry for the category of this type.
self.addName(self.typeCategory, name, 'consts')
self.consts[name] = None
#
# Command generation
#
# Add the command name to the 'protos' dictionary, with the
# value being an ordered list of the parameter names.
def genCmd(self, cmdinfo, name):
OutputGenerator.genCmd(self, cmdinfo, name)
# Add a typeCategory{} entry for the category of this type.
self.addName(self.typeCategory, name, 'protos')
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)