2016-11-12 11:23:34 +00:00
|
|
|
#!/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-18 04:11:25 +00:00
|
|
|
# Copyright (c) 2013-2017 The Khronos Group Inc.
|
2016-11-12 11:23:34 +00:00
|
|
|
#
|
|
|
|
# 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 *
|
|
|
|
|
|
|
|
doc = """
|
|
|
|
/*
|
|
|
|
** This is a simple extension loader which provides the implementations for the
|
|
|
|
** extension prototypes declared in vulkan header. It supports loading extensions either
|
|
|
|
** for a single instance or a single device. Multiple instances are not yet supported.
|
|
|
|
**
|
|
|
|
** To use the loader add vulkan_ext.c to your solution and include <vulkan/vulkan_ext.h>.
|
|
|
|
**
|
|
|
|
** If your application is using a single instance, but multiple devices callParam
|
|
|
|
**
|
|
|
|
** vkExtInitInstance(instance);
|
|
|
|
**
|
|
|
|
** after initializing the instance. This way the extension loader will use the loaders
|
|
|
|
** trampoline functions to call the correct driver for each call. This method is safe
|
|
|
|
** if your application might use more than one device at the cost of one additional
|
|
|
|
** indirection, the dispatch table of each dispatchable object.
|
|
|
|
**
|
|
|
|
** If your application uses only a single device it's better to use
|
|
|
|
**
|
|
|
|
** vkExtInitDevice(device);
|
|
|
|
**
|
|
|
|
** once the device has been initialized. This will resolve the function pointers
|
|
|
|
** upfront and thus removes one indirection for each call into the driver. This *can*
|
|
|
|
** result in slightly more performance for calling overhead limited cases.
|
|
|
|
*/
|
|
|
|
"""
|
|
|
|
|
|
|
|
# StubExtGeneratorOptions - subclass of GeneratorOptions.
|
|
|
|
#
|
|
|
|
# Adds options used by COutputGenerator objects during C language header
|
|
|
|
# generation.
|
|
|
|
#
|
|
|
|
# Additional members
|
|
|
|
# prefixText - list of strings to prefix generated header with
|
|
|
|
# (usually a copyright statement + calling convention macros).
|
|
|
|
# alignFuncParam - if nonzero and parameters are being put on a
|
|
|
|
# separate line, align parameter names at the specified column
|
|
|
|
class StubExtGeneratorOptions(GeneratorOptions):
|
|
|
|
"""Represents options during C interface generation for headers"""
|
|
|
|
def __init__(self,
|
|
|
|
filename = None,
|
|
|
|
directory = '.',
|
|
|
|
apiname = None,
|
|
|
|
profile = None,
|
|
|
|
versions = '.*',
|
|
|
|
emitversions = '.*',
|
|
|
|
defaultExtensions = None,
|
|
|
|
addExtensions = None,
|
|
|
|
removeExtensions = None,
|
|
|
|
sortProcedure = regSortFeatures,
|
|
|
|
prefixText = "",
|
|
|
|
alignFuncParam = 0):
|
|
|
|
GeneratorOptions.__init__(self, filename, directory, apiname, profile,
|
|
|
|
versions, emitversions, defaultExtensions,
|
|
|
|
addExtensions, removeExtensions, sortProcedure)
|
|
|
|
self.prefixText = prefixText
|
|
|
|
self.alignFuncParam = alignFuncParam
|
|
|
|
|
|
|
|
# ExtensionStubSourceOutputGenerator - subclass of OutputGenerator.
|
|
|
|
# Generates C-language extension wrapper interface sources.
|
|
|
|
#
|
|
|
|
# ---- methods ----
|
|
|
|
# ExtensionStubSourceOutputGenerator(errFile, warnFile, diagFile) - args as for
|
|
|
|
# OutputGenerator. Defines additional internal state.
|
|
|
|
# ---- methods overriding base class ----
|
|
|
|
# beginFile(genOpts)
|
|
|
|
# endFile()
|
|
|
|
# beginFeature(interface, emit)
|
|
|
|
# endFeature()
|
|
|
|
# genType(typeinfo,name)
|
|
|
|
# genStruct(typeinfo,name)
|
|
|
|
# genGroup(groupinfo,name)
|
|
|
|
# genEnum(enuminfo, name)
|
|
|
|
# genCmd(cmdinfo)
|
|
|
|
class ExtensionStubSourceOutputGenerator(OutputGenerator):
|
|
|
|
"""Generate specified API interfaces in a specific style, such as a C header"""
|
|
|
|
# This is an ordered list of sections in the header file.
|
|
|
|
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)
|
|
|
|
#
|
|
|
|
def beginFile(self, genOpts):
|
|
|
|
OutputGenerator.beginFile(self, genOpts)
|
|
|
|
# C-specific
|
|
|
|
#
|
|
|
|
# Multiple inclusion protection & C++ wrappers.
|
|
|
|
|
Change log for November 25, 2016 Vulkan 1.0.35 spec update:
* Bump API patch number and header version number to 35 for this update.
Github Issues:
* Document in the <<memory-device-hostaccess,Host Access>> section that
mapping and unmapping does not invalidate or flush the mapped memory
(public issues 27, 126).
* Redefine the entire <<synchronization>> chapter in terms of consistent
and well defined terminology, that's called out at the start of the
chapter. This terminology is applied equally to all synchronization
types, including subpass dependencies, submissions, and much of the
implicit ordering stuff dotted around the spec. Key terms are laid out
in the <<synchronization-dependencies,Execution and Memory
Dependencies>> section at the top of the rewritten chapter (public
issues 128, 131, 132, 217, 299, 300, 302, 306, 322, 346, 347, 371, 407).
* Specify order of submission for batches in the
<<vkQueueSubmit,vkQueueSubmit>> and
<<vkQueueBindSparse,vkQueueBindSparse>> commands (public issue 371).
* Add valid usage statements to each of the WSI extension sections
indicating that the WSI-specific structure parameters must be valid, and
remove automatically generated valid usage statements now covered by the
manual sections (public issue 383).
* Clarify render pass compatibility for flink:vkCmdExecuteCommands (public
issue 390).
Internal Issues:
* Update +vk.xml+ to make previously explicit valid usage statements for
<<vkDebugReportMessageEXT,vkDebugReportMessageEXT>> implicit instead
(internal issue 553).
* Add valid usage statement for slink:VkCreateImageInfo preventing
creation of 1D sparse images (internal issue 573).
* Fix Python scripts to always read/write files in utf-8 encoding, and a
logic error in reflib.py which could cause a fatal error for
malstructured asciidoc (internal issues 578, 586).
2016-11-26 10:33:44 +00:00
|
|
|
# Internal state - accumulators for function pointers and function
|
|
|
|
# pointer initializatoin
|
2016-11-12 11:23:34 +00:00
|
|
|
self.pointers = [];
|
|
|
|
self.pointerInitializersInstance = [];
|
|
|
|
self.pointerInitializersDevice = [];
|
|
|
|
|
|
|
|
#
|
|
|
|
# Write header protection
|
Change log for November 25, 2016 Vulkan 1.0.35 spec update:
* Bump API patch number and header version number to 35 for this update.
Github Issues:
* Document in the <<memory-device-hostaccess,Host Access>> section that
mapping and unmapping does not invalidate or flush the mapped memory
(public issues 27, 126).
* Redefine the entire <<synchronization>> chapter in terms of consistent
and well defined terminology, that's called out at the start of the
chapter. This terminology is applied equally to all synchronization
types, including subpass dependencies, submissions, and much of the
implicit ordering stuff dotted around the spec. Key terms are laid out
in the <<synchronization-dependencies,Execution and Memory
Dependencies>> section at the top of the rewritten chapter (public
issues 128, 131, 132, 217, 299, 300, 302, 306, 322, 346, 347, 371, 407).
* Specify order of submission for batches in the
<<vkQueueSubmit,vkQueueSubmit>> and
<<vkQueueBindSparse,vkQueueBindSparse>> commands (public issue 371).
* Add valid usage statements to each of the WSI extension sections
indicating that the WSI-specific structure parameters must be valid, and
remove automatically generated valid usage statements now covered by the
manual sections (public issue 383).
* Clarify render pass compatibility for flink:vkCmdExecuteCommands (public
issue 390).
Internal Issues:
* Update +vk.xml+ to make previously explicit valid usage statements for
<<vkDebugReportMessageEXT,vkDebugReportMessageEXT>> implicit instead
(internal issue 553).
* Add valid usage statement for slink:VkCreateImageInfo preventing
creation of 1D sparse images (internal issue 573).
* Fix Python scripts to always read/write files in utf-8 encoding, and a
logic error in reflib.py which could cause a fatal error for
malstructured asciidoc (internal issues 578, 586).
2016-11-26 10:33:44 +00:00
|
|
|
filename = self.genOpts.directory + '/' + 'vulkan_ext.h'
|
|
|
|
self.outFileHeader = open(filename, 'w', encoding='utf-8')
|
2016-11-12 11:23:34 +00:00
|
|
|
|
|
|
|
write('#ifndef VULKAN_EXT_H', file=self.outFileHeader)
|
|
|
|
write('#define VULKAN_EXT_H', file=self.outFileHeader)
|
|
|
|
write('', file=self.outFileHeader)
|
|
|
|
write('#ifdef __cplusplus', file=self.outFileHeader)
|
|
|
|
write('extern "C" {', file=self.outFileHeader)
|
|
|
|
write('#endif', file=self.outFileHeader)
|
|
|
|
|
|
|
|
#
|
|
|
|
# User-supplied prefix text, if any (list of strings)
|
|
|
|
if (genOpts.prefixText):
|
|
|
|
for s in genOpts.prefixText:
|
|
|
|
write(s, file=self.outFile)
|
|
|
|
write(s, file=self.outFileHeader)
|
|
|
|
|
|
|
|
write(doc, file=self.outFileHeader)
|
|
|
|
|
|
|
|
write('#include <vulkan/vulkan.h>', file=self.outFile)
|
|
|
|
self.newline()
|
|
|
|
|
|
|
|
write('#include <vulkan/vulkan.h>', file=self.outFileHeader)
|
|
|
|
write('', file=self.outFileHeader)
|
|
|
|
|
|
|
|
write('void vkExtInitInstance(VkInstance instance);', file=self.outFileHeader)
|
|
|
|
write('void vkExtInitDevice(VkDevice device);', file=self.outFileHeader)
|
|
|
|
write('', file=self.outFileHeader)
|
|
|
|
|
|
|
|
def endFile(self):
|
|
|
|
for pointer in self.pointers:
|
|
|
|
write(pointer, file=self.outFile)
|
|
|
|
|
|
|
|
self.newline()
|
|
|
|
|
|
|
|
write('void vkExtInitInstance(VkInstance instance)\n{', file=self.outFile)
|
|
|
|
for pointerInitializer in self.pointerInitializersInstance:
|
|
|
|
write(pointerInitializer, file=self.outFile)
|
|
|
|
write('}', file=self.outFile)
|
|
|
|
|
|
|
|
self.newline()
|
|
|
|
|
|
|
|
write('void vkExtInitDevice(VkDevice device)\n{', file=self.outFile)
|
|
|
|
for pointerInitializer in self.pointerInitializersDevice:
|
|
|
|
write(pointerInitializer, file=self.outFile)
|
|
|
|
write('}', file=self.outFile)
|
|
|
|
|
|
|
|
self.newline()
|
|
|
|
|
|
|
|
#Finish header file
|
|
|
|
write('#ifdef __cplusplus', file=self.outFileHeader)
|
|
|
|
write('}', file=self.outFileHeader)
|
|
|
|
write('#endif', file=self.outFileHeader)
|
|
|
|
write('', file=self.outFileHeader)
|
|
|
|
write('#endif', file=self.outFileHeader)
|
|
|
|
self.outFileHeader.close()
|
|
|
|
|
|
|
|
# Finish processing in superclass
|
|
|
|
OutputGenerator.endFile(self)
|
|
|
|
|
|
|
|
def beginFeature(self, interface, emit):
|
|
|
|
# Start processing in superclass
|
|
|
|
OutputGenerator.beginFeature(self, interface, emit)
|
|
|
|
|
|
|
|
# Accumulate function pointers and function pointer initialization
|
|
|
|
self.featurePointers = []
|
|
|
|
self.featurePointerInitializersInstance = []
|
|
|
|
self.featurePointerInitializersDevice = []
|
|
|
|
|
|
|
|
def endFeature(self):
|
|
|
|
# Add feature to global list with protectFeature
|
|
|
|
if (self.emit and self.featurePointers):
|
|
|
|
if (self.genOpts.protectFeature):
|
|
|
|
self.pointers.append('#ifdef ' + self.featureName)
|
|
|
|
self.pointerInitializersInstance.append('#ifdef ' + self.featureName)
|
|
|
|
self.pointerInitializersDevice.append('#ifdef ' + self.featureName)
|
|
|
|
|
|
|
|
if (self.featureExtraProtect != None):
|
|
|
|
self.pointers.append('#ifdef ' + self.featureExtraProtect)
|
|
|
|
self.pointerInitializersInstance.append('#ifndef ' + self.featureName)
|
|
|
|
self.pointerInitializersDevice.append('#ifndef ' + self.featureName)
|
|
|
|
|
|
|
|
self.pointers += self.featurePointers;
|
|
|
|
self.pointerInitializersInstance += self.featurePointerInitializersInstance;
|
|
|
|
self.pointerInitializersDevice += self.featurePointerInitializersDevice;
|
|
|
|
|
|
|
|
if (self.featureExtraProtect != None):
|
|
|
|
self.pointers.append('#endif /* ' + self.featureExtraProtect + ' */')
|
|
|
|
self.pointerInitializersInstance.append('#endif /* ' + self.featureExtraProtect + ' */')
|
|
|
|
self.pointerInitializersDevice.append('#endif /* ' + self.featureExtraProtect + ' */')
|
|
|
|
if (self.genOpts.protectFeature):
|
|
|
|
self.pointers.append('#endif /* ' + self.featureName + ' */')
|
|
|
|
self.pointerInitializersInstance.append('#endif /* ' + self.featureName + ' */')
|
|
|
|
self.pointerInitializersDevice.append('#endif /* ' + self.featureName + ' */')
|
|
|
|
|
|
|
|
# Finish processing in superclass
|
|
|
|
OutputGenerator.endFeature(self)
|
|
|
|
#
|
|
|
|
# Type generation
|
|
|
|
def genType(self, typeinfo, name):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def genStruct(self, typeinfo, typeName):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def genGroup(self, groupinfo, groupName):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def genEnum(self, enuminfo, name):
|
|
|
|
pass
|
|
|
|
|
|
|
|
#
|
|
|
|
# Command generation
|
|
|
|
def genCmd(self, cmdinfo, name):
|
|
|
|
OutputGenerator.genCmd(self, cmdinfo, name)
|
|
|
|
|
|
|
|
#
|
|
|
|
decls = self.makeStub(cmdinfo.elem)
|
|
|
|
self.featurePointerInitializersInstance.append(decls[0])
|
|
|
|
self.featurePointerInitializersDevice.append(decls[1])
|
|
|
|
self.featurePointers.append(decls[2])
|
|
|
|
|
|
|
|
#
|
|
|
|
# makeStub - return static declaration for function pointer and initialization of function pointer
|
|
|
|
# as a two-element list of strings.
|
|
|
|
# cmd - Element containing a <command> tag
|
|
|
|
def makeStub(self, cmd):
|
|
|
|
"""Generate a stub function pointer <command> Element"""
|
|
|
|
proto = cmd.find('proto')
|
|
|
|
params = cmd.findall('param')
|
|
|
|
name = cmd.find('name')
|
|
|
|
|
|
|
|
# Begin accumulating prototype and typedef strings
|
|
|
|
pfnDecl = 'static '
|
|
|
|
pfnDecl += noneStr(proto.text)
|
|
|
|
|
|
|
|
# Find the name tag and generate the function pointer and function pointer initialization code
|
|
|
|
nameTag = proto.find('name')
|
|
|
|
tail = noneStr(nameTag.tail)
|
|
|
|
returnType = noneStr(proto.find('type').text)
|
|
|
|
|
|
|
|
type = self.makeFunctionPointerType(nameTag.text, tail)
|
|
|
|
|
|
|
|
# For each child element, if it's a <name> wrap in appropriate
|
|
|
|
# declaration. Otherwise append its contents and tail con#tents.
|
2017-09-21 15:08:00 +00:00
|
|
|
stubDecl = ''
|
2016-11-12 11:23:34 +00:00
|
|
|
for elem in proto:
|
|
|
|
text = noneStr(elem.text)
|
|
|
|
tail = noneStr(elem.tail)
|
|
|
|
if (elem.tag == 'name'):
|
2017-09-21 15:08:00 +00:00
|
|
|
name = self.makeProtoName(text, tail)
|
|
|
|
stubDecl += name
|
2016-11-12 11:23:34 +00:00
|
|
|
else:
|
|
|
|
stubDecl += text + tail
|
|
|
|
|
|
|
|
pfnName = self.makeFunctionPointerName(nameTag.text, noneStr(tail));
|
|
|
|
pfnDecl += type + ' ' + pfnName + ';'
|
|
|
|
|
|
|
|
# Now generate the stub function
|
|
|
|
pfnDecl += '\n'
|
|
|
|
|
|
|
|
# Now add the parameter declaration list, which is identical
|
|
|
|
# for prototypes and typedefs. Concatenate all the text from
|
|
|
|
# a <param> node without the tags. No tree walking required
|
|
|
|
# since all tags are ignored.
|
|
|
|
n = len(params)
|
|
|
|
paramdecl = '(\n'
|
|
|
|
|
|
|
|
pfnCall = '\n{\n ' + ('return ', '')[returnType == 'void'] + pfnName + '(\n'
|
|
|
|
# Indented parameters
|
|
|
|
if n > 0:
|
|
|
|
indentCallParam = '(\n'
|
|
|
|
indentdecl = '(\n'
|
|
|
|
for i in range(0,n):
|
|
|
|
callParam = ''
|
|
|
|
|
|
|
|
paramdecl += self.makeCParamDecl(params[i], self.genOpts.alignFuncParam)
|
|
|
|
pfnCall += self.makeCCallParam(params[i], self.genOpts.alignFuncParam)
|
|
|
|
if (i < n - 1):
|
|
|
|
paramdecl += ',\n'
|
|
|
|
pfnCall += ',\n'
|
|
|
|
else:
|
|
|
|
paramdecl += ')'
|
|
|
|
pfnCall += '\n );\n'
|
|
|
|
indentdecl += paramdecl
|
|
|
|
indentCallParam += pfnCall
|
|
|
|
else:
|
|
|
|
indentdecl = '(void);'
|
|
|
|
|
|
|
|
pfnCall += '}\n'
|
|
|
|
|
|
|
|
featureInstance = ' ' + pfnName + ' = ('+type+')vkGetInstanceProcAddr(instance, "' + name + '");'
|
|
|
|
featureDevice = ' ' + pfnName + ' = ('+type+')vkGetDeviceProcAddr(device, "' + name + '");'
|
|
|
|
return [featureInstance, featureDevice , pfnDecl + stubDecl + paramdecl + pfnCall]
|
|
|
|
|
|
|
|
# Return function pointer type for given function
|
|
|
|
def makeFunctionPointerType(self, name, tail):
|
|
|
|
return 'PFN_' + name + tail
|
|
|
|
|
|
|
|
# Return name of static variable which stores the function pointer for the given function
|
|
|
|
def makeFunctionPointerName(self, name, tail):
|
|
|
|
return '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).
|
|
|
|
# param - Element (<param> or <member>) to format
|
|
|
|
# aligncol - if non-zero, attempt to align the nested <name> element
|
|
|
|
# at this column
|
|
|
|
def makeCCallParam(self, param, aligncol):
|
|
|
|
return ' ' + param.find('name').text
|
|
|
|
|