Vulkan-Docs/src/spec/extensionStubSource.py

333 lines
13 KiB
Python
Raw Normal View History

Change log for November 11, 2016 Vulkan 1.0.33 spec update: * Bump API patch number and header version number to 33 for this update. Github Issues: * Added implicit external synchronization parameters to vkBegin/EndCommandBuffer, and fixed missing command pool host synchronization from per-command lists (public issue 398). * Started using git tags including the spec release number, such as 'v1.0.32-core', instead of tags including the date of release, such as 'v1.0-core-20161025' (public issue 405). Internal Issues: * Add validity constraint for slink:VkImportMemoryWin32HandleInfoNV::pname:handle (internal issue #480). * Add scripts to compare two Vulkan HTML specifications, derived from W3 htmldiff service (internal issue 525). * Relax requirement that memoryTypeBits can't depend on format, to allow it to differ only for depth/stencil formats (internal issue 544). * Add a new generator script to create a simple extension loader for Vulkan based on +vk.xml+ (internal issue 558). * Add the overlooked requirement that buffer and image memory alignment requirements must be a power of two in the <<resources-association,Resource Memory Association>> section (internal issue 569). Other Issues: * Add a naming rule to the style guide for members of extension structures defining array lengths which are the same as array lengths of the core structure they are chained from. * Add a new generator to create a simple extension loader in +src/ext_loader/vulkan_ext.[ch]+ from +vk.xml+. This code can be included in your project, and is expected to be packaged in the Vulkan SDK provided by LunarG in the future.
2016-11-12 11:23:34 +00:00
#!/usr/bin/python3 -i
#
# Copyright (c) 2013-2016 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 *
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
Change log for November 11, 2016 Vulkan 1.0.33 spec update: * Bump API patch number and header version number to 33 for this update. Github Issues: * Added implicit external synchronization parameters to vkBegin/EndCommandBuffer, and fixed missing command pool host synchronization from per-command lists (public issue 398). * Started using git tags including the spec release number, such as 'v1.0.32-core', instead of tags including the date of release, such as 'v1.0-core-20161025' (public issue 405). Internal Issues: * Add validity constraint for slink:VkImportMemoryWin32HandleInfoNV::pname:handle (internal issue #480). * Add scripts to compare two Vulkan HTML specifications, derived from W3 htmldiff service (internal issue 525). * Relax requirement that memoryTypeBits can't depend on format, to allow it to differ only for depth/stencil formats (internal issue 544). * Add a new generator script to create a simple extension loader for Vulkan based on +vk.xml+ (internal issue 558). * Add the overlooked requirement that buffer and image memory alignment requirements must be a power of two in the <<resources-association,Resource Memory Association>> section (internal issue 569). Other Issues: * Add a naming rule to the style guide for members of extension structures defining array lengths which are the same as array lengths of the core structure they are chained from. * Add a new generator to create a simple extension loader in +src/ext_loader/vulkan_ext.[ch]+ from +vk.xml+. This code can be included in your project, and is expected to be packaged in the Vulkan SDK provided by LunarG in the future.
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')
Change log for November 11, 2016 Vulkan 1.0.33 spec update: * Bump API patch number and header version number to 33 for this update. Github Issues: * Added implicit external synchronization parameters to vkBegin/EndCommandBuffer, and fixed missing command pool host synchronization from per-command lists (public issue 398). * Started using git tags including the spec release number, such as 'v1.0.32-core', instead of tags including the date of release, such as 'v1.0-core-20161025' (public issue 405). Internal Issues: * Add validity constraint for slink:VkImportMemoryWin32HandleInfoNV::pname:handle (internal issue #480). * Add scripts to compare two Vulkan HTML specifications, derived from W3 htmldiff service (internal issue 525). * Relax requirement that memoryTypeBits can't depend on format, to allow it to differ only for depth/stencil formats (internal issue 544). * Add a new generator script to create a simple extension loader for Vulkan based on +vk.xml+ (internal issue 558). * Add the overlooked requirement that buffer and image memory alignment requirements must be a power of two in the <<resources-association,Resource Memory Association>> section (internal issue 569). Other Issues: * Add a naming rule to the style guide for members of extension structures defining array lengths which are the same as array lengths of the core structure they are chained from. * Add a new generator to create a simple extension loader in +src/ext_loader/vulkan_ext.[ch]+ from +vk.xml+. This code can be included in your project, and is expected to be packaged in the Vulkan SDK provided by LunarG in the future.
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.
stubDecl = ''
for elem in proto:
text = noneStr(elem.text)
tail = noneStr(elem.tail)
if (elem.tag == 'name'):
name = self.makeProtoName(text, tail)
stubDecl += name
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