mirror of
https://github.com/status-im/Vulkan-Docs.git
synced 2025-02-20 01:58:06 +00:00
* 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.
331 lines
13 KiB
Python
331 lines
13 KiB
Python
#!/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.
|
|
|
|
# Internal state - accumulators for function pointers and function pointer initializatoin
|
|
self.pointers = [];
|
|
self.pointerInitializersInstance = [];
|
|
self.pointerInitializersDevice = [];
|
|
|
|
#
|
|
# Write header protection
|
|
self.outFileHeader = open(self.genOpts.directory + '/' + 'vulkan_ext.h', 'w')
|
|
|
|
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
|
|
|