mirror of
https://github.com/status-im/Vulkan-Docs.git
synced 2025-01-23 12:49:27 +00:00
476e3f422d
* 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)
338 lines
13 KiB
Python
338 lines
13 KiB
Python
#!/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.
|
|
|
|
import os,re,sys
|
|
from generator import *
|
|
|
|
doc = """
|
|
/*
|
|
** This target is no longer maintained and supported.
|
|
** See README.adoc for discussion.
|
|
**
|
|
** 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,
|
|
emitExtensions = None,
|
|
sortProcedure = regSortFeatures,
|
|
prefixText = "",
|
|
alignFuncParam = 0):
|
|
GeneratorOptions.__init__(self, filename, directory, apiname, profile,
|
|
versions, emitversions, defaultExtensions,
|
|
addExtensions, removeExtensions,
|
|
emitExtensions, 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
|
|
filename = self.genOpts.directory + '/' + 'vulkan_ext.h'
|
|
self.outFileHeader = open(filename, 'w', encoding='utf-8')
|
|
|
|
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_core.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, alias):
|
|
pass
|
|
|
|
def genStruct(self, typeinfo, typeName, alias):
|
|
pass
|
|
|
|
def genGroup(self, groupinfo, groupName, alias):
|
|
pass
|
|
|
|
def genEnum(self, enuminfo, name, alias):
|
|
pass
|
|
|
|
#
|
|
# Command generation
|
|
def genCmd(self, cmdinfo, name, alias):
|
|
OutputGenerator.genCmd(self, cmdinfo, name, alias)
|
|
|
|
#
|
|
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
|
|
|